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