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