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