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