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