TAS
TCP Acceleration as an OS Service
interpose.c
1 /*
2  * Copyright 2019 University of Washington, Max Planck Institute for
3  * Software Systems, and The University of Texas at Austin
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #define __USE_GNU
30 #include <dlfcn.h>
31 #include <pthread.h>
32 #include <sys/select.h>
33 #include <sys/syscall.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 
37 #include <utils.h>
38 #include <tas_sockets.h>
39 
40 static inline void ensure_init(void);
41 
42 /* Function pointers to the libc functions */
43 static int (*libc_socket)(int domain, int type, int protocol) = NULL;
44 static int (*libc_close)(int sockfd) = NULL;
45 static int (*libc_shutdown)(int sockfd, int how) = NULL;
46 static int (*libc_bind)(int sockfd, const struct sockaddr *addr,
47  socklen_t addrlen) = NULL;
48 static int (*libc_connect)(int sockfd, const struct sockaddr *addr,
49  socklen_t addrlen) = NULL;
50 static int (*libc_listen)(int sockfd, int backlog) = NULL;
51 static int (*libc_accept4)(int sockfd, struct sockaddr *addr,
52  socklen_t *addrlen, int flags) = NULL;
53 static int (*libc_accept)(int sockfd, struct sockaddr *addr,
54  socklen_t *addrlen) = NULL;
55 static int (*libc_fcntl)(int sockfd, int cmd, ...) = NULL;
56 static int (*libc_fcntl64)(int sockfd, int cmd, ...) = NULL;
57 static int (*libc_getsockopt)(int sockfd, int level, int optname, void *optval,
58  socklen_t *optlen) = NULL;
59 static int (*libc_setsockopt)(int sockfd, int level, int optname,
60  const void *optval, socklen_t optlen) = NULL;
61 static int (*libc_getsockname)(int sockfd, struct sockaddr *addr,
62  socklen_t *addrlen) = NULL;
63 static int (*libc_getpeername)(int sockfd, struct sockaddr *addr,
64  socklen_t *addrlen) = NULL;
65 static ssize_t (*libc_read)(int fd, void *buf, size_t count) = NULL;
66 static ssize_t (*libc_recv)(int sockfd, void *buf, size_t len,
67  int flags) = NULL;
68 static ssize_t (*libc_recvfrom)(int sockfd, void *buf, size_t len, int flags,
69  struct sockaddr *src_addr, socklen_t *addrlen) = NULL;
70 static ssize_t (*libc_recvmsg)(int sockfd, struct msghdr *msg, int flags)
71  = NULL;
72 static ssize_t (*libc_readv)(int sockfd, const struct iovec *iov, int iovcnt)
73  = NULL;
74 static ssize_t (*libc_pread)(int sockfd, void *buf, size_t count, off_t offset)
75  = NULL;
76 static ssize_t (*libc_write)(int fd, const void *buf, size_t count) = NULL;
77 static ssize_t (*libc_send)(int sockfd, const void *buf, size_t len, int flags)
78  = NULL;
79 static ssize_t (*libc_sendto)(int sockfd, const void *buf, size_t len,
80  int flags, const struct sockaddr *dest_addr, socklen_t addrlen) = NULL;
81 static ssize_t (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags)
82  = NULL;
83 static ssize_t (*libc_writev)(int sockfd, const struct iovec *iov, int iovcnt)
84  = NULL;
85 static ssize_t (*libc_pwrite)(int sockfd, const void *buf, size_t count,
86  off_t offset) = NULL;
87 static ssize_t (*libc_sendfile)(int sockfd, int in_fd, off_t *offset,
88  size_t len) = NULL;
89 static long (*libc_syscall)(long num, ...) = NULL;
90 
91 int socket(int domain, int type, int protocol)
92 {
93  ensure_init();
94 
95  /* if not a TCP socket, pass call to libc */
96  if (domain != AF_INET ||
97  (type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != SOCK_STREAM) {
98  return libc_socket(domain, type, protocol);
99  }
100 
101  return tas_socket(domain, type, protocol);
102 }
103 
104 int close(int sockfd)
105 {
106  int ret;
107  ensure_init();
108  if ((ret = tas_close(sockfd)) == -1 && errno == EBADF) {
109  return libc_close(sockfd);
110  }
111  return ret;
112 }
113 
114 int shutdown(int sockfd, int how)
115 {
116  int ret;
117  ensure_init();
118  if ((ret = tas_shutdown(sockfd, how)) == -1 && errno == EBADF) {
119  return libc_shutdown(sockfd, how);
120  }
121  return ret;
122 }
123 
124 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
125 {
126  int ret;
127  ensure_init();
128  if ((ret = tas_bind(sockfd, addr, addrlen)) == -1 && errno == EBADF) {
129  return libc_bind(sockfd, addr, addrlen);
130  }
131  return ret;
132 }
133 
134 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
135 {
136  int ret;
137  ensure_init();
138  if ((ret = tas_connect(sockfd, addr, addrlen)) == -1 && errno == EBADF) {
139  return libc_connect(sockfd, addr, addrlen);
140  }
141  return ret;
142 }
143 
144 int listen(int sockfd, int backlog)
145 {
146  int ret;
147  ensure_init();
148  if ((ret = tas_listen(sockfd, backlog)) == -1 && errno == EBADF) {
149  return libc_listen(sockfd, backlog);
150  }
151  return ret;
152 }
153 
154 int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
155  int flags)
156 {
157  int ret;
158  ensure_init();
159  if ((ret = tas_accept4(sockfd, addr, addrlen, flags)) == -1 &&
160  errno == EBADF)
161  {
162  return libc_accept4(sockfd, addr, addrlen, flags);
163  }
164  return ret;
165 }
166 
167 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
168 {
169  int ret;
170  ensure_init();
171  if ((ret = tas_accept(sockfd, addr, addrlen)) == -1 && errno == EBADF) {
172  return libc_accept(sockfd, addr, addrlen);
173  }
174  return ret;
175 }
176 
177 static int vfcntl(int sockfd, int cmd, va_list val, int is_64)
178 {
179  int ret, arg_i;
180  void *arg_p;
181 
182  /* this is pretty ugly, but unfortunately there is no other way to interpose
183  * on variadic functions and pass along all arguments. */
184  switch (cmd) {
185  /* these take no argument */
186  case F_GETFD:
187  case F_GETFL:
188  case F_GETOWN:
189  case F_GETSIG:
190  case F_GETLEASE:
191  case F_GETPIPE_SZ:
192 #ifdef F_GET_SEALS
193  case F_GET_SEALS:
194 #endif
195  if ((ret = tas_fcntl(sockfd, cmd)) == -1 && errno == EBADF) {
196  if (is_64)
197  ret = libc_fcntl64(sockfd, cmd);
198  else
199  ret = libc_fcntl(sockfd, cmd);
200  }
201  break;
202 
203 
204  /* these take int as an argument */
205  case F_DUPFD:
206  case F_DUPFD_CLOEXEC:
207  case F_SETFD:
208  case F_SETFL:
209  case F_SETOWN:
210  case F_SETSIG:
211  case F_SETLEASE:
212  case F_NOTIFY:
213  case F_SETPIPE_SZ:
214 #ifdef F_ADD_SEALS
215  case F_ADD_SEALS:
216 #endif
217  arg_i = va_arg(val, int);
218  if ((ret = tas_fcntl(sockfd, cmd, arg_i)) == -1 && errno == EBADF) {
219  if (is_64)
220  ret = libc_fcntl64(sockfd, cmd, arg_i);
221  else
222  ret = libc_fcntl(sockfd, cmd, arg_i);
223  }
224  break;
225 
226 
227  /* these take a pointer as an argument */
228  case F_SETLK:
229  case F_SETLKW:
230  case F_GETLK:
231  case F_OFD_SETLK:
232  case F_OFD_SETLKW:
233  case F_OFD_GETLK:
234  case F_GETOWN_EX:
235  case F_SETOWN_EX:
236 #ifdef F_GET_RW_HINT
237  case F_GET_RW_HINT:
238  case F_SET_RW_HINT:
239 #endif
240 #ifdef F_GET_FILE_RW_HINT
241  case F_GET_FILE_RW_HINT:
242  case F_SET_FILE_RW_HINT:
243 #endif
244  arg_p = va_arg(val, void *);
245  if ((ret = tas_fcntl(sockfd, cmd, arg_p)) == -1 && errno == EBADF) {
246  if (is_64)
247  ret = libc_fcntl64(sockfd, cmd, arg_p);
248  else
249  ret = libc_fcntl(sockfd, cmd, arg_p);
250  }
251  break;
252 
253  /* unsupported */
254  default:
255  fprintf(stderr, "tas fcntl wrapper: unsupported cmd (%u)\n", cmd);
256  errno = EINVAL;
257  ret = -1;
258  break;
259  }
260 
261  return ret;
262 
263 }
264 
265 int fcntl(int sockfd, int cmd, ...)
266 {
267  int ret;
268  va_list val;
269  ensure_init();
270 
271  va_start(val, cmd);
272  ret = vfcntl(sockfd, cmd, val, 0);
273  va_end(val);
274 
275  return ret;
276 }
277 
278 int fcntl64(int sockfd, int cmd, ...)
279 {
280  int ret;
281  va_list val;
282  ensure_init();
283 
284  va_start(val, cmd);
285  ret = vfcntl(sockfd, cmd, val, 1);
286  va_end(val);
287 
288  return ret;
289 }
290 
291 int getsockopt(int sockfd, int level, int optname, void *optval,
292  socklen_t *optlen)
293 {
294  int ret;
295  ensure_init();
296  if ((ret = tas_getsockopt(sockfd, level, optname, optval, optlen)) == -1 &&
297  errno == EBADF)
298  {
299  return libc_getsockopt(sockfd, level, optname, optval, optlen);
300  }
301  return ret;
302 }
303 
304 int setsockopt(int sockfd, int level, int optname, const void *optval,
305  socklen_t optlen)
306 {
307  int ret;
308  ensure_init();
309  if ((ret = tas_setsockopt(sockfd, level, optname, optval, optlen)) == -1 &&
310  errno == EBADF)
311  {
312  return libc_setsockopt(sockfd, level, optname, optval, optlen);
313  }
314  return ret;
315 }
316 
317 int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
318 {
319  int ret;
320  ensure_init();
321  if ((ret = tas_getsockname(sockfd, addr, addrlen)) == -1 && errno == EBADF) {
322  return libc_getsockname(sockfd, addr, addrlen);
323  }
324  return ret;
325 }
326 
327 int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
328 {
329  int ret;
330  ensure_init();
331  if ((ret = tas_getpeername(sockfd, addr, addrlen)) == -1 && errno == EBADF) {
332  return libc_getpeername(sockfd, addr, addrlen);
333  }
334  return ret;
335 }
336 
337 ssize_t read(int sockfd, void *buf, size_t count)
338 {
339  ssize_t ret;
340  ensure_init();
341  if ((ret = tas_read(sockfd, buf, count)) == -1 && errno == EBADF) {
342  return libc_read(sockfd, buf, count);
343  }
344  return ret;
345 }
346 
347 ssize_t recv(int sockfd, void *buf, size_t len, int flags)
348 {
349  ssize_t ret;
350  ensure_init();
351  if ((ret = tas_recv(sockfd, buf, len, flags)) == -1 && errno == EBADF) {
352  return libc_recv(sockfd, buf, len, flags);
353  }
354  return ret;
355 }
356 
357 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
358  struct sockaddr *src_addr, socklen_t *addrlen)
359 {
360  ssize_t ret;
361  ensure_init();
362  if ((ret = tas_recvfrom(sockfd, buf, len, flags, src_addr, addrlen)) == -1 &&
363  errno == EBADF)
364  {
365  return libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
366  }
367  return ret;
368 }
369 
370 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
371 {
372  ssize_t ret;
373  ensure_init();
374  if ((ret = tas_recvmsg(sockfd, msg, flags)) == -1 && errno == EBADF) {
375  return libc_recvmsg(sockfd, msg, flags);
376  }
377  return ret;
378 }
379 
380 ssize_t readv(int sockfd, const struct iovec *iov, int iovcnt)
381 {
382  ssize_t ret;
383  ensure_init();
384  if ((ret = tas_readv(sockfd, iov, iovcnt)) == -1 && errno == EBADF) {
385  return libc_readv(sockfd, iov, iovcnt);
386  }
387  return ret;
388 }
389 
390 ssize_t pread(int sockfd, void *buf, size_t count, off_t offset)
391 {
392  ssize_t ret;
393  ensure_init();
394  if ((ret = tas_pread(sockfd, buf, count, offset)) == -1 && errno == EBADF) {
395  return libc_pread(sockfd, buf, count, offset);
396  }
397  return ret;
398 }
399 
400 ssize_t write(int sockfd, const void *buf, size_t count)
401 {
402  ssize_t ret;
403  ensure_init();
404  if ((ret = tas_write(sockfd, buf, count)) == -1 && errno == EBADF) {
405  return libc_write(sockfd, buf, count);
406  }
407  return ret;
408 }
409 
410 ssize_t send(int sockfd, const void *buf, size_t len, int flags)
411 {
412  ssize_t ret;
413  ensure_init();
414  if ((ret = tas_send(sockfd, buf, len, flags)) == -1 && errno == EBADF) {
415  return libc_send(sockfd, buf, len, flags);
416  }
417  return ret;
418 }
419 
420 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
421  const struct sockaddr *dest_addr, socklen_t addrlen)
422 {
423  ssize_t ret;
424  ensure_init();
425  if ((ret = tas_sendto(sockfd, buf, len, flags, dest_addr, addrlen)) == -1 &&
426  errno == EBADF)
427  {
428  return libc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
429  }
430  return ret;
431 }
432 
433 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
434 {
435  ssize_t ret;
436  ensure_init();
437  if ((ret = tas_sendmsg(sockfd, msg, flags)) == -1 && errno == EBADF) {
438  return libc_sendmsg(sockfd, msg, flags);
439  }
440  return ret;
441 }
442 
443 ssize_t writev(int sockfd, const struct iovec *iov, int iovcnt)
444 {
445  ssize_t ret;
446  ensure_init();
447  if ((ret = tas_writev(sockfd, iov, iovcnt)) == -1 && errno == EBADF) {
448  return libc_writev(sockfd, iov, iovcnt);
449  }
450  return ret;
451 }
452 
453 ssize_t pwrite(int sockfd, const void *buf, size_t count, off_t offset)
454 {
455  ssize_t ret;
456  ensure_init();
457  if ((ret = tas_pwrite(sockfd, buf, count, offset)) == -1 && errno == EBADF) {
458  return libc_pwrite(sockfd, buf, count, offset);
459  }
460  return ret;
461 }
462 
463 ssize_t sendfile(int sockfd, int in_fd, off_t *offset, size_t len)
464 {
465  ssize_t ret;
466  ensure_init();
467  if ((ret = tas_sendfile(sockfd, in_fd, offset, len)) == -1 && errno == EBADF) {
468  return libc_sendfile(sockfd, in_fd, offset, len);
469  }
470  return ret;
471 }
472 
473 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
474  struct timeval *timeout)
475 {
476  ensure_init();
477  return tas_select(nfds, readfds, writefds, exceptfds, timeout);
478 }
479 
480 int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
481  const struct timespec *timeout, const sigset_t *sigmask)
482 {
483  ensure_init();
484  return tas_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
485 }
486 
487 int epoll_create(int size)
488 {
489  ensure_init();
490  return tas_epoll_create(size);
491 }
492 
493 int epoll_create1(int flags)
494 {
495  ensure_init();
496  return tas_epoll_create1(flags);
497 }
498 
499 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
500 {
501  ensure_init();
502  return tas_epoll_ctl(epfd, op, fd, event);
503 }
504 
505 int epoll_wait(int epfd, struct epoll_event *events, int maxevents,
506  int timeout)
507 {
508  ensure_init();
509  return tas_epoll_wait(epfd, events, maxevents, timeout);
510 }
511 
512 int epoll_pwait(int epfd, struct epoll_event *events, int maxevents,
513  int timeout, const sigset_t *sigmask)
514 {
515  ensure_init();
516  return tas_epoll_pwait(epfd, events, maxevents, timeout, sigmask);
517 }
518 
519 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
520 {
521  ensure_init();
522  return tas_poll(fds, nfds, timeout);
523 }
524 
525 int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p,
526  const sigset_t *sigmask)
527 {
528  ensure_init();
529  return tas_ppoll(fds, nfds, tmo_p, sigmask);
530 }
531 
532 int dup(int oldfd)
533 {
534  return tas_dup(oldfd);
535 }
536 
537 int dup2(int oldfd, int newfd)
538 {
539  return tas_dup2(oldfd, newfd);
540 }
541 
542 int dup3(int oldfd, int newfd, int flags)
543 {
544  return tas_dup3(oldfd, newfd, flags);
545 }
546 
547 /* I really apologize to anyone reading this particular piece of code.
548  * So apparently there is code out there that calls some socket calls directly
549  * with syscall (nodejs being one example). In this case these get past our
550  * interposition layer and break things.
551  */
552 long syscall(long number, ...)
553 {
554  long ret;
555  va_list val;
556  long arg1, arg2, arg3, arg4, arg5, arg6;
557 
558  ensure_init();
559 
560  /* pray to god that this is safe on X86-64... */
561  va_start(val, number);
562  arg1 = va_arg(val, long);
563  arg2 = va_arg(val, long);
564  arg3 = va_arg(val, long);
565  arg4 = va_arg(val, long);
566  arg5 = va_arg(val, long);
567  arg6 = va_arg(val, long);
568  va_end(val);
569 
570  switch (number) {
571  case SYS_socket:
572  return socket((int) arg1, (int) arg2, (int) arg3);
573  case SYS_close:
574  return close((int) arg1);
575  case SYS_shutdown:
576  return shutdown((int) arg1, (int) arg2);
577  case SYS_bind:
578  return bind((int) arg1, (const struct sockaddr *) (uintptr_t) arg2,
579  (socklen_t) arg3);
580  case SYS_connect:
581  return connect((int) arg1, (const struct sockaddr *) (uintptr_t) arg2,
582  (socklen_t) arg3);
583  case SYS_listen:
584  return listen((int) arg1, (int) arg2);
585  case SYS_accept4:
586  return accept4((int) arg1, (struct sockaddr *) (uintptr_t) arg2,
587  (socklen_t *) (uintptr_t) arg3, (int) arg4);
588  case SYS_accept:
589  return accept((int) arg1, (struct sockaddr *) (uintptr_t) arg2,
590  (socklen_t *) (uintptr_t) arg3);
591  case SYS_fcntl:
592  va_start(val, number);
593  (void) va_arg(val, long);
594  (void) va_arg(val, long);
595  ret = vfcntl((int) arg1, (int) arg2, val, 0);
596  va_end(val);
597  return ret;
598 #ifdef SYS_fcntl64
599  case SYS_fcntl64:
600  va_start(val, number);
601  (void) va_arg(val, long);
602  (void) va_arg(val, long);
603  ret = vfcntl((int) arg1, (int) arg2, val, 1);
604  va_end(val);
605  return ret;
606 #endif
607  case SYS_getsockopt:
608  return getsockopt((int) arg1, (int) arg2, (int) arg3,
609  (void *) (uintptr_t) arg4, (socklen_t *) (uintptr_t) arg5);
610  case SYS_setsockopt:
611  return setsockopt((int) arg1, (int) arg2, (int) arg3,
612  (const void *) (uintptr_t) arg4, (socklen_t) arg5);
613  case SYS_getsockname:
614  return getsockname((int) arg1, (struct sockaddr *) (uintptr_t) arg2,
615  (socklen_t *) (uintptr_t) arg3);
616  case SYS_getpeername:
617  return getpeername((int) arg1, (struct sockaddr *) (uintptr_t) arg2,
618  (socklen_t *) (uintptr_t) arg3);
619 
620  case SYS_read:
621  return read((int) arg1, (void *) (uintptr_t) arg2, (size_t) arg3);
622 #ifdef SYS_recv
623  case SYS_recv:
624  return recv((int) arg1, (void *) (uintptr_t) arg2, (size_t) arg3,
625  (int) arg4);
626 #endif
627  case SYS_recvfrom:
628  return recvfrom((int) arg1, (void *) (uintptr_t) arg2, (size_t) arg3,
629  (int) arg4, (struct sockaddr *) (uintptr_t) arg5,
630  (socklen_t *) (uintptr_t) arg6);
631  case SYS_recvmsg:
632  return recvmsg((int) arg1, (struct msghdr *) (uintptr_t) arg2,
633  (int) arg3);
634  case SYS_readv:
635  return readv((int) arg1, (struct iovec *) (uintptr_t) arg2,
636  (int) arg3);
637  case SYS_pread64:
638  return pread((int) arg1, (void *) (uintptr_t) arg2, (size_t) arg3,
639  (off_t) arg4);
640 
641  case SYS_write:
642  return write((int) arg1, (const void *) (uintptr_t) arg2, (size_t) arg3);
643 #ifdef SYS_send
644  case SYS_send:
645  return send((int) arg1, (const void *) (uintptr_t) arg2, (size_t) arg3,
646  (int) arg4);
647 #endif
648  case SYS_sendto:
649  return sendto((int) arg1,(const void *) (uintptr_t) arg2, (size_t) arg3,
650  (int) arg4, (const struct sockaddr *) (uintptr_t) arg5,
651  (socklen_t) arg6);
652  case SYS_sendmsg:
653  return sendmsg((int) arg1, (const struct msghdr *) (uintptr_t) arg2,
654  (int) arg3);
655  case SYS_writev:
656  return writev((int) arg1, (const struct iovec *) (uintptr_t) arg2,
657  (int) arg3);
658  case SYS_pwrite64:
659  return pwrite((int) arg1, (const void *) (uintptr_t) arg2, (size_t) arg3,
660  (off_t) arg4);
661  case SYS_sendfile:
662  return sendfile((int) arg1, (int) arg2, (off_t *) (uintptr_t) arg3,
663  (size_t) arg4);
664 
665  case SYS_select:
666  return select((int) arg1, (fd_set *) (uintptr_t) arg2,
667  (fd_set *) (uintptr_t) arg3, (fd_set *) (uintptr_t) arg4,
668  (struct timeval *) (uintptr_t) arg5);
669  case SYS_pselect6:
670  fprintf(stderr, "tas syscall(): warning our pselect6 does not update "
671  "timeout value\n");
672  return pselect((int) arg1, (fd_set *) (uintptr_t) arg2,
673  (fd_set *) (uintptr_t) arg3, (fd_set *) (uintptr_t) arg4,
674  (struct timespec *) (uintptr_t) arg5,
675  (const sigset_t *) (uintptr_t) arg6);
676  case SYS_epoll_create:
677  return epoll_create((int) arg1);
678  case SYS_epoll_create1:
679  return epoll_create1((int) arg1);
680  case SYS_epoll_ctl:
681  return epoll_ctl((int) arg1, (int) arg2, (int) arg3,
682  (struct epoll_event *) (uintptr_t) arg4);
683  case SYS_epoll_wait:
684  return epoll_wait((int) arg1, (struct epoll_event *) (uintptr_t) arg2,
685  (int) arg3, (int) arg4);
686  case SYS_epoll_pwait:
687  return epoll_pwait((int) arg1, (struct epoll_event *) (uintptr_t) arg2,
688  (int) arg3, (int) arg4, (const sigset_t *) (uintptr_t) arg5);
689  case SYS_poll:
690  return poll((struct pollfd *) (uintptr_t) arg1, (nfds_t) arg2,
691  (int) arg3);
692  case SYS_ppoll:
693  return ppoll((struct pollfd *) (uintptr_t) arg1, (nfds_t) arg2,
694  (const struct timespec *) (uintptr_t) arg3,
695  (const sigset_t *) (uintptr_t) arg4);
696 
697  case SYS_dup:
698  return dup((int) arg1);
699  case SYS_dup2:
700  return dup2((int) arg1, (int) arg2);
701  case SYS_dup3:
702  return dup3((int) arg1, (int) arg2, (int) arg3);
703  }
704 
705  return libc_syscall(number, arg1, arg2, arg3, arg4, arg5, arg6);
706 }
707 
708 /******************************************************************************/
709 /* Helper functions */
710 
711 static void *bind_symbol(const char *sym)
712 {
713  void *ptr;
714  if ((ptr = dlsym(RTLD_NEXT, sym)) == NULL) {
715  fprintf(stderr, "flextcp socket interpose: dlsym failed (%s)\n", sym);
716  abort();
717  }
718  return ptr;
719 }
720 
721 static void init(void)
722 {
723  libc_socket = bind_symbol("socket");
724  libc_close = bind_symbol("close");
725  libc_shutdown = bind_symbol("shutdown");
726  libc_bind = bind_symbol("bind");
727  libc_connect = bind_symbol("connect");
728  libc_listen = bind_symbol("listen");
729  libc_accept4 = bind_symbol("accept4");
730  libc_accept = bind_symbol("accept");
731  libc_fcntl = bind_symbol("fcntl");
732 
733  libc_fcntl64 = dlsym(RTLD_NEXT, "fcntl64");
734  if (libc_fcntl64 == NULL)
735  libc_fcntl64 = libc_fcntl;
736 
737  libc_getsockopt = bind_symbol("getsockopt");
738  libc_setsockopt = bind_symbol("setsockopt");
739  libc_getsockname = bind_symbol("getsockname");
740  libc_getpeername = bind_symbol("getpeername");
741  libc_read = bind_symbol("read");
742  libc_recv = bind_symbol("recv");
743  libc_recvfrom = bind_symbol("recvfrom");
744  libc_recvmsg = bind_symbol("recvmsg");
745  libc_readv = bind_symbol("readv");
746  libc_pread = bind_symbol("pread");
747  libc_write = bind_symbol("write");
748  libc_send = bind_symbol("send");
749  libc_sendto = bind_symbol("sendto");
750  libc_sendmsg = bind_symbol("sendmsg");
751  libc_writev = bind_symbol("writev");
752  libc_pwrite = bind_symbol("pwrite");
753  libc_sendfile = bind_symbol("sendfile");
754  libc_syscall = bind_symbol("syscall");
755 
756  if (tas_init() != 0) {
757  abort();
758  }
759 }
760 
761 static inline void ensure_init(void)
762 {
763  static volatile uint32_t init_cnt = 0;
764  static volatile uint8_t init_done = 0;
765  static __thread uint8_t in_init = 0;
766 
767  if (init_done == 0) {
768  /* during init the socket functions will be used to connect to the kernel on
769  * a unix socket, so make sure that runs through. */
770  if (in_init) {
771  return;
772  }
773 
774  if (__sync_fetch_and_add(&init_cnt, 1) == 0) {
775  in_init = 1;
776  init();
777  in_init = 0;
778  MEM_BARRIER();
779  init_done = 1;
780  } else {
781  while (init_done == 0) {
782  pthread_yield();
783  }
784  MEM_BARRIER();
785  }
786  }
787 }
int tas_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
Definition: control.c:586
TAS sockets emulation.
static int epfd
Definition: appif.c:80