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