vcom.c revision 34956cc3
1/*
2 * Copyright (c) 2016 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#include <unistd.h>
16#include <stdio.h>
17#include <signal.h>
18#include <dlfcn.h>
19#include <pthread.h>
20#include <time.h>
21
22#include <stdarg.h>
23
24#include <libvcl-ldpreload/vcom_socket_wrapper.h>
25#include <libvcl-ldpreload/vcom.h>
26#include <sys/time.h>
27
28#include <uri/vppcom.h>
29#include <libvcl-ldpreload/vcom_socket.h>
30
31
32
33/* GCC have printf type attribute check. */
34#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
35#define PRINTF_ATTRIBUTE(a,b)                       \
36    __attribute__ ((__format__ (__printf__, a, b)))
37#else
38#define PRINTF_ATTRIBUTE(a,b)
39#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
40
41#define HAVE_CONSTRUCTOR_ATTRIBUTE
42#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
43#define CONSTRUCTOR_ATTRIBUTE                       \
44    __attribute__ ((constructor))
45#else
46#define CONSTRUCTOR_ATTRIBUTE
47#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
48
49#define HAVE_DESTRUCTOR_ATTRIBUTE
50#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
51#define DESTRUCTOR_ATTRIBUTE                        \
52    __attribute__ ((destructor))
53#else
54#define DESTRUCTOR_ATTRIBUTE
55#endif
56
57#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE
58#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
59#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE           \
60    __attribute__((no_sanitize_address))
61#else
62#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
63#endif
64
65
66
67
68
69
70#define VCOM_SOCKET_FD_MAX  0x10000
71
72static char vcom_app_name[MAX_VCOM_APP_NAME];
73
74/*
75 * RETURN:  0 on success or -1 on error.
76 * */
77int
78vcom_set_app_name (char *__app_name)
79{
80  return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d",
81                   __app_name, getpid ()) < 0 ? -1 : 0;
82}
83
84static char *
85vcom_get_app_name ()
86{
87  if (vcom_app_name[0] == '\0')
88    {
89      snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ());
90    }
91  return vcom_app_name;
92}
93
94/*
95 * 1 if init, 0 otherwise
96 */
97static int is_vcom_init;
98
99/*
100 * TBD: Make it thread safe
101 */
102
103/*
104 * constructor function called before main is called
105 * RETURN: 0 on success -1 on failure
106 * */
107static inline int
108vcom_init ()
109{
110  pid_t pid = getpid ();
111
112  if (!is_vcom_init)
113    {
114      if (vppcom_app_create (vcom_get_app_name ()) != 0)
115        {
116          printf ("\n[%d] vcom_init...failed!\n", pid);
117          if (VCOM_DEBUG > 0)
118            fprintf (stderr,
119                     "[%d] vcom_init: vppcom_app_create failed!\n", pid);
120          return -1;
121        }
122      if (vcom_socket_main_init () != 0)
123        {
124          printf ("\n[%d] vcom_init...failed!\n", pid);
125          if (VCOM_DEBUG > 0)
126            fprintf (stderr,
127                     "[%d] vcom_init: vcom_socket_main_init failed!\n", pid);
128          return -1;
129        }
130
131      is_vcom_init = 1;
132      printf ("\n[%d] vcom_init...done!\n", pid);
133    }
134  return 0;
135}
136
137static inline void
138vcom_destroy (void)
139{
140  pid_t pid = getpid ();
141
142  if (is_vcom_init)
143    {
144      vcom_socket_main_destroy ();
145      vppcom_app_destroy ();
146      is_vcom_init = 0;
147      fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid);
148    }
149}
150
151static inline int
152is_vcom_socket_fd (int fd)
153{
154  return vcom_socket_is_vcom_fd (fd);
155}
156
157static inline int
158is_vcom_epfd (int epfd)
159{
160  return vcom_socket_is_vcom_epfd (epfd);
161}
162
163
164/*
165 *
166 * Generic glibc fd api
167 *
168 */
169
170/* Close the file descriptor FD.
171
172   This function is a cancellation point and therefore
173   not marked with __THROW.  */
174/*
175 * PRE:     is_vcom_socket_fd(__fd) == 1
176 * RETURN:  0 on success and -1 for errors.
177 * */
178int
179vcom_close (int __fd)
180{
181  if (vcom_init () != 0)
182    {
183      return -1;
184    }
185
186  if (vcom_socket_close (__fd) != 0)
187    {
188      return -1;
189    }
190
191  return 0;
192}
193
194/*
195 * RETURN:  0 on success, or -1 on error
196 */
197int
198close (int __fd)
199{
200  int rv;
201  pid_t pid = getpid ();
202
203  if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd))
204    {
205      if (VCOM_DEBUG > 0)
206        vcom_socket_main_show ();
207      rv = vcom_close (__fd);
208      if (VCOM_DEBUG > 0)
209        fprintf (stderr, "[%d] close: " "'%04d'='%04d'\n", pid, rv, __fd);
210      if (VCOM_DEBUG > 0)
211        vcom_socket_main_show ();
212      if (rv != 0)
213        {
214          errno = -rv;
215          return -1;
216        }
217      return 0;
218    }
219  return libc_close (__fd);
220}
221
222/* Read NBYTES into BUF from FD.  Return the
223   number read, -1 for errors or 0 for EOF.
224
225   This function is a cancellation point and therefore
226   not marked with __THROW.  */
227ssize_t
228vcom_read (int __fd, void *__buf, size_t __nbytes)
229{
230  if (vcom_init () != 0)
231    {
232      return -1;
233    }
234
235  return vcom_socket_read (__fd, __buf, __nbytes);
236}
237
238ssize_t
239read (int __fd, void *__buf, size_t __nbytes)
240{
241  ssize_t size = 0;
242  pid_t pid = getpid ();
243  pthread_t tid = pthread_self ();
244
245  if (is_vcom_socket_fd (__fd))
246    {
247      if (VCOM_DEBUG > 0)
248        fprintf (stderr,
249                 "[%d][%lu (0x%lx)] read:1 "
250                 "'%04d'='%04d', '%p', '%04d'\n",
251                 pid, (unsigned long) tid, (unsigned long) tid,
252                 (int) size, __fd, __buf, (int) __nbytes);
253      size = vcom_read (__fd, __buf, __nbytes);
254      if (VCOM_DEBUG > 0)
255        fprintf (stderr,
256                 "[%d][%lu (0x%lx)] read:2 "
257                 "'%04d'='%04d', '%p', '%04d'\n",
258                 pid, (unsigned long) tid, (unsigned long) tid,
259                 (int) size, __fd, __buf, (int) __nbytes);
260      if (size < 0)
261        {
262          errno = -size;
263          return -1;
264        }
265      return size;
266    }
267  return libc_read (__fd, __buf, __nbytes);
268}
269
270/* Write N bytes of BUF to FD.  Return the number written, or -1.
271
272   This function is a cancellation point and therefore
273   not marked with __THROW.  */
274ssize_t
275vcom_write (int __fd, const void *__buf, size_t __n)
276{
277  if (vcom_init () != 0)
278    {
279      return -1;
280    }
281
282  return vcom_socket_write (__fd, (void *) __buf, __n);
283}
284
285ssize_t
286write (int __fd, const void *__buf, size_t __n)
287{
288  ssize_t size = 0;
289  pid_t pid = getpid ();
290  pthread_t tid = pthread_self ();
291
292  if (is_vcom_socket_fd (__fd))
293    {
294      if (VCOM_DEBUG > 0)
295        fprintf (stderr,
296                 "[%d][%lu (0x%lx)] write:1 "
297                 "'%04d'='%04d', '%p', '%04d'\n",
298                 pid, (unsigned long) tid, (unsigned long) tid,
299                 (int) size, __fd, __buf, (int) __n);
300      size = vcom_write (__fd, __buf, __n);
301      if (VCOM_DEBUG > 0)
302        fprintf (stderr,
303                 "[%d][%lu (0x%lx)] write:2 "
304                 "'%04d'='%04d', '%p', '%04d'\n",
305                 pid, (unsigned long) tid, (unsigned long) tid,
306                 (int) size, __fd, __buf, (int) __n);
307      if (size < 0)
308        {
309          errno = -size;
310          return -1;
311        }
312      return size;
313    }
314  return libc_write (__fd, __buf, __n);
315}
316
317/* Do the file control operation described by CMD on FD.
318   The remaining arguments are interpreted depending on CMD.
319
320   This function is a cancellation point and therefore
321   not marked with __THROW.  */
322int
323vcom_fcntl_va (int __fd, int __cmd, va_list __ap)
324{
325  if (vcom_init () != 0)
326    {
327      return -1;
328    }
329
330  return vcom_socket_fcntl_va (__fd, __cmd, __ap);
331}
332
333int
334vcom_fcntl (int __fd, int __cmd, ...)
335{
336  int rv = -1;
337  va_list ap;
338
339  if (is_vcom_socket_fd (__fd))
340    {
341      va_start (ap, __cmd);
342      rv = vcom_fcntl_va (__fd, __cmd, ap);
343      va_end (ap);
344    }
345  return rv;
346}
347
348int
349fcntl (int __fd, int __cmd, ...)
350{
351  int rv;
352  va_list ap;
353  pid_t pid = getpid ();
354
355  va_start (ap, __cmd);
356  if (is_vcom_socket_fd (__fd))
357    {
358      rv = vcom_fcntl_va (__fd, __cmd, ap);
359      if (VCOM_DEBUG > 0)
360        fprintf (stderr,
361                 "[%d] fcntl: "
362                 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd);
363      if (rv < 0)
364        {
365          errno = -rv;
366          rv = -1;
367        }
368      goto out;
369    }
370  rv = libc_vfcntl (__fd, __cmd, ap);
371
372out:
373  va_end (ap);
374  return rv;
375}
376
377/*
378 * Check the first NFDS descriptors each in READFDS (if not NULL) for
379 *  read readiness, in WRITEFDS (if not NULL) for write readiness,
380 *  and in EXCEPTFDS (if not NULL) for exceptional conditions.
381 *  If TIMEOUT is not NULL, time out after waiting the interval
382 *  specified therein.  Returns the number of ready descriptors,
383 *  or -1 for errors.
384 *
385 * This function is a cancellation point and therefore not marked
386 * with __THROW.
387 * */
388
389/*
390 * clear all vcom FDs from fd_sets __readfds, __writefds and
391 * __exceptfds and update the new nfds
392 *
393 * new nfds is the highest-numbered file descriptor
394 * in any of the three sets, plus 1
395 *
396 * Return the number of file descriptors contained in the
397 * three descriptor sets. ie. the total number of the bits
398 * that are set in  __readfds, __writefds and __exceptfds
399 */
400static inline int
401vcom_fd_clear (int __nfds,
402               int *__new_nfds,
403               fd_set * __restrict __readfds,
404               fd_set * __restrict __writefds,
405               fd_set * __restrict __exceptfds)
406{
407  int fd;
408  /* invalid max_fd is -1 */
409  int max_fd = -1;
410  int nfd = 0;
411
412
413  /* clear all vcom fd from the sets */
414  for (fd = 0; fd < __nfds; fd++)
415    {
416
417      /* clear vcom fd from set */
418      /*
419       * F fd set
420       */
421#define _(F)                                    \
422      if ((F) && FD_ISSET (fd, (F)))            \
423        {                                       \
424          if (is_vcom_socket_fd (fd))           \
425            {                                   \
426              FD_CLR (fd, (F));                 \
427            }                                   \
428        }
429
430
431      _(__readfds);
432      _(__writefds);
433      _(__exceptfds);
434#undef _
435    }
436
437  /*
438   *  compute nfd and __new_nfds
439   */
440  for (fd = 0; fd < __nfds; fd++)
441    {
442
443      /*
444       * F fd set
445       */
446#define _(F)                                    \
447      if ((F) && FD_ISSET (fd, (F)))            \
448        {                                       \
449          if (fd > max_fd)                      \
450            {                                   \
451              max_fd = fd;                      \
452            }                                   \
453          ++nfd;                                \
454        }
455
456
457      _(__readfds);
458      _(__writefds);
459      _(__exceptfds);
460#undef _
461    }
462
463  *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
464  return nfd;
465}
466
467/*
468 * Return the number of file descriptors contained in the
469 * three descriptor sets. ie. the total number of the bits
470 * that are set in  __readfds, __writefds and __exceptfds
471 */
472static inline int
473vcom_fd_set (int __nfds,
474             /* dest */
475             int *__new_nfds,
476             fd_set * __restrict __readfds,
477             fd_set * __restrict __writefds, fd_set * __restrict __exceptfds,
478             /* src */
479             fd_set * __restrict __saved_readfds,
480             fd_set * __restrict __saved_writefds,
481             fd_set * __restrict __saved_exceptfds)
482{
483  int fd;
484  /* invalid max_fd is -1 */
485  int max_fd = -1;
486  int nfd = 0;
487
488  for (fd = 0; fd < __nfds; fd++)
489    {
490      /*
491       * F fd set
492       * S saved fd set
493       */
494#define _(S,F)                                  \
495      if ((F) && (S) && FD_ISSET (fd, (S)))     \
496        {                                       \
497          if (is_vcom_socket_fd (fd))           \
498            {                                   \
499              FD_SET (fd, (F));                 \
500            }                                   \
501        }
502
503
504      _(__saved_readfds, __readfds);
505      _(__saved_writefds, __writefds);
506#undef _
507    }
508
509
510  /*
511   *  compute nfd and __new_nfds
512   */
513  for (fd = 0; fd < __nfds; fd++)
514    {
515
516      /*
517       * F fd set
518       */
519#define _(F)                                    \
520      if ((F) && FD_ISSET (fd, (F)))            \
521        {                                       \
522          if (fd > max_fd)                      \
523            {                                   \
524              max_fd = fd;                      \
525            }                                   \
526          ++nfd;                                \
527        }
528
529
530      _(__readfds);
531      _(__writefds);
532      _(__exceptfds);
533#undef _
534    }
535
536  *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
537  return nfd;
538}
539
540/*
541 * split select sets(src) into
542 * vcom sets(dest1) and libc sets(dest2)
543 */
544static inline void
545vcom_fd_set_split (
546                    /* src, select sets */
547                    int nfds,
548                    fd_set * __restrict readfds,
549                    fd_set * __restrict writefds,
550                    fd_set * __restrict exceptfds,
551                    /* dest1, vcom sets */
552                    int *vcom_nfds,
553                    fd_set * __restrict vcom_readfds,
554                    fd_set * __restrict vcom_writefds,
555                    fd_set * __restrict vcom_exceptfds, int *vcom_nfd,
556                    /* dest2, libc sets */
557                    int *libc_nfds,
558                    fd_set * __restrict libc_readfds,
559                    fd_set * __restrict libc_writefds,
560                    fd_set * __restrict libc_exceptfds, int *libc_nfd)
561{
562  int fd;
563
564  /* vcom */
565  /* invalid max_fd is -1 */
566  int vcom_max_fd = -1;
567  int vcom_nfd2 = 0;
568
569  /* libc */
570  /* invalid max_fd is -1 */
571  int libc_max_fd = -1;
572  int libc_nfd2 = 0;
573
574
575  for (fd = 0; fd < nfds; fd++)
576    {
577      /*
578       * S select fd set
579       * V vcom fd set
580       * L libc fd set
581       */
582#define _(S,V,L)                            \
583      if ((S) && FD_ISSET (fd, (S)))        \
584        {                                   \
585          if (is_vcom_socket_fd (fd))       \
586            {                               \
587              if ((V))                      \
588                {                           \
589                  FD_SET(fd, (V));          \
590                  if (fd > vcom_max_fd)     \
591                    {                       \
592                      vcom_max_fd = fd;     \
593                    }                       \
594                  ++vcom_nfd2;              \
595                }                           \
596            }                               \
597          else                              \
598            {                               \
599              if ((L))                      \
600                {                           \
601                  FD_SET(fd, (L));          \
602                  if (fd > libc_max_fd)     \
603                    {                       \
604                      libc_max_fd = fd;     \
605                    }                       \
606                  ++libc_nfd2;              \
607                }                           \
608            }                               \
609        }
610
611
612      _(readfds, vcom_readfds, libc_readfds);
613      _(writefds, vcom_writefds, libc_writefds);
614      _(exceptfds, vcom_exceptfds, libc_exceptfds);
615#undef _
616    }
617
618  if (vcom_nfds)
619    *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0;
620  if (vcom_nfd)
621    *vcom_nfd = vcom_nfd2;
622  if (libc_nfds)
623    *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0;
624  if (libc_nfd)
625    *libc_nfd = libc_nfd2;
626}
627
628/*
629 * merge vcom sets(src1) and libc sets(src2)
630 * into select sets(dest)
631 */
632static inline void
633vcom_fd_set_merge (
634                    /* dest, select sets */
635                    int *nfds,
636                    fd_set * __restrict readfds,
637                    fd_set * __restrict writefds,
638                    fd_set * __restrict exceptfds, int *nfd,
639                    /* src1, vcom sets */
640                    int vcom_nfds,
641                    fd_set * __restrict vcom_readfds,
642                    fd_set * __restrict vcom_writefds,
643                    fd_set * __restrict vcom_exceptfds, int vcom_nfd,
644                    /* src2, libc sets */
645                    int libc_nfds,
646                    fd_set * __restrict libc_readfds,
647                    fd_set * __restrict libc_writefds,
648                    fd_set * __restrict libc_exceptfds, int libc_nfd)
649{
650  int fd;
651  /* invalid max_fd is -1 */
652  int max_fd = -1;
653  int nfd2 = 0;
654
655
656  /* FD_BIT_OR
657   *
658   * dest |= src at current bit index
659   * update MAX and NFD of dest fd set
660   *
661   *
662   * FS source fd set
663   * FD dest fd set
664   * BI bit index
665   * MAX current max_fd of dest fd sets
666   * NFD current nfd of dest fd sets
667   * N  nfds of source fd set
668   */
669#define FD_BIT_OR(FD,FS,BI,          \
670                  MAX,NFD)           \
671  if ((FS) && (FD) && FD_ISSET ((BI), (FS)))    \
672    {                                           \
673      FD_SET ((BI), (FD));                      \
674      if ((BI) > (MAX))                         \
675        {                                       \
676          (MAX) = (BI);                         \
677        }                                       \
678      ++(NFD);                                  \
679    }
680
681
682  /* FD_RWE_SET_OR */
683  /*
684   * SR,SW,SE source RWE fd sets
685   * DR,DW,DE dest RWE fd sets
686   * BI bit index
687   * NFDS  nfds of source fd sets
688   * MAX current max_fd of dest fd sets
689   * NFD current nfd of dest fd sets
690   */
691#define FD_RWE_SETS_OR(DR,DW,DE,      \
692                      SR,SW,SE,       \
693                      BI,NFDS,        \
694                      MAX,NFD)        \
695  do                                                      \
696    {                                                     \
697      for ((BI) = 0; (BI) < (NFDS); (BI)++)               \
698        {                                                 \
699          FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD));      \
700          FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD));      \
701          FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD));      \
702        }                                                 \
703      }                                                   \
704    while (0);
705
706
707  /* source(vcom) to dest(select) rwe fd sets */
708  FD_RWE_SETS_OR (readfds, writefds, exceptfds,
709                  vcom_readfds, vcom_writefds, vcom_exceptfds,
710                  fd, vcom_nfds, max_fd, nfd2);
711
712  /* source(libc) to dest(select) rwe fd sets */
713  FD_RWE_SETS_OR (readfds, writefds, exceptfds,
714                  libc_readfds, libc_writefds, libc_exceptfds,
715                  fd, libc_nfds, max_fd, nfd2);
716
717#undef FD_RWE_SETS_OR
718#undef FD_BIT_OR
719
720  if (nfds)
721    *nfds = max_fd != -1 ? max_fd + 1 : 0;
722  if (nfd)
723    *nfd = nfd2;
724}
725
726/*
727 * RETURN 1 if fds is NULL or empty. 0 otherwise
728 */
729static inline int
730fd_set_iszero (fd_set * __restrict fds)
731{
732  int fd;
733
734  /* NULL fds */
735  if (!fds)
736    return 1;
737
738  for (fd = 0; fd < FD_SETSIZE; fd++)
739    {
740      if (FD_ISSET (fd, fds))
741        {
742          /* non-empty fds */
743          return 0;
744        }
745    }
746  /* empty fds */
747  return 1;
748}
749
750
751/*
752 * ################
753 * kernel time64.h
754 * ################
755 * */
756typedef long int s64;
757typedef unsigned long int u64;
758
759typedef long long int __s64;
760typedef unsigned long long int __u64;
761
762typedef __s64 time64_t;
763typedef __u64 timeu64_t;
764
765/* Parameters used to convert the timespec values: */
766#define MSEC_PER_SEC    1000L
767#define USEC_PER_MSEC   1000L
768#define NSEC_PER_USEC   1000L
769#define NSEC_PER_MSEC   1000000L
770#define USEC_PER_SEC    1000000L
771#define NSEC_PER_SEC    1000000000L
772#define FSEC_PER_SEC    1000000000000000LL
773
774
775/*
776 * ################
777 * kernel time.h
778 * ################
779 * */
780
781
782#define TIME_T_MAX      (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
783
784static inline int
785timespec_equal (const struct timespec *a, const struct timespec *b)
786{
787  return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
788}
789
790/*
791 * lhs < rhs:  return <0
792 * lhs == rhs: return 0
793 * lhs > rhs:  return >0
794 */
795static inline int
796timespec_compare (const struct timespec *lhs, const struct timespec *rhs)
797{
798  if (lhs->tv_sec < rhs->tv_sec)
799    return -1;
800  if (lhs->tv_sec > rhs->tv_sec)
801    return 1;
802  return lhs->tv_nsec - rhs->tv_nsec;
803}
804
805static inline int
806timeval_compare (const struct timeval *lhs, const struct timeval *rhs)
807{
808  if (lhs->tv_sec < rhs->tv_sec)
809    return -1;
810  if (lhs->tv_sec > rhs->tv_sec)
811    return 1;
812  return lhs->tv_usec - rhs->tv_usec;
813}
814
815extern void set_normalized_timespec (struct timespec *ts, time_t sec,
816                                     s64 nsec);
817
818
819static inline struct timespec
820timespec_add (struct timespec lhs, struct timespec rhs)
821{
822  struct timespec ts_delta;
823  set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec,
824                           lhs.tv_nsec + rhs.tv_nsec);
825  return ts_delta;
826}
827
828/*
829 * sub = lhs - rhs, in normalized form
830 */
831static inline struct timespec
832timespec_sub (struct timespec lhs, struct timespec rhs)
833{
834  struct timespec ts_delta;
835  set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec,
836                           lhs.tv_nsec - rhs.tv_nsec);
837  return ts_delta;
838}
839
840/*
841 * ################
842 * kernel time.c
843 * ################
844 * */
845
846
847/**
848 * set_normalized_timespec - set timespec sec and nsec parts and normalize
849 *
850 * @ts:         pointer to timespec variable to be set
851 * @sec:        seconds to set
852 * @nsec:       nanoseconds to set
853 *
854 * Set seconds and nanoseconds field of a timespec variable and
855 * normalize to the timespec storage format
856 *
857 * Note: The tv_nsec part is always in the range of
858 *      0 <= tv_nsec < NSEC_PER_SEC
859 * For negative values only the tv_sec field is negative !
860 */
861void
862set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec)
863{
864  while (nsec >= NSEC_PER_SEC)
865    {
866      /*
867       * The following asm() prevents the compiler from
868       * optimising this loop into a modulo operation. See
869       * also __iter_div_u64_rem() in include/linux/time.h
870       */
871    asm ("":"+rm" (nsec));
872      nsec -= NSEC_PER_SEC;
873      ++sec;
874    }
875  while (nsec < 0)
876    {
877    asm ("":"+rm" (nsec));
878      nsec += NSEC_PER_SEC;
879      --sec;
880    }
881  ts->tv_sec = sec;
882  ts->tv_nsec = nsec;
883}
884
885#define vcom_timerisvalid(tvp)        (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0))
886
887/* Macros for converting between `struct timeval' and `struct timespec'.  */
888#define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) {                             \
889        (ts)->tv_sec = (tv)->tv_sec;                                    \
890        (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
891}
892#define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) {                             \
893        (tv)->tv_sec = (ts)->tv_sec;                                    \
894        (tv)->tv_usec = (ts)->tv_nsec / 1000;                           \
895}
896
897static inline int
898vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds,
899                  fd_set * __restrict vcom_writefds,
900                  fd_set * __restrict vcom_exceptfds,
901                  struct timeval *__restrict timeout)
902{
903  return vcom_socket_select (vcom_nfds, vcom_readfds,
904                             vcom_writefds, vcom_exceptfds, timeout);
905}
906
907int
908vcom_select (int __nfds, fd_set * __restrict __readfds,
909             fd_set * __restrict __writefds,
910             fd_set * __restrict __exceptfds,
911             struct timeval *__restrict __timeout)
912{
913  int rv;
914  int rv2 = 0;
915  pid_t pid = getpid ();
916
917  int timedout = 0;
918  /* block indefinitely */
919  int no_timeout = 0;
920  int first_clock_gettime_failed = 0;
921  /* timeout value in units of timespec */
922  struct timespec timeout_ts;
923  struct timespec start_time, now, end_time;
924
925  /* select sets attributes - after merge */
926  int new_nfds = 0;
927  int new_nfd = -1;
928
929  /* vcom */
930  int vcom_nfds = 0;
931  fd_set vcom_readfds;
932  fd_set vcom_writefds;
933  fd_set vcom_exceptfds;
934  int vcom_nfd = -1;
935
936  /* libc */
937  int libc_nfds = 0;
938  fd_set libc_readfds;
939  fd_set libc_writefds;
940  fd_set libc_exceptfds;
941  int libc_nfd = -1;
942
943  /* for polling */
944  struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
945
946  /* validate __timeout */
947  if (__timeout)
948    {
949      /* validate tv_sec */
950      /* bogus */
951      if (!vcom_timerisvalid (__timeout))
952        {
953          rv = -EINVAL;
954          goto select_done;
955        }
956
957      /* validate tv_usec */
958      /* TBD: */
959      /* init timeout_ts */
960      VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts);
961      set_normalized_timespec (&timeout_ts,
962                               timeout_ts.tv_sec, timeout_ts.tv_nsec);
963    }
964
965  rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
966  if (rv == -1)
967    {
968      rv = -errno;
969      first_clock_gettime_failed = 1;
970      goto select_done;
971    }
972
973  /* init end_time */
974  if (__timeout)
975    {
976      if (timerisset (__timeout))
977        {
978          end_time = timespec_add (start_time, timeout_ts);
979        }
980      else
981        {
982          /*
983           * if both fields of the timeout structure are zero,
984           * then select returns immediately
985           * */
986          end_time = start_time;
987        }
988    }
989  else
990    {
991      /* block indefinitely */
992      no_timeout = 1;
993    }
994
995
996
997  if (vcom_init () != 0)
998    {
999      rv = -1;
1000      goto select_done;
1001    }
1002
1003  /* validate __nfds */
1004  if (__nfds < 0 || __nfds > FD_SETSIZE)
1005    {
1006      rv = -EINVAL;
1007      goto select_done;
1008    }
1009
1010
1011  /*
1012   * usleep(3) emulation
1013   * */
1014
1015  /* call libc_select() with a finite timeout and
1016   * no file descriptors or empty fd sets and
1017   * zero nfds */
1018  if (__nfds == 0 &&
1019      (!__readfds || fd_set_iszero (__readfds)) &&
1020      (!__writefds || fd_set_iszero (__writefds)) &&
1021      (!__exceptfds || fd_set_iszero (__exceptfds)))
1022    {
1023      if (__timeout)
1024        {
1025          rv = libc_select (__nfds,
1026                            __readfds, __writefds, __exceptfds, __timeout);
1027          if (rv == -1)
1028            rv = -errno;
1029        }
1030      else
1031        {
1032          /* TBD: block indefinitely or return -EINVAL */
1033          rv = -EINVAL;
1034        }
1035      goto select_done;
1036    }
1037
1038  /* init once before the polling loop */
1039
1040  /* zero vcom and libc fd sets */
1041  /*
1042   * S select fd set
1043   * V vcom fd set
1044   * L libc fd set
1045   */
1046#define _(S,V,L)      \
1047  if ((S))            \
1048    {                 \
1049      FD_ZERO ((V));  \
1050      FD_ZERO ((L));  \
1051    }
1052
1053
1054  _(__readfds, &vcom_readfds, &libc_readfds);
1055  _(__writefds, &vcom_writefds, &libc_writefds);
1056  _(__exceptfds, &vcom_exceptfds, &libc_exceptfds);
1057#undef _
1058  new_nfds = 0;
1059  new_nfd = -1;
1060
1061  vcom_nfds = 0;
1062  vcom_nfd = -1;
1063  libc_nfds = 0;
1064  libc_nfd = -1;
1065
1066  vcom_fd_set_split (
1067                      /* src, select sets */
1068                      __nfds, __readfds, __writefds, __exceptfds,
1069                      /* dest1, vcom sets */
1070                      __readfds || __writefds || __exceptfds ?
1071                      &vcom_nfds : NULL,
1072                      __readfds ? &vcom_readfds : NULL,
1073                      __writefds ? &vcom_writefds : NULL,
1074                      __exceptfds ? &vcom_exceptfds : NULL,
1075                      __readfds || __writefds || __exceptfds ?
1076                      &vcom_nfd : NULL,
1077                      /* dest2, libc sets */
1078                      __readfds || __writefds || __exceptfds ?
1079                      &libc_nfds : NULL,
1080                      __readfds ? &libc_readfds : NULL,
1081                      __writefds ? &libc_writefds : NULL,
1082                      __exceptfds ? &libc_exceptfds : NULL,
1083                      __readfds || __writefds || __exceptfds ?
1084                      &libc_nfd : NULL);
1085
1086  /*
1087   * polling loop
1088   * */
1089  do
1090    {
1091      new_nfd = -1;
1092      vcom_nfd = -1;
1093      libc_nfd = -1;
1094
1095      /*
1096       * if both fields of timeval structure are zero,
1097       * vcom_select_impl and libc_select returns immediately.
1098       * useful for polling and ensure fairness among
1099       * file descriptors watched.
1100       */
1101
1102      /* for polling */
1103      tv.tv_sec = 0;
1104      tv.tv_usec = 0;
1105
1106      /* select on vcom fds */
1107      if (vcom_nfds)
1108        {
1109          vcom_nfd = vcom_select_impl (vcom_nfds,
1110                                       __readfds ? &vcom_readfds : NULL,
1111                                       __writefds ? &vcom_writefds : NULL,
1112                                       __exceptfds ? &vcom_exceptfds : NULL,
1113                                       &tv);
1114          if (VCOM_DEBUG > 0)
1115            fprintf (stderr,
1116                     "[%d] select vcom: "
1117                     "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
1118
1119          if (vcom_nfd < 0)
1120            {
1121              rv = vcom_nfd;
1122              goto select_done;
1123            }
1124        }
1125      /* select on libc fds */
1126      if (libc_nfds)
1127        {
1128          libc_nfd = libc_select (libc_nfds,
1129                                  __readfds ? &libc_readfds : NULL,
1130                                  __writefds ? &libc_writefds : NULL,
1131                                  __exceptfds ? &libc_exceptfds : NULL, &tv);
1132          if (VCOM_DEBUG > 0)
1133            fprintf (stderr,
1134                     "[%d] select libc: "
1135                     "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds);
1136
1137          if (libc_nfd < 0)
1138            {
1139              /* tv becomes undefined */
1140              libc_nfd = errno;
1141              rv = libc_nfd;
1142              goto select_done;
1143            }
1144        }
1145
1146      /* check if any file descriptors changed status */
1147      if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0))
1148        {
1149          /* zero the sets before merge and exit */
1150
1151          /*
1152           * F fd set
1153           */
1154#define _(F)                  \
1155          if ((F))            \
1156            {                 \
1157              FD_ZERO ((F));  \
1158            }
1159
1160
1161          _(__readfds);
1162          _(__writefds);
1163          _(__exceptfds);
1164#undef _
1165          new_nfds = 0;
1166          new_nfd = -1;
1167
1168          /*
1169           * on exit, sets are modified in place to indicate which
1170           * file descriptors actually changed status
1171           * */
1172          vcom_fd_set_merge (
1173                              /* dest, select sets */
1174                              __readfds || __writefds || __exceptfds ?
1175                              &new_nfds : NULL,
1176                              __readfds,
1177                              __writefds,
1178                              __exceptfds,
1179                              __readfds || __writefds || __exceptfds ?
1180                              &new_nfd : NULL,
1181                              /* src1, vcom sets */
1182                              vcom_nfds,
1183                              __readfds ? &vcom_readfds : NULL,
1184                              __writefds ? &vcom_writefds : NULL,
1185                              __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd,
1186                              /* src2, libc sets */
1187                              libc_nfds,
1188                              __readfds ? &libc_readfds : NULL,
1189                              __writefds ? &libc_writefds : NULL,
1190                              __exceptfds ? &libc_exceptfds : NULL, libc_nfd);
1191          /*
1192           * return the number of file descriptors contained in the
1193           * three returned sets
1194           * */
1195          rv = 0;
1196          /*
1197           * for documentation
1198           *
1199           * if(vcom_nfd > 0)
1200           *   rv += vcom_nfd;
1201           * if(libc_nfd > 0)
1202           *   rv += libc_nfd;
1203           */
1204
1205          rv = new_nfd == -1 ? 0 : new_nfd;
1206          goto select_done;
1207        }
1208
1209      rv = clock_gettime (CLOCK_MONOTONIC, &now);
1210      if (rv == -1)
1211        {
1212          rv = -errno;
1213          goto select_done;
1214        }
1215    }
1216  while (no_timeout || timespec_compare (&now, &end_time) < 0);
1217
1218  /* timeout expired before anything interesting happened */
1219  timedout = 1;
1220  rv = 0;
1221
1222select_done:
1223  if (VCOM_DEBUG > 0)
1224    fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1225  /*
1226   * modify timeout parameter to reflect the amount of time not slept
1227   * */
1228  if (__timeout)
1229    {
1230      if (vcom_timerisvalid (__timeout))
1231        {
1232          /* timeout expired */
1233          if (timedout)
1234            {
1235              timerclear (__timeout);
1236            }
1237          else if (!first_clock_gettime_failed)
1238            {
1239              rv2 = clock_gettime (CLOCK_MONOTONIC, &now);
1240              if (rv2 == -1)
1241                {
1242                  rv = -errno;
1243                }
1244              else
1245                {
1246                  struct timespec ts_delta;
1247                  ts_delta = timespec_sub (end_time, now);
1248                  VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta);
1249                }
1250            }
1251        }
1252    }
1253  if (VCOM_DEBUG > 0)
1254    fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds);
1255
1256  return rv;
1257}
1258
1259int
1260vcom_select_internal (int __nfds, fd_set * __restrict __readfds,
1261                      fd_set * __restrict __writefds,
1262                      fd_set * __restrict __exceptfds,
1263                      struct timeval *__restrict __timeout)
1264{
1265  int rv;
1266  int new_nfds = 0;
1267  int nfd = 0;
1268  pid_t pid = getpid ();
1269
1270  fd_set saved_readfds;
1271  fd_set saved_writefds;
1272  fd_set saved_exceptfds;
1273
1274  /* validate __nfds */
1275  if (__nfds < 0)
1276    {
1277      errno = EINVAL;
1278      return -1;
1279    }
1280
1281  /* validate __timeout */
1282  if (__timeout)
1283    {
1284      /* validate tv_sec */
1285      /* bogus */
1286      if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0)
1287        {
1288          errno = EINVAL;
1289          return -1;
1290        }
1291
1292      /* validate tv_usec */
1293      /* TBD: */
1294    }
1295
1296  /* init saved_x fds */
1297  if (__readfds)
1298    {
1299      saved_readfds = *__readfds;
1300      /*
1301         memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1302       */
1303    }
1304  else
1305    {
1306      FD_ZERO (&saved_readfds);
1307    }
1308
1309  if (__writefds)
1310    {
1311      saved_writefds = *__writefds;
1312      /*
1313         memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1314       */
1315
1316    }
1317  else
1318    {
1319      FD_ZERO (&saved_writefds);
1320    }
1321
1322  if (__exceptfds)
1323    {
1324      saved_exceptfds = *__exceptfds;
1325      /*
1326         memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1327       */
1328
1329    }
1330  else
1331    {
1332      FD_ZERO (&saved_exceptfds);
1333    }
1334
1335  /* clear vcom fds */
1336  nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1337
1338  /* set to an invalid value */
1339  rv = -2;
1340  /* have kernel fds */
1341  if (new_nfds)
1342    rv = libc_select (new_nfds, __readfds,
1343                      __writefds, __exceptfds, __timeout);
1344
1345  if (new_nfds && rv == -1)
1346    {
1347      /* on error, the file descriptor sets are unmodified */
1348      if (__readfds)
1349        *__readfds = saved_readfds;
1350      if (__writefds)
1351        *__writefds = saved_writefds;
1352      if (__exceptfds)
1353        *__exceptfds = saved_exceptfds;
1354      return rv;
1355    }
1356  else if ((new_nfds && rv != -1) || (rv == -2))
1357    {
1358      /* restore vcom fds */
1359      nfd = vcom_fd_set (__nfds,
1360                         &new_nfds,
1361                         __readfds,
1362                         __writefds,
1363                         __exceptfds,
1364                         &saved_readfds, &saved_writefds, &saved_exceptfds);
1365      rv = nfd;
1366    }
1367
1368  if (VCOM_DEBUG > 0)
1369    fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds);
1370  return rv;
1371}
1372
1373int
1374select (int __nfds, fd_set * __restrict __readfds,
1375        fd_set * __restrict __writefds,
1376        fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout)
1377{
1378  int rv = 0;
1379  pid_t pid = getpid ();
1380
1381  if (VCOM_DEBUG > 0)
1382    fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1383  rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout);
1384  if (VCOM_DEBUG > 0)
1385    fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds);
1386  if (rv < 0)
1387    {
1388      errno = -rv;
1389      return -1;
1390    }
1391  return rv;
1392}
1393
1394#ifdef __USE_XOPEN2K
1395/*
1396 * Same as above only that the TIMEOUT value is given with higher
1397 * resolution and a sigmask which is been set temporarily.  This
1398 * version should be used.
1399 *
1400 * This function is a cancellation point and therefore not marked
1401 * with __THROW.
1402 * */
1403int
1404vcom_pselect (int __nfds, fd_set * __restrict __readfds,
1405              fd_set * __restrict __writefds,
1406              fd_set * __restrict __exceptfds,
1407              const struct timespec *__restrict __timeout,
1408              const __sigset_t * __restrict __sigmask)
1409{
1410  int fd;
1411  int vcom_nfds = 0;
1412
1413  for (fd = 0; fd < __nfds; fd++)
1414    {
1415      if (__readfds && FD_ISSET (fd, __readfds))
1416        {
1417          if (is_vcom_socket_fd (fd))
1418            {
1419              vcom_nfds++;
1420            }
1421        }
1422
1423      if (__writefds && FD_ISSET (fd, __writefds))
1424        {
1425          if (is_vcom_socket_fd (fd))
1426            {
1427              vcom_nfds++;
1428            }
1429        }
1430      if (__exceptfds && FD_ISSET (fd, __exceptfds))
1431        {
1432          if (is_vcom_socket_fd (fd))
1433            {
1434              FD_CLR (fd, __exceptfds);
1435            }
1436        }
1437    }
1438  return vcom_nfds;
1439}
1440
1441int
1442pselect (int __nfds, fd_set * __restrict __readfds,
1443         fd_set * __restrict __writefds,
1444         fd_set * __restrict __exceptfds,
1445         const struct timespec *__restrict __timeout,
1446         const __sigset_t * __restrict __sigmask)
1447{
1448  int rv;
1449  int new_nfds = 0;
1450  int nfd = 0;
1451  pid_t pid = getpid ();
1452
1453  fd_set saved_readfds;
1454  fd_set saved_writefds;
1455  fd_set saved_exceptfds;
1456
1457  /* validate __nfds */
1458  if (__nfds < 0)
1459    {
1460      errno = EINVAL;
1461      return -1;
1462    }
1463
1464  /* validate __timeout */
1465  if (__timeout)
1466    {
1467      /* validate tv_sec */
1468      /* bogus */
1469      if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0)
1470        {
1471          errno = EINVAL;
1472          return -1;
1473        }
1474
1475      /* validate tv_usec */
1476      /* TBD: */
1477    }
1478
1479  /* init saved fds */
1480  if (__readfds)
1481    {
1482      saved_readfds = *__readfds;
1483      /*
1484         memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1485       */
1486    }
1487  else
1488    {
1489      FD_ZERO (&saved_readfds);
1490    }
1491
1492  if (__writefds)
1493    {
1494      saved_writefds = *__writefds;
1495      /*
1496         memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1497       */
1498
1499    }
1500  else
1501    {
1502      FD_ZERO (&saved_writefds);
1503    }
1504
1505  if (__exceptfds)
1506    {
1507      saved_exceptfds = *__exceptfds;
1508      /*
1509         memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1510       */
1511
1512    }
1513  else
1514    {
1515      FD_ZERO (&saved_exceptfds);
1516    }
1517
1518  /* clear vcom fds */
1519  nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1520
1521  /* set to an invalid value */
1522  rv = -2;
1523  if (new_nfds)
1524    rv = libc_pselect (new_nfds,
1525                       __readfds,
1526                       __writefds, __exceptfds, __timeout, __sigmask);
1527
1528  if (new_nfds && rv == -1)
1529    {
1530      /* on error, the file descriptor sets are unmodified */
1531      if (__readfds)
1532        *__readfds = saved_readfds;
1533      if (__writefds)
1534        *__writefds = saved_writefds;
1535      if (__exceptfds)
1536        *__exceptfds = saved_exceptfds;
1537      return rv;
1538    }
1539  else if ((new_nfds && rv != -1) || (rv == -2))
1540    {
1541      /* restore vcom fds */
1542      nfd = vcom_fd_set (__nfds,
1543                         &new_nfds,
1544                         __readfds,
1545                         __writefds,
1546                         __exceptfds,
1547                         &saved_readfds, &saved_writefds, &saved_exceptfds);
1548      rv = nfd;
1549    }
1550
1551  if (VCOM_DEBUG > 0)
1552    fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds);
1553  return rv;
1554}
1555#endif
1556
1557/*
1558 *
1559 * Socket specific glibc api
1560 *
1561 */
1562
1563/* Create a new socket of type TYPE in domain DOMAIN, using
1564 * protocol PROTOCOL.  If PROTOCOL is zero, one is chosen
1565 * automatically. Returns a file descriptor for the new socket,
1566 * or -1 for errors.
1567 * RETURN:  a valid file descriptor for the new socket,
1568 * or -1 for errors.
1569 * */
1570
1571int
1572vcom_socket (int __domain, int __type, int __protocol)
1573{
1574  if (vcom_init () != 0)
1575    {
1576      return -1;
1577    }
1578
1579  return vcom_socket_socket (__domain, __type, __protocol);
1580}
1581
1582int
1583socket (int __domain, int __type, int __protocol)
1584{
1585  int rv;
1586  pid_t pid = getpid ();
1587  pthread_t tid = pthread_self ();
1588
1589  /* handle domains implemented by vpp */
1590  switch (__domain)
1591    {
1592    case AF_INET:
1593    case AF_INET6:
1594      /* handle types implemented by vpp */
1595      switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1596        {
1597        case SOCK_STREAM:
1598        case SOCK_DGRAM:
1599          if (VCOM_DEBUG > 0)
1600            vcom_socket_main_show ();
1601          rv = vcom_socket (__domain, __type, __protocol);
1602          if (VCOM_DEBUG > 0)
1603            fprintf (stderr,
1604                     "[%d][%lu (0x%lx)] socket: "
1605                     "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1606                     pid, (unsigned long) tid, (unsigned long) tid,
1607                     rv, __domain, __type, __protocol);
1608          if (VCOM_DEBUG > 0)
1609            vcom_socket_main_show ();
1610          if (rv < 0)
1611            {
1612              errno = -rv;
1613              return -1;
1614            }
1615          return rv;
1616          break;
1617
1618        default:
1619          goto CALL_GLIBC_SOCKET_API;
1620          break;
1621        }
1622
1623      break;
1624
1625    default:
1626      goto CALL_GLIBC_SOCKET_API;
1627      break;
1628    }
1629
1630CALL_GLIBC_SOCKET_API:
1631  return libc_socket (__domain, __type, __protocol);
1632}
1633
1634/*
1635 * Create two new sockets, of type TYPE in domain DOMAIN and using
1636 * protocol PROTOCOL, which are connected to each other, and put file
1637 * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
1638 * one will be chosen automatically.
1639 * Returns 0 on success, -1 for errors.
1640 * */
1641int
1642vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2])
1643{
1644  if (vcom_init () != 0)
1645    {
1646      return -1;
1647    }
1648
1649  return vcom_socket_socketpair (__domain, __type, __protocol, __fds);
1650}
1651
1652int
1653socketpair (int __domain, int __type, int __protocol, int __fds[2])
1654{
1655  int rv;
1656  pid_t pid = getpid ();
1657
1658  /* handle domains implemented by vpp */
1659  switch (__domain)
1660    {
1661    case AF_INET:
1662    case AF_INET6:
1663      /* handle types implemented by vpp */
1664      switch (__type)
1665        {
1666        case SOCK_STREAM:
1667        case SOCK_DGRAM:
1668          rv = vcom_socketpair (__domain, __type, __protocol, __fds);
1669          if (VCOM_DEBUG > 0)
1670            fprintf (stderr,
1671                     "[%d] socketpair: "
1672                     "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1673                     pid, rv, __domain, __type, __protocol);
1674          if (rv < 0)
1675            {
1676              errno = -rv;
1677              return -1;
1678            }
1679          return 0;
1680          break;
1681
1682        default:
1683          goto CALL_GLIBC_SOCKET_API;
1684          break;
1685        }
1686
1687      break;
1688
1689    default:
1690      goto CALL_GLIBC_SOCKET_API;
1691      break;
1692    }
1693
1694CALL_GLIBC_SOCKET_API:
1695  return libc_socketpair (__domain, __type, __protocol, __fds);
1696}
1697
1698/*
1699 * Give the socket FD the local address ADDR
1700 * (which is LEN bytes long).
1701 * */
1702int
1703vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1704{
1705  int rv;
1706
1707  if (vcom_init () != 0)
1708    {
1709      return -1;
1710    }
1711
1712  /* validate __len */
1713  switch (__addr->sa_family)
1714    {
1715    case AF_INET:
1716      if (__len != sizeof (struct sockaddr_in))
1717        return -EINVAL;
1718      break;
1719    case AF_INET6:
1720      if (__len != sizeof (struct sockaddr_in6))
1721        return -EINVAL;
1722      break;
1723
1724    default:
1725      return -1;
1726      break;
1727    }
1728
1729  /* handle domains implemented by vpp */
1730  switch (__addr->sa_family)
1731    {
1732    case AF_INET:
1733    case AF_INET6:
1734      rv = vcom_socket_bind (__fd, __addr, __len);
1735      return rv;
1736      break;
1737
1738    default:
1739      return -1;
1740      break;
1741    }
1742
1743  return -1;
1744}
1745
1746int
1747bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1748{
1749  int rv;
1750  pid_t pid = getpid ();
1751
1752  if (is_vcom_socket_fd (__fd))
1753    {
1754
1755      rv = vcom_bind (__fd, __addr, __len);
1756      if (VCOM_DEBUG > 0)
1757        fprintf (stderr,
1758                 "[%d] bind: "
1759                 "'%04d'='%04d', '%p', '%04d'\n",
1760                 pid, rv, __fd, __addr, __len);
1761      if (rv != 0)
1762        {
1763          errno = -rv;
1764          return -1;
1765        }
1766      return 0;
1767    }
1768  return libc_bind (__fd, __addr, __len);
1769}
1770
1771/*
1772 * Put the local address of FD into *ADDR and its length in *LEN.
1773 * */
1774int
1775vcom_getsockname (int __fd, __SOCKADDR_ARG __addr,
1776                  socklen_t * __restrict __len)
1777{
1778  if (vcom_init () != 0)
1779    {
1780      return -1;
1781    }
1782
1783  return vcom_socket_getsockname (__fd, __addr, __len);
1784}
1785
1786int
1787getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1788{
1789  int rv;
1790  pid_t pid = getpid ();
1791
1792  if (is_vcom_socket_fd (__fd))
1793    {
1794      rv = vcom_getsockname (__fd, __addr, __len);
1795      if (VCOM_DEBUG > 0)
1796        fprintf (stderr,
1797                 "[%d] getsockname: "
1798                 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1799      if (rv != 0)
1800        {
1801          errno = -rv;
1802          return -1;
1803        }
1804      return 0;
1805    }
1806  return libc_getsockname (__fd, __addr, __len);
1807}
1808
1809/*
1810 * Open a connection on socket FD to peer at ADDR
1811 * (which LEN bytes long). For connectionless socket types, just set
1812 * the default address to send to and the only address from which to
1813 * accept transmissions. Return 0 on success, -1 for errors.
1814 * This function is a cancellation point and therefore not marked
1815 * with __THROW.
1816 * */
1817int
1818vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1819{
1820  int rv = -1;
1821
1822  if (vcom_init () != 0)
1823    {
1824      return -1;
1825    }
1826
1827  /* validate __len */
1828  switch (__addr->sa_family)
1829    {
1830    case AF_INET:
1831      if (__len != INET_ADDRSTRLEN)
1832        return -1;
1833      break;
1834    case AF_INET6:
1835      if (__len != INET6_ADDRSTRLEN)
1836        return -1;
1837      break;
1838
1839    default:
1840      return -1;
1841      break;
1842    }
1843
1844  /* handle domains implemented by vpp */
1845  switch (__addr->sa_family)
1846    {
1847    case AF_INET:
1848    case AF_INET6:
1849      rv = vcom_socket_connect (__fd, __addr, __len);
1850      break;
1851
1852    default:
1853      return -1;
1854      break;
1855    }
1856
1857  return rv;
1858}
1859
1860int
1861connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1862{
1863  int rv;
1864  pid_t pid = getpid ();
1865  pthread_t tid = pthread_self ();
1866
1867  if (is_vcom_socket_fd (__fd))
1868    {
1869      rv = vcom_connect (__fd, __addr, __len);
1870      if (VCOM_DEBUG > 0)
1871        fprintf (stderr,
1872                 "[%d][%lu (0x%lx)] connect: "
1873                 "'%04d'='%04d', '%p', '%04d'\n",
1874                 pid, (unsigned long) tid, (unsigned long) tid,
1875                 rv, __fd, __addr, __len);
1876      if (rv != 0)
1877        {
1878          errno = -rv;
1879          return -1;
1880        }
1881      return 0;
1882    }
1883
1884  return libc_connect (__fd, __addr, __len);
1885}
1886
1887/*
1888 * Put the address of the peer connected to socket FD into *ADDR
1889 * (which is *LEN bytes long), and its actual length into *LEN.
1890 * */
1891int
1892vcom_getpeername (int __fd, __SOCKADDR_ARG __addr,
1893                  socklen_t * __restrict __len)
1894{
1895  if (vcom_init () != 0)
1896    {
1897      return -1;
1898    }
1899
1900  return vcom_socket_getpeername (__fd, __addr, __len);
1901}
1902
1903int
1904getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1905{
1906  int rv;
1907  pid_t pid = getpid ();
1908
1909  if (is_vcom_socket_fd (__fd))
1910    {
1911      rv = vcom_getpeername (__fd, __addr, __len);
1912      if (VCOM_DEBUG > 0)
1913        fprintf (stderr,
1914                 "[%d] getpeername: "
1915                 "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1916      if (rv != 0)
1917        {
1918          errno = -rv;
1919          return -1;
1920        }
1921      return 0;
1922    }
1923  return libc_getpeername (__fd, __addr, __len);
1924}
1925
1926/*
1927 * Send N bytes of BUF to socket FD.  Returns the number sent or -1.
1928 * This function is a cancellation point and therefore not marked
1929 * with __THROW.
1930 * */
1931ssize_t
1932vcom_send (int __fd, const void *__buf, size_t __n, int __flags)
1933{
1934
1935  if (vcom_init () != 0)
1936    {
1937      return -1;
1938    }
1939
1940  return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags);
1941}
1942
1943ssize_t
1944send (int __fd, const void *__buf, size_t __n, int __flags)
1945{
1946  ssize_t size;
1947  pid_t pid = getpid ();
1948
1949  if (is_vcom_socket_fd (__fd))
1950    {
1951      size = vcom_send (__fd, __buf, __n, __flags);
1952      if (VCOM_DEBUG > 0)
1953        fprintf (stderr,
1954                 "[%d] send: "
1955                 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
1956                 pid, (int) size, __fd, __buf, (int) __n, __flags);
1957      if (size < 0)
1958        {
1959          errno = -size;
1960          return -1;
1961        }
1962      return size;
1963    }
1964  return libc_send (__fd, __buf, __n, __flags);
1965}
1966
1967/*
1968 * Read N bytes into BUF from socket FD.
1969 * Returns the number read or -1 for errors.
1970 * This function is a cancellation point and therefore not marked
1971 *  with __THROW.
1972 *  */
1973ssize_t
1974vcom_recv (int __fd, void *__buf, size_t __n, int __flags)
1975{
1976  if (vcom_init () != 0)
1977    {
1978      return -1;
1979    }
1980
1981  return vcom_socket_recv (__fd, __buf, __n, __flags);
1982}
1983
1984ssize_t
1985recv (int __fd, void *__buf, size_t __n, int __flags)
1986{
1987  ssize_t size;
1988  pid_t pid = getpid ();
1989
1990  if (is_vcom_socket_fd (__fd))
1991    {
1992      size = vcom_recv (__fd, __buf, __n, __flags);
1993      if (VCOM_DEBUG > 0)
1994        fprintf (stderr,
1995                 "[%d] recv: "
1996                 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
1997                 pid, (int) size, __fd, __buf, (int) __n, __flags);
1998      if (size < 0)
1999        {
2000          errno = -size;
2001          return -1;
2002        }
2003      return size;
2004    }
2005  return libc_recv (__fd, __buf, __n, __flags);
2006}
2007
2008/*
2009 * Send N bytes of BUF on socket FD to peer at address ADDR (which is
2010 * ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.
2011 * This function is a cancellation point and therefore not marked
2012 * with __THROW.
2013 * */
2014ssize_t
2015vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags,
2016             __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2017{
2018  if (vcom_init () != 0)
2019    {
2020      return -1;
2021    }
2022
2023  return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2024}
2025
2026ssize_t
2027sendto (int __fd, const void *__buf, size_t __n, int __flags,
2028        __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2029{
2030  ssize_t size;
2031  pid_t pid = getpid ();
2032
2033  if (is_vcom_socket_fd (__fd))
2034    {
2035      size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2036      if (VCOM_DEBUG > 0)
2037        fprintf (stderr,
2038                 "[%d] sendto: "
2039                 "'%04d'='%04d', '%p', '%04d', '%04x', "
2040                 "'%p', '%04d'\n",
2041                 pid, (int) size, __fd, __buf, (int) __n, __flags,
2042                 __addr, __addr_len);
2043      if (size < 0)
2044        {
2045          errno = -size;
2046          return -1;
2047        }
2048      return size;
2049    }
2050  return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2051}
2052
2053/*
2054 * Read N bytes into BUF through socket FD.
2055 * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the
2056 * address of the sender, and store the actual size of the address
2057 * in *ADDR_LEN.
2058 * Returns the number of bytes read or -1 for errors.
2059 * This function is a cancellation point and therefore not marked
2060 * with __THROW.
2061 * */
2062ssize_t
2063vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n,
2064               int __flags,
2065               __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2066{
2067  if (vcom_init () != 0)
2068    {
2069      return -1;
2070    }
2071
2072  return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2073}
2074
2075ssize_t
2076recvfrom (int __fd, void *__restrict __buf, size_t __n,
2077          int __flags,
2078          __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2079{
2080  ssize_t size;
2081  pid_t pid = getpid ();
2082
2083  if (is_vcom_socket_fd (__fd))
2084    {
2085      size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2086      if (VCOM_DEBUG > 0)
2087        fprintf (stderr,
2088                 "[%d] recvfrom: "
2089                 "'%04d'='%04d', '%p', '%04d', '%04x', "
2090                 "'%p', '%p'\n",
2091                 pid, (int) size, __fd, __buf, (int) __n, __flags,
2092                 __addr, __addr_len);
2093      if (size < 0)
2094        {
2095          errno = -size;
2096          return -1;
2097        }
2098      return size;
2099    }
2100  return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2101}
2102
2103/*
2104 * Send a message described MESSAGE on socket FD.
2105 * Returns the number of bytes sent, or -1 for errors.
2106 * This function is a cancellation point and therefore not marked
2107 * with __THROW.
2108 * */
2109ssize_t
2110vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags)
2111{
2112  if (vcom_init () != 0)
2113    {
2114      return -1;
2115    }
2116
2117  return vcom_socket_sendmsg (__fd, __message, __flags);
2118}
2119
2120ssize_t
2121sendmsg (int __fd, const struct msghdr * __message, int __flags)
2122{
2123  ssize_t size;
2124  pid_t pid = getpid ();
2125
2126  if (is_vcom_socket_fd (__fd))
2127    {
2128      size = vcom_sendmsg (__fd, __message, __flags);
2129      if (VCOM_DEBUG > 0)
2130        fprintf (stderr,
2131                 "[%d] sendmsg: "
2132                 "'%04d'='%04d', '%p', '%04x'\n",
2133                 pid, (int) size, __fd, __message, __flags);
2134      if (size < 0)
2135        {
2136          errno = -size;
2137          return -1;
2138        }
2139      return size;
2140    }
2141  return libc_sendmsg (__fd, __message, __flags);
2142}
2143
2144#ifdef __USE_GNU
2145/*
2146 * Send a VLEN messages as described by VMESSAGES to socket FD.
2147 * Returns the number of datagrams successfully written
2148 * or -1 for errors.
2149 * This function is a cancellation point and therefore not marked
2150 * with __THROW.
2151 * */
2152int
2153vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages,
2154               unsigned int __vlen, int __flags)
2155{
2156  if (vcom_init () != 0)
2157    {
2158      return -1;
2159    }
2160
2161  return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags);
2162}
2163
2164int
2165sendmmsg (int __fd, struct mmsghdr *__vmessages,
2166          unsigned int __vlen, int __flags)
2167{
2168  ssize_t size;
2169  pid_t pid = getpid ();
2170
2171  if (is_vcom_socket_fd (__fd))
2172    {
2173      size = vcom_sendmmsg (__fd, __message, __vlen, __flags);
2174      if (VCOM_DEBUG > 0)
2175        fprintf (stderr,
2176                 "[%d] sendmmsg: "
2177                 "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2178                 pid, (int) size, __fd, __vmessages, __vlen, __flags);
2179      if (size < 0)
2180        {
2181          errno = -size;
2182          return -1;
2183        }
2184      return size;
2185    }
2186  return libc_sendmmsg (__fd, __message, __vlen, __flags);
2187}
2188
2189#endif
2190
2191/*
2192 * Receive a message as described by MESSAGE from socket FD.
2193 * Returns the number of bytes read or -1 for errors.
2194 * This function is a cancellation point and therefore not marked
2195 * with __THROW.
2196 * */
2197ssize_t
2198vcom_recvmsg (int __fd, struct msghdr * __message, int __flags)
2199{
2200  if (vcom_init () != 0)
2201    {
2202      return -1;
2203    }
2204
2205  return vcom_socket_recvmsg (__fd, __message, __flags);
2206}
2207
2208ssize_t
2209recvmsg (int __fd, struct msghdr * __message, int __flags)
2210{
2211  ssize_t size;
2212  pid_t pid = getpid ();
2213
2214  if (is_vcom_socket_fd (__fd))
2215    {
2216      size = vcom_recvmsg (__fd, __message, __flags);
2217      if (VCOM_DEBUG > 0)
2218        fprintf (stderr,
2219                 "[%d] recvmsg: "
2220                 "'%04d'='%04d', '%p', '%04x'\n",
2221                 pid, (int) size, __fd, __message, __flags);
2222      if (size < 0)
2223        {
2224          errno = -size;
2225          return -1;
2226        }
2227      return size;
2228    }
2229  return libc_recvmsg (__fd, __message, __flags);
2230}
2231
2232#ifdef __USE_GNU
2233/*
2234 * Receive up to VLEN messages as described by VMESSAGES from socket FD.
2235 * Returns the number of messages received or -1 for errors.
2236 * This function is a cancellation point and therefore not marked
2237 * with __THROW.
2238 * */
2239int
2240vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages,
2241               unsigned int __vlen, int __flags, struct timespec *__tmo)
2242{
2243  if (vcom_init () != 0)
2244    {
2245      return -1;
2246    }
2247
2248  return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2249}
2250
2251int
2252recvmmsg (int __fd, struct mmsghdr *__vmessages,
2253          unsigned int __vlen, int __flags, struct timespec *__tmo)
2254{
2255  ssize_t size;
2256  pid_t pid = getpid ();
2257
2258  if (is_vcom_socket_fd (__fd))
2259    {
2260      size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2261      if (VCOM_DEBUG > 0)
2262        fprintf (stderr,
2263                 "[%d] recvmmsg: "
2264                 "'%04d'='%04d', '%p', "
2265                 "'%04d', '%04x', '%p'\n",
2266                 pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo);
2267      if (size < 0)
2268        {
2269          errno = -size;
2270          return -1;
2271        }
2272      return size;
2273    }
2274  return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2275}
2276
2277#endif
2278
2279/*
2280 * Put the current value for socket FD's option OPTNAME
2281 * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long),
2282 * and set *OPTLEN to the value's actual length.
2283 * Returns 0 on success, -1 for errors.
2284 * */
2285int
2286vcom_getsockopt (int __fd, int __level, int __optname,
2287                 void *__restrict __optval, socklen_t * __restrict __optlen)
2288{
2289  if (vcom_init () != 0)
2290    {
2291      return -1;
2292    }
2293
2294  return vcom_socket_getsockopt (__fd, __level, __optname,
2295                                 __optval, __optlen);
2296}
2297
2298int
2299getsockopt (int __fd, int __level, int __optname,
2300            void *__restrict __optval, socklen_t * __restrict __optlen)
2301{
2302  int rv;
2303  pid_t pid = getpid ();
2304
2305  if (is_vcom_socket_fd (__fd))
2306    {
2307      rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen);
2308      if (VCOM_DEBUG > 0)
2309        fprintf (stderr,
2310                 "[%d] getsockopt: "
2311                 "'%04d'='%04d', '%04d', '%04d', "
2312                 "'%p', '%p'\n",
2313                 pid, rv, __fd, __level, __optname, __optval, __optlen);
2314      if (rv != 0)
2315        {
2316          errno = -rv;
2317          return -1;
2318        }
2319      return 0;
2320    }
2321  return libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
2322}
2323
2324/*
2325 * Set socket FD's option OPTNAME at protocol level LEVEL
2326 * to *OPTVAL (which is OPTLEN bytes long).
2327 * Returns 0 on success, -1 for errors.
2328 * */
2329int
2330vcom_setsockopt (int __fd, int __level, int __optname,
2331                 const void *__optval, socklen_t __optlen)
2332{
2333  if (vcom_init () != 0)
2334    {
2335      return -1;
2336    }
2337
2338  return vcom_socket_setsockopt (__fd, __level, __optname,
2339                                 __optval, __optlen);
2340}
2341
2342int
2343setsockopt (int __fd, int __level, int __optname,
2344            const void *__optval, socklen_t __optlen)
2345{
2346  int rv;
2347  pid_t pid = getpid ();
2348
2349  if (is_vcom_socket_fd (__fd))
2350    {
2351      rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen);
2352      if (VCOM_DEBUG > 0)
2353        fprintf (stderr,
2354                 "[%d] setsockopt: "
2355                 "'%04d'='%04d', '%04d', '%04d', "
2356                 "'%p', '%04d'\n",
2357                 pid, rv, __fd, __level, __optname, __optval, __optlen);
2358      if (rv != 0)
2359        {
2360          errno = -rv;
2361          return -1;
2362        }
2363      return 0;
2364    }
2365  return libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2366}
2367
2368/*
2369 * Prepare to accept connections on socket FD.
2370 * N connection requests will be queued before further
2371 * requests are refused.
2372 * Returns 0 on success, -1 for errors.
2373 * */
2374int
2375vcom_listen (int __fd, int __n)
2376{
2377  if (vcom_init () != 0)
2378    {
2379      return -1;
2380    }
2381
2382  return vcom_socket_listen (__fd, __n);
2383}
2384
2385int
2386listen (int __fd, int __n)
2387{
2388  int rv;
2389  pid_t pid = getpid ();
2390
2391  if (is_vcom_socket_fd (__fd))
2392    {
2393      rv = vcom_listen (__fd, __n);
2394      if (VCOM_DEBUG > 0)
2395        fprintf (stderr,
2396                 "[%d] listen: "
2397                 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n);
2398      if (rv != 0)
2399        {
2400          errno = -rv;
2401          return -1;
2402        }
2403      return 0;
2404    }
2405  return libc_listen (__fd, __n);
2406}
2407
2408/*
2409 * Await a connection on socket FD.
2410 * When a connection arrives, open a new socket to communicate
2411 * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address
2412 * of the connecting peer and *ADDR_LEN to the address's actual
2413 * length, and return the new socket's descriptor, or -1 for errors.
2414 * This function is a cancellation point and therefore not marked
2415 * with __THROW.
2416 * */
2417int
2418vcom_accept (int __fd, __SOCKADDR_ARG __addr,
2419             socklen_t * __restrict __addr_len)
2420{
2421
2422  if (vcom_init () != 0)
2423    {
2424      return -1;
2425    }
2426  return vcom_socket_accept (__fd, __addr, __addr_len);
2427}
2428
2429int
2430accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2431{
2432  int rv = -1;
2433  pid_t pid = getpid ();
2434  pthread_t tid = pthread_self ();
2435
2436  if (is_vcom_socket_fd (__fd))
2437    {
2438      if (VCOM_DEBUG > 0)
2439        vcom_socket_main_show ();
2440      if (VCOM_DEBUG > 0)
2441        fprintf (stderr,
2442                 "[%d][%lu (0x%lx)] accept1: "
2443                 "'%04d'='%04d', '%p', '%p'\n",
2444                 pid, (unsigned long) tid, (unsigned long) tid,
2445                 rv, __fd, __addr, __addr_len);
2446      rv = vcom_accept (__fd, __addr, __addr_len);
2447      if (VCOM_DEBUG > 0)
2448        fprintf (stderr,
2449                 "[%d][%lu (0x%lx)] accept2: "
2450                 "'%04d'='%04d', '%p', '%p'\n",
2451                 pid, (unsigned long) tid, (unsigned long) tid,
2452                 rv, __fd, __addr, __addr_len);
2453      if (VCOM_DEBUG > 0)
2454        vcom_socket_main_show ();
2455      if (rv < 0)
2456        {
2457          errno = -rv;
2458          return -1;
2459        }
2460      return rv;
2461    }
2462  return libc_accept (__fd, __addr, __addr_len);
2463}
2464
2465#ifdef __USE_GNU
2466/*
2467 * Similar to 'accept' but takes an additional parameter to specify
2468 * flags.
2469 * This function is a cancellation point and therefore not marked
2470 * with __THROW.
2471 * */
2472int
2473vcom_accept4 (int __fd, __SOCKADDR_ARG __addr,
2474              socklen_t * __restrict __addr_len, int __flags)
2475{
2476
2477  if (vcom_init () != 0)
2478    {
2479      return -1;
2480    }
2481
2482  return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags);
2483}
2484
2485int
2486accept4 (int __fd, __SOCKADDR_ARG __addr,
2487         socklen_t * __restrict __addr_len, int __flags)
2488{
2489  int rv;
2490  pid_t pid = getpid ();
2491
2492  if (is_vcom_socket_fd (__fd))
2493    {
2494      if (VCOM_DEBUG > 0)
2495        vcom_socket_main_show ();
2496      rv = vcom_accept4 (__fd, __addr, __addr_len, __flags);
2497      if (VCOM_DEBUG > 0)
2498        fprintf (stderr,
2499                 "[%d] accept4: "
2500                 "'%04d'='%04d', '%p', '%p', '%04x'\n",
2501                 pid, rv, __fd, __addr, __addr_len, __flags);
2502      if (VCOM_DEBUG > 0)
2503        vcom_socket_main_show ();
2504      if (rv < 0)
2505        {
2506          errno = -rv;
2507          return -1;
2508        }
2509      return rv;
2510    }
2511  return libc_accept4 (__fd, __addr, __addr_len, __flags);
2512}
2513
2514#endif
2515
2516/*
2517 * Shut down all or part of the connection open on socket FD.
2518 * HOW determines what to shut down:
2519 *   SHUT_RD   = No more receptions;
2520 *   SHUT_WR   = No more transmissions;
2521 *   SHUT_RDWR = No more receptions or transmissions.
2522 * Returns 0 on success, -1 for errors.
2523 * */
2524int
2525vcom_shutdown (int __fd, int __how)
2526{
2527  if (vcom_init () != 0)
2528    {
2529      return -1;
2530    }
2531  return vcom_socket_shutdown (__fd, __how);
2532}
2533
2534int
2535shutdown (int __fd, int __how)
2536{
2537  int rv;
2538  pid_t pid = getpid ();
2539
2540  if (is_vcom_socket_fd (__fd))
2541    {
2542      rv = vcom_shutdown (__fd, __how);
2543      if (VCOM_DEBUG > 0)
2544        fprintf (stderr,
2545                 "[%d] shutdown: "
2546                 "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how);
2547      if (rv != 0)
2548        {
2549          errno = -rv;
2550          return -1;
2551        }
2552      return 0;
2553    }
2554  return libc_shutdown (__fd, __how);
2555}
2556
2557int
2558vcom_epoll_create (int __size)
2559{
2560
2561  if (vcom_init () != 0)
2562    {
2563      return -1;
2564    }
2565
2566  if (__size <= 0)
2567    {
2568      return -EINVAL;
2569    }
2570
2571  /* __size argument is ignored "thereafter" */
2572  return vcom_epoll_create1(0);
2573}
2574
2575/*
2576 * __size argument is ignored, but must be greater than zero
2577 */
2578int
2579epoll_create (int __size)
2580{
2581  int rv = 0;
2582
2583  rv = vcom_epoll_create(__size);
2584  if (rv < 0)
2585    {
2586      errno = -rv;
2587      return -1;
2588    }
2589  return rv;
2590}
2591
2592int
2593vcom_epoll_create1 (int __flags)
2594{
2595  if (vcom_init () != 0)
2596    {
2597      return -1;
2598    }
2599
2600  if (__flags < 0)
2601    {
2602      return -EINVAL;
2603    }
2604  if (__flags & ~EPOLL_CLOEXEC)
2605    {
2606      return -EINVAL;
2607    }
2608  /* __flags can be either zero or EPOLL_CLOEXEC */
2609  /* implementation */
2610  return vcom_socket_epoll_create1(__flags);
2611}
2612
2613/*
2614 * __flags can be either zero or EPOLL_CLOEXEC
2615 * */
2616int
2617epoll_create1 (int __flags)
2618{
2619  int rv = 0;
2620
2621  rv = vcom_epoll_create1(__flags);
2622  if (rv < 0)
2623    {
2624      errno = -rv;
2625      return -1;
2626    }
2627  return rv;
2628}
2629
2630int
2631vcom_epoll_ctl (int __epfd, int __op, int __fd,
2632                struct epoll_event *__event)
2633{
2634  if (vcom_init () != 0)
2635    {
2636      return -1;
2637    }
2638
2639  /* implementation */
2640  return vcom_socket_epoll_ctl (__epfd, __op, __fd,
2641                                __event);
2642}
2643
2644static inline int
2645ep_op_has_event (int op)
2646{
2647  return op != EPOLL_CTL_DEL;
2648}
2649
2650int
2651epoll_ctl (int __epfd, int __op, int __fd,
2652           struct epoll_event *__event)
2653{
2654  int rv;
2655  pid_t pid = getpid ();
2656
2657  if ((ep_op_has_event (__op) && !__event))
2658    {
2659      errno = EFAULT;
2660      return -1;
2661    }
2662  if (is_vcom_epfd (__epfd))
2663    {
2664      /* TBD: currently limiting epoll to support only vcom fds */
2665      if (is_vcom_socket_fd (__fd))
2666        {
2667          rv = vcom_epoll_ctl (__epfd, __op, __fd,
2668                               __event);
2669          if (VCOM_DEBUG > 0)
2670            fprintf (stderr,
2671                     "[%d] epoll_ctl: "
2672                     "'%04d'='%04d', '%04d', '%04d'\n", pid, rv, __epfd, __op, __fd);
2673          if (rv != 0)
2674            {
2675              errno = -rv;
2676              return -1;
2677            }
2678          return 0;
2679        }
2680      else
2681        {
2682          /* TBD: currently epoll does not support kernel fds */
2683          errno = EBADF;
2684          return -1;
2685        }
2686    }
2687  else
2688    {
2689      errno = EINVAL;
2690      return -1;
2691    }
2692  return 0;
2693}
2694
2695int
2696vcom_epoll_wait (int __epfd, struct epoll_event *__events,
2697                 int __maxevents, int __timeout)
2698{
2699  if (vcom_init () != 0)
2700    {
2701      return -1;
2702    }
2703
2704  return vcom_epoll_pwait(__epfd, __events,
2705                          __maxevents, __timeout,
2706                          NULL);
2707}
2708
2709int
2710epoll_wait (int __epfd, struct epoll_event *__events,
2711            int __maxevents, int __timeout)
2712{
2713  int rv;
2714  pid_t pid = getpid ();
2715
2716  if (__maxevents <=0 || __maxevents > EP_MAX_EVENTS)
2717    {
2718      errno = EINVAL;
2719      return -1;
2720    }
2721
2722  if (is_vcom_epfd (__epfd))
2723    {
2724      rv = vcom_epoll_wait (__epfd, __events,
2725                            __maxevents, __timeout);
2726      if (VCOM_DEBUG > 0)
2727        fprintf (stderr,
2728                 "[%d] epoll_wait: "
2729                 "'%04d'='%04d', '%p', "
2730                 "'%04d', '%04d'\n",
2731                 pid,
2732                 rv, __epfd, __events,
2733                 __maxevents, __timeout);
2734      if (rv != 0)
2735        {
2736          errno = -rv;
2737          return -1;
2738        }
2739      return 0;
2740    }
2741  else
2742    {
2743      errno = EINVAL;
2744      return -1;
2745    }
2746  return 0;
2747}
2748
2749
2750int
2751vcom_epoll_pwait (int __epfd, struct epoll_event *__events,
2752                  int __maxevents, int __timeout,
2753                  const __sigset_t *__ss)
2754{
2755  if (vcom_init () != 0)
2756    {
2757      return -1;
2758    }
2759
2760  /* implementation */
2761  return vcom_socket_epoll_pwait (__epfd, __events,
2762                                  __maxevents, __timeout,
2763                                  __ss);
2764}
2765
2766int
2767epoll_pwait (int __epfd, struct epoll_event *__events,
2768             int __maxevents, int __timeout,
2769             const __sigset_t *__ss)
2770{
2771  int rv;
2772  pid_t pid = getpid ();
2773
2774  if (__maxevents <=0 || __maxevents > EP_MAX_EVENTS)
2775    {
2776      errno = EINVAL;
2777      return -1;
2778    }
2779
2780  if (is_vcom_epfd (__epfd))
2781    {
2782      rv = vcom_epoll_pwait (__epfd, __events,
2783                             __maxevents, __timeout,
2784                             __ss);
2785      if (VCOM_DEBUG > 0)
2786        fprintf (stderr,
2787                 "[%d] epoll_pwait: "
2788                 "'%04d'='%04d', '%p', "
2789                 "'%04d', '%04d', "
2790                 "'%p'\n",
2791                 pid,
2792                 rv, __epfd, __events,
2793                 __maxevents, __timeout,
2794                 __ss);
2795      if (rv != 0)
2796        {
2797          errno = -rv;
2798          return -1;
2799        }
2800      return 0;
2801    }
2802  else
2803    {
2804      errno = EINVAL;
2805      return -1;
2806    }
2807
2808  return 0;
2809}
2810
2811void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
2812
2813void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
2814
2815void
2816vcom_constructor (void)
2817{
2818  pid_t pid = getpid ();
2819
2820  swrap_constructor ();
2821  if (vcom_init () != 0)
2822    {
2823      printf ("\n[%d] vcom_constructor...failed!\n", pid);
2824    }
2825  else
2826    {
2827      printf ("\n[%d] vcom_constructor...done!\n", pid);
2828    }
2829}
2830
2831/*
2832 * This function is called when the library is unloaded
2833 */
2834void
2835vcom_destructor (void)
2836{
2837  pid_t pid = getpid ();
2838
2839  vcom_destroy ();
2840  swrap_destructor ();
2841  printf ("\n[%d] vcom_destructor...done!\n", pid);
2842}
2843
2844
2845/*
2846 * fd.io coding-style-patch-verification: ON
2847 *
2848 * Local Variables:
2849 * eval: (c-set-style "gnu")
2850 * End:
2851 */
2852