backupkey: Handle more clearly the case where we find the secret, but it has no value
[Samba.git] / lib / socket_wrapper / socket_wrapper.c
blob1188c4e538892088b01ec1c1bea728314b6a6765
1 /*
2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
40 is set.
43 #include "config.h"
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
52 #endif
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
55 #endif
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
58 #endif
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
61 #endif
62 #include <sys/uio.h>
63 #include <errno.h>
64 #include <sys/un.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
68 #include <fcntl.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <stdio.h>
72 #include <stdint.h>
73 #include <stdarg.h>
74 #include <stdbool.h>
75 #include <unistd.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
78 #endif
79 #ifdef HAVE_RPC_RPC_H
80 #include <rpc/rpc.h>
81 #endif
83 enum swrap_dbglvl_e {
84 SWRAP_LOG_ERROR = 0,
85 SWRAP_LOG_WARN,
86 SWRAP_LOG_DEBUG,
87 SWRAP_LOG_TRACE
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
93 #else
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
99 #else
100 #define DESTRUCTOR_ATTRIBUTE
101 #endif
103 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
105 #else
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
107 #endif
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
111 #else
112 # define SWRAP_THREAD
113 #endif
115 #ifndef MIN
116 #define MIN(a,b) ((a)<(b)?(a):(b))
117 #endif
119 #ifndef ZERO_STRUCT
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
121 #endif
123 #ifndef ZERO_STRUCTP
124 #define ZERO_STRUCTP(x) do { \
125 if ((x) != NULL) \
126 memset((char *)(x), 0, sizeof(*(x))); \
127 } while(0)
128 #endif
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
132 #endif
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
136 #endif
138 #ifdef IPV6_PKTINFO
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
149 #ifndef IP_PKTINFO
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
152 # endif
153 #endif
156 #define SWRAP_DLIST_ADD(list,item) do { \
157 if (!(list)) { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
160 (list) = (item); \
161 } else { \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
165 (list) = (item); \
167 } while (0)
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
172 if (list) { \
173 (list)->prev = NULL; \
175 } else { \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
185 } while (0)
187 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
188 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
189 #else
190 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
191 #endif
193 /* we need to use a very terse format here as IRIX 6.4 silently
194 truncates names to 16 chars, so if we use a longer name then we
195 can't tell which port a packet came from with recvfrom()
197 with this format we have 8 chars left for the directory name
199 #define SOCKET_FORMAT "%c%02X%04X"
200 #define SOCKET_TYPE_CHAR_TCP 'T'
201 #define SOCKET_TYPE_CHAR_UDP 'U'
202 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
203 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
206 * Cut down to 1500 byte packets for stream sockets,
207 * which makes it easier to format PCAP capture files
208 * (as the caller will simply continue from here)
210 #define SOCKET_MAX_PACKET 1500
212 #define SOCKET_MAX_SOCKETS 1024
214 /* This limit is to avoid broadcast sendto() needing to stat too many
215 * files. It may be raised (with a performance cost) to up to 254
216 * without changing the format above */
217 #define MAX_WRAPPED_INTERFACES 40
219 struct swrap_address {
220 socklen_t sa_socklen;
221 union {
222 struct sockaddr s;
223 struct sockaddr_in in;
224 #ifdef HAVE_IPV6
225 struct sockaddr_in6 in6;
226 #endif
227 struct sockaddr_un un;
228 struct sockaddr_storage ss;
229 } sa;
232 struct socket_info_fd {
233 struct socket_info_fd *prev, *next;
234 int fd;
237 struct socket_info
239 struct socket_info_fd *fds;
241 int family;
242 int type;
243 int protocol;
244 int bound;
245 int bcast;
246 int is_server;
247 int connected;
248 int defer_connect;
249 int pktinfo;
251 /* The unix path so we can unlink it on close() */
252 struct sockaddr_un un_addr;
254 struct swrap_address bindname;
255 struct swrap_address myname;
256 struct swrap_address peername;
258 struct {
259 unsigned long pck_snd;
260 unsigned long pck_rcv;
261 } io;
263 struct socket_info *prev, *next;
267 * File descriptors are shared between threads so we should share socket
268 * information too.
270 struct socket_info *sockets;
272 /* Function prototypes */
274 bool socket_wrapper_enabled(void);
275 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
277 #ifdef NDEBUG
278 # define SWRAP_LOG(...)
279 #else
281 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
282 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
284 static void swrap_log(enum swrap_dbglvl_e dbglvl,
285 const char *func,
286 const char *format, ...)
288 char buffer[1024];
289 va_list va;
290 const char *d;
291 unsigned int lvl = 0;
293 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
294 if (d != NULL) {
295 lvl = atoi(d);
298 va_start(va, format);
299 vsnprintf(buffer, sizeof(buffer), format, va);
300 va_end(va);
302 if (lvl >= dbglvl) {
303 switch (dbglvl) {
304 case SWRAP_LOG_ERROR:
305 fprintf(stderr,
306 "SWRAP_ERROR(%d) - %s: %s\n",
307 (int)getpid(), func, buffer);
308 break;
309 case SWRAP_LOG_WARN:
310 fprintf(stderr,
311 "SWRAP_WARN(%d) - %s: %s\n",
312 (int)getpid(), func, buffer);
313 break;
314 case SWRAP_LOG_DEBUG:
315 fprintf(stderr,
316 "SWRAP_DEBUG(%d) - %s: %s\n",
317 (int)getpid(), func, buffer);
318 break;
319 case SWRAP_LOG_TRACE:
320 fprintf(stderr,
321 "SWRAP_TRACE(%d) - %s: %s\n",
322 (int)getpid(), func, buffer);
323 break;
327 #endif
329 /*********************************************************
330 * SWRAP LOADING LIBC FUNCTIONS
331 *********************************************************/
333 #include <dlfcn.h>
335 struct swrap_libc_fns {
336 int (*libc_accept)(int sockfd,
337 struct sockaddr *addr,
338 socklen_t *addrlen);
339 int (*libc_bind)(int sockfd,
340 const struct sockaddr *addr,
341 socklen_t addrlen);
342 int (*libc_close)(int fd);
343 int (*libc_connect)(int sockfd,
344 const struct sockaddr *addr,
345 socklen_t addrlen);
346 int (*libc_dup)(int fd);
347 int (*libc_dup2)(int oldfd, int newfd);
348 int (*libc_fcntl)(int fd, int cmd, ...);
349 FILE *(*libc_fopen)(const char *name, const char *mode);
350 #ifdef HAVE_EVENTFD
351 int (*libc_eventfd)(int count, int flags);
352 #endif
353 int (*libc_getpeername)(int sockfd,
354 struct sockaddr *addr,
355 socklen_t *addrlen);
356 int (*libc_getsockname)(int sockfd,
357 struct sockaddr *addr,
358 socklen_t *addrlen);
359 int (*libc_getsockopt)(int sockfd,
360 int level,
361 int optname,
362 void *optval,
363 socklen_t *optlen);
364 int (*libc_ioctl)(int d, unsigned long int request, ...);
365 int (*libc_listen)(int sockfd, int backlog);
366 int (*libc_open)(const char *pathname, int flags, mode_t mode);
367 int (*libc_pipe)(int pipefd[2]);
368 int (*libc_read)(int fd, void *buf, size_t count);
369 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
370 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
371 int (*libc_recvfrom)(int sockfd,
372 void *buf,
373 size_t len,
374 int flags,
375 struct sockaddr *src_addr,
376 socklen_t *addrlen);
377 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
378 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
379 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
380 int (*libc_sendto)(int sockfd,
381 const void *buf,
382 size_t len,
383 int flags,
384 const struct sockaddr *dst_addr,
385 socklen_t addrlen);
386 int (*libc_setsockopt)(int sockfd,
387 int level,
388 int optname,
389 const void *optval,
390 socklen_t optlen);
391 #ifdef HAVE_SIGNALFD
392 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
393 #endif
394 int (*libc_socket)(int domain, int type, int protocol);
395 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
396 #ifdef HAVE_TIMERFD_CREATE
397 int (*libc_timerfd_create)(int clockid, int flags);
398 #endif
399 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
402 struct swrap {
403 void *libc_handle;
404 void *libsocket_handle;
406 bool initialised;
407 bool enabled;
409 char *socket_dir;
411 struct swrap_libc_fns fns;
414 static struct swrap swrap;
416 /* prototypes */
417 static const char *socket_wrapper_dir(void);
419 #define LIBC_NAME "libc.so"
421 enum swrap_lib {
422 SWRAP_LIBC,
423 SWRAP_LIBNSL,
424 SWRAP_LIBSOCKET,
427 #ifndef NDEBUG
428 static const char *swrap_str_lib(enum swrap_lib lib)
430 switch (lib) {
431 case SWRAP_LIBC:
432 return "libc";
433 case SWRAP_LIBNSL:
434 return "libnsl";
435 case SWRAP_LIBSOCKET:
436 return "libsocket";
439 /* Compiler would warn us about unhandled enum value if we get here */
440 return "unknown";
442 #endif
444 static void *swrap_load_lib_handle(enum swrap_lib lib)
446 int flags = RTLD_LAZY;
447 void *handle = NULL;
448 int i;
450 #ifdef RTLD_DEEPBIND
451 flags |= RTLD_DEEPBIND;
452 #endif
454 switch (lib) {
455 case SWRAP_LIBNSL:
456 /* FALL TROUGH */
457 case SWRAP_LIBSOCKET:
458 #ifdef HAVE_LIBSOCKET
459 handle = swrap.libsocket_handle;
460 if (handle == NULL) {
461 for (i = 10; i >= 0; i--) {
462 char soname[256] = {0};
464 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
465 handle = dlopen(soname, flags);
466 if (handle != NULL) {
467 break;
471 swrap.libsocket_handle = handle;
473 break;
474 #endif
475 /* FALL TROUGH */
476 case SWRAP_LIBC:
477 handle = swrap.libc_handle;
478 #ifdef LIBC_SO
479 if (handle == NULL) {
480 handle = dlopen(LIBC_SO, flags);
482 swrap.libc_handle = handle;
484 #endif
485 if (handle == NULL) {
486 for (i = 10; i >= 0; i--) {
487 char soname[256] = {0};
489 snprintf(soname, sizeof(soname), "libc.so.%d", i);
490 handle = dlopen(soname, flags);
491 if (handle != NULL) {
492 break;
496 swrap.libc_handle = handle;
498 break;
501 if (handle == NULL) {
502 #ifdef RTLD_NEXT
503 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
504 #else
505 SWRAP_LOG(SWRAP_LOG_ERROR,
506 "Failed to dlopen library: %s\n",
507 dlerror());
508 exit(-1);
509 #endif
512 return handle;
515 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
517 void *handle;
518 void *func;
520 handle = swrap_load_lib_handle(lib);
522 func = dlsym(handle, fn_name);
523 if (func == NULL) {
524 SWRAP_LOG(SWRAP_LOG_ERROR,
525 "Failed to find %s: %s\n",
526 fn_name, dlerror());
527 exit(-1);
530 SWRAP_LOG(SWRAP_LOG_TRACE,
531 "Loaded %s from %s",
532 fn_name, swrap_str_lib(lib));
533 return func;
536 #define swrap_load_lib_function(lib, fn_name) \
537 if (swrap.fns.libc_##fn_name == NULL) { \
538 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
539 *(void **) (&swrap.fns.libc_##fn_name) = \
540 swrap_cast_ptr; \
545 * IMPORTANT
547 * Functions especially from libc need to be loaded individually, you can't load
548 * all at once or gdb will segfault at startup. The same applies to valgrind and
549 * has probably something todo with with the linker.
550 * So we need load each function at the point it is called the first time.
552 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
554 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
556 return swrap.fns.libc_accept(sockfd, addr, addrlen);
559 static int libc_bind(int sockfd,
560 const struct sockaddr *addr,
561 socklen_t addrlen)
563 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
565 return swrap.fns.libc_bind(sockfd, addr, addrlen);
568 static int libc_close(int fd)
570 swrap_load_lib_function(SWRAP_LIBC, close);
572 return swrap.fns.libc_close(fd);
575 static int libc_connect(int sockfd,
576 const struct sockaddr *addr,
577 socklen_t addrlen)
579 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
581 return swrap.fns.libc_connect(sockfd, addr, addrlen);
584 static int libc_dup(int fd)
586 swrap_load_lib_function(SWRAP_LIBC, dup);
588 return swrap.fns.libc_dup(fd);
591 static int libc_dup2(int oldfd, int newfd)
593 swrap_load_lib_function(SWRAP_LIBC, dup2);
595 return swrap.fns.libc_dup2(oldfd, newfd);
598 #ifdef HAVE_EVENTFD
599 static int libc_eventfd(int count, int flags)
601 swrap_load_lib_function(SWRAP_LIBC, eventfd);
603 return swrap.fns.libc_eventfd(count, flags);
605 #endif
607 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
608 static int libc_vfcntl(int fd, int cmd, va_list ap)
610 long int args[4];
611 int rc;
612 int i;
614 swrap_load_lib_function(SWRAP_LIBC, fcntl);
616 for (i = 0; i < 4; i++) {
617 args[i] = va_arg(ap, long int);
620 rc = swrap.fns.libc_fcntl(fd,
621 cmd,
622 args[0],
623 args[1],
624 args[2],
625 args[3]);
627 return rc;
630 static int libc_getpeername(int sockfd,
631 struct sockaddr *addr,
632 socklen_t *addrlen)
634 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
636 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
639 static int libc_getsockname(int sockfd,
640 struct sockaddr *addr,
641 socklen_t *addrlen)
643 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
645 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
648 static int libc_getsockopt(int sockfd,
649 int level,
650 int optname,
651 void *optval,
652 socklen_t *optlen)
654 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
656 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
659 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
660 static int libc_vioctl(int d, unsigned long int request, va_list ap)
662 long int args[4];
663 int rc;
664 int i;
666 swrap_load_lib_function(SWRAP_LIBC, ioctl);
668 for (i = 0; i < 4; i++) {
669 args[i] = va_arg(ap, long int);
672 rc = swrap.fns.libc_ioctl(d,
673 request,
674 args[0],
675 args[1],
676 args[2],
677 args[3]);
679 return rc;
682 static int libc_listen(int sockfd, int backlog)
684 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
686 return swrap.fns.libc_listen(sockfd, backlog);
689 static FILE *libc_fopen(const char *name, const char *mode)
691 swrap_load_lib_function(SWRAP_LIBC, fopen);
693 return swrap.fns.libc_fopen(name, mode);
696 static int libc_vopen(const char *pathname, int flags, va_list ap)
698 long int mode = 0;
699 int fd;
701 swrap_load_lib_function(SWRAP_LIBC, open);
703 mode = va_arg(ap, long int);
705 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
707 return fd;
710 static int libc_open(const char *pathname, int flags, ...)
712 va_list ap;
713 int fd;
715 va_start(ap, flags);
716 fd = libc_vopen(pathname, flags, ap);
717 va_end(ap);
719 return fd;
722 static int libc_pipe(int pipefd[2])
724 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
726 return swrap.fns.libc_pipe(pipefd);
729 static int libc_read(int fd, void *buf, size_t count)
731 swrap_load_lib_function(SWRAP_LIBC, read);
733 return swrap.fns.libc_read(fd, buf, count);
736 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
738 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
740 return swrap.fns.libc_readv(fd, iov, iovcnt);
743 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
745 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
747 return swrap.fns.libc_recv(sockfd, buf, len, flags);
750 static int libc_recvfrom(int sockfd,
751 void *buf,
752 size_t len,
753 int flags,
754 struct sockaddr *src_addr,
755 socklen_t *addrlen)
757 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
759 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
762 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
764 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
766 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
769 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
771 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
773 return swrap.fns.libc_send(sockfd, buf, len, flags);
776 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
778 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
780 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
783 static int libc_sendto(int sockfd,
784 const void *buf,
785 size_t len,
786 int flags,
787 const struct sockaddr *dst_addr,
788 socklen_t addrlen)
790 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
792 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
795 static int libc_setsockopt(int sockfd,
796 int level,
797 int optname,
798 const void *optval,
799 socklen_t optlen)
801 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
803 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
806 #ifdef HAVE_SIGNALFD
807 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
809 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
811 return swrap.fns.libc_signalfd(fd, mask, flags);
813 #endif
815 static int libc_socket(int domain, int type, int protocol)
817 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
819 return swrap.fns.libc_socket(domain, type, protocol);
822 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
824 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
826 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
829 #ifdef HAVE_TIMERFD_CREATE
830 static int libc_timerfd_create(int clockid, int flags)
832 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
834 return swrap.fns.libc_timerfd_create(clockid, flags);
836 #endif
838 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
840 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
842 return swrap.fns.libc_writev(fd, iov, iovcnt);
845 /*********************************************************
846 * SWRAP HELPER FUNCTIONS
847 *********************************************************/
849 #ifdef HAVE_IPV6
851 * FD00::5357:5FXX
853 static const struct in6_addr *swrap_ipv6(void)
855 static struct in6_addr v;
856 static int initialized;
857 int ret;
859 if (initialized) {
860 return &v;
862 initialized = 1;
864 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
865 if (ret <= 0) {
866 abort();
869 return &v;
871 #endif
873 static void set_port(int family, int prt, struct swrap_address *addr)
875 switch (family) {
876 case AF_INET:
877 addr->sa.in.sin_port = htons(prt);
878 break;
879 #ifdef HAVE_IPV6
880 case AF_INET6:
881 addr->sa.in6.sin6_port = htons(prt);
882 break;
883 #endif
887 static size_t socket_length(int family)
889 switch (family) {
890 case AF_INET:
891 return sizeof(struct sockaddr_in);
892 #ifdef HAVE_IPV6
893 case AF_INET6:
894 return sizeof(struct sockaddr_in6);
895 #endif
897 return 0;
900 static const char *socket_wrapper_dir(void)
902 const char *s = getenv("SOCKET_WRAPPER_DIR");
903 if (s == NULL) {
904 return NULL;
906 /* TODO use realpath(3) here, when we add support for threads */
907 if (strncmp(s, "./", 2) == 0) {
908 s += 2;
911 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
912 return s;
915 bool socket_wrapper_enabled(void)
917 const char *s = socket_wrapper_dir();
919 return s != NULL ? true : false;
922 static unsigned int socket_wrapper_default_iface(void)
924 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
925 if (s) {
926 unsigned int iface;
927 if (sscanf(s, "%u", &iface) == 1) {
928 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
929 return iface;
934 return 1;/* 127.0.0.1 */
937 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
939 unsigned int iface;
940 unsigned int prt;
941 const char *p;
942 char type;
944 p = strrchr(un->sun_path, '/');
945 if (p) p++; else p = un->sun_path;
947 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
948 errno = EINVAL;
949 return -1;
952 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
953 type, iface, prt);
955 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
956 errno = EINVAL;
957 return -1;
960 if (prt > 0xFFFF) {
961 errno = EINVAL;
962 return -1;
965 switch(type) {
966 case SOCKET_TYPE_CHAR_TCP:
967 case SOCKET_TYPE_CHAR_UDP: {
968 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
970 if ((*len) < sizeof(*in2)) {
971 errno = EINVAL;
972 return -1;
975 memset(in2, 0, sizeof(*in2));
976 in2->sin_family = AF_INET;
977 in2->sin_addr.s_addr = htonl((127<<24) | iface);
978 in2->sin_port = htons(prt);
980 *len = sizeof(*in2);
981 break;
983 #ifdef HAVE_IPV6
984 case SOCKET_TYPE_CHAR_TCP_V6:
985 case SOCKET_TYPE_CHAR_UDP_V6: {
986 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
988 if ((*len) < sizeof(*in2)) {
989 errno = EINVAL;
990 return -1;
993 memset(in2, 0, sizeof(*in2));
994 in2->sin6_family = AF_INET6;
995 in2->sin6_addr = *swrap_ipv6();
996 in2->sin6_addr.s6_addr[15] = iface;
997 in2->sin6_port = htons(prt);
999 *len = sizeof(*in2);
1000 break;
1002 #endif
1003 default:
1004 errno = EINVAL;
1005 return -1;
1008 return 0;
1011 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1012 int *bcast)
1014 char type = '\0';
1015 unsigned int prt;
1016 unsigned int iface;
1017 int is_bcast = 0;
1019 if (bcast) *bcast = 0;
1021 switch (inaddr->sa_family) {
1022 case AF_INET: {
1023 const struct sockaddr_in *in =
1024 (const struct sockaddr_in *)(const void *)inaddr;
1025 unsigned int addr = ntohl(in->sin_addr.s_addr);
1026 char u_type = '\0';
1027 char b_type = '\0';
1028 char a_type = '\0';
1030 switch (si->type) {
1031 case SOCK_STREAM:
1032 u_type = SOCKET_TYPE_CHAR_TCP;
1033 break;
1034 case SOCK_DGRAM:
1035 u_type = SOCKET_TYPE_CHAR_UDP;
1036 a_type = SOCKET_TYPE_CHAR_UDP;
1037 b_type = SOCKET_TYPE_CHAR_UDP;
1038 break;
1039 default:
1040 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1041 errno = ESOCKTNOSUPPORT;
1042 return -1;
1045 prt = ntohs(in->sin_port);
1046 if (a_type && addr == 0xFFFFFFFF) {
1047 /* 255.255.255.255 only udp */
1048 is_bcast = 2;
1049 type = a_type;
1050 iface = socket_wrapper_default_iface();
1051 } else if (b_type && addr == 0x7FFFFFFF) {
1052 /* 127.255.255.255 only udp */
1053 is_bcast = 1;
1054 type = b_type;
1055 iface = socket_wrapper_default_iface();
1056 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1057 /* 127.0.0.X */
1058 is_bcast = 0;
1059 type = u_type;
1060 iface = (addr & 0x000000FF);
1061 } else {
1062 errno = ENETUNREACH;
1063 return -1;
1065 if (bcast) *bcast = is_bcast;
1066 break;
1068 #ifdef HAVE_IPV6
1069 case AF_INET6: {
1070 const struct sockaddr_in6 *in =
1071 (const struct sockaddr_in6 *)(const void *)inaddr;
1072 struct in6_addr cmp1, cmp2;
1074 switch (si->type) {
1075 case SOCK_STREAM:
1076 type = SOCKET_TYPE_CHAR_TCP_V6;
1077 break;
1078 case SOCK_DGRAM:
1079 type = SOCKET_TYPE_CHAR_UDP_V6;
1080 break;
1081 default:
1082 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1083 errno = ESOCKTNOSUPPORT;
1084 return -1;
1087 /* XXX no multicast/broadcast */
1089 prt = ntohs(in->sin6_port);
1091 cmp1 = *swrap_ipv6();
1092 cmp2 = in->sin6_addr;
1093 cmp2.s6_addr[15] = 0;
1094 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1095 iface = in->sin6_addr.s6_addr[15];
1096 } else {
1097 errno = ENETUNREACH;
1098 return -1;
1101 break;
1103 #endif
1104 default:
1105 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1106 errno = ENETUNREACH;
1107 return -1;
1110 if (prt == 0) {
1111 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1112 errno = EINVAL;
1113 return -1;
1116 if (is_bcast) {
1117 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1118 socket_wrapper_dir());
1119 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1120 /* the caller need to do more processing */
1121 return 0;
1124 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1125 socket_wrapper_dir(), type, iface, prt);
1126 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1128 return 0;
1131 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1132 int *bcast)
1134 char type = '\0';
1135 unsigned int prt;
1136 unsigned int iface;
1137 struct stat st;
1138 int is_bcast = 0;
1140 if (bcast) *bcast = 0;
1142 switch (si->family) {
1143 case AF_INET: {
1144 const struct sockaddr_in *in =
1145 (const struct sockaddr_in *)(const void *)inaddr;
1146 unsigned int addr = ntohl(in->sin_addr.s_addr);
1147 char u_type = '\0';
1148 char d_type = '\0';
1149 char b_type = '\0';
1150 char a_type = '\0';
1152 prt = ntohs(in->sin_port);
1154 switch (si->type) {
1155 case SOCK_STREAM:
1156 u_type = SOCKET_TYPE_CHAR_TCP;
1157 d_type = SOCKET_TYPE_CHAR_TCP;
1158 break;
1159 case SOCK_DGRAM:
1160 u_type = SOCKET_TYPE_CHAR_UDP;
1161 d_type = SOCKET_TYPE_CHAR_UDP;
1162 a_type = SOCKET_TYPE_CHAR_UDP;
1163 b_type = SOCKET_TYPE_CHAR_UDP;
1164 break;
1165 default:
1166 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1167 errno = ESOCKTNOSUPPORT;
1168 return -1;
1171 if (addr == 0) {
1172 /* 0.0.0.0 */
1173 is_bcast = 0;
1174 type = d_type;
1175 iface = socket_wrapper_default_iface();
1176 } else if (a_type && addr == 0xFFFFFFFF) {
1177 /* 255.255.255.255 only udp */
1178 is_bcast = 2;
1179 type = a_type;
1180 iface = socket_wrapper_default_iface();
1181 } else if (b_type && addr == 0x7FFFFFFF) {
1182 /* 127.255.255.255 only udp */
1183 is_bcast = 1;
1184 type = b_type;
1185 iface = socket_wrapper_default_iface();
1186 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1187 /* 127.0.0.X */
1188 is_bcast = 0;
1189 type = u_type;
1190 iface = (addr & 0x000000FF);
1191 } else {
1192 errno = EADDRNOTAVAIL;
1193 return -1;
1196 /* Store the bind address for connect() */
1197 if (si->bindname.sa_socklen == 0) {
1198 struct sockaddr_in bind_in;
1199 socklen_t blen = sizeof(struct sockaddr_in);
1201 ZERO_STRUCT(bind_in);
1202 bind_in.sin_family = in->sin_family;
1203 bind_in.sin_port = in->sin_port;
1204 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1206 si->bindname.sa_socklen = blen;
1207 memcpy(&si->bindname.sa.in, &bind_in, blen);
1210 break;
1212 #ifdef HAVE_IPV6
1213 case AF_INET6: {
1214 const struct sockaddr_in6 *in =
1215 (const struct sockaddr_in6 *)(const void *)inaddr;
1216 struct in6_addr cmp1, cmp2;
1218 switch (si->type) {
1219 case SOCK_STREAM:
1220 type = SOCKET_TYPE_CHAR_TCP_V6;
1221 break;
1222 case SOCK_DGRAM:
1223 type = SOCKET_TYPE_CHAR_UDP_V6;
1224 break;
1225 default:
1226 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1227 errno = ESOCKTNOSUPPORT;
1228 return -1;
1231 /* XXX no multicast/broadcast */
1233 prt = ntohs(in->sin6_port);
1235 cmp1 = *swrap_ipv6();
1236 cmp2 = in->sin6_addr;
1237 cmp2.s6_addr[15] = 0;
1238 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1239 iface = socket_wrapper_default_iface();
1240 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1241 iface = in->sin6_addr.s6_addr[15];
1242 } else {
1243 errno = EADDRNOTAVAIL;
1244 return -1;
1247 /* Store the bind address for connect() */
1248 if (si->bindname.sa_socklen == 0) {
1249 struct sockaddr_in6 bind_in;
1250 socklen_t blen = sizeof(struct sockaddr_in6);
1252 ZERO_STRUCT(bind_in);
1253 bind_in.sin6_family = in->sin6_family;
1254 bind_in.sin6_port = in->sin6_port;
1256 bind_in.sin6_addr = *swrap_ipv6();
1257 bind_in.sin6_addr.s6_addr[15] = iface;
1259 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1260 si->bindname.sa_socklen = blen;
1263 break;
1265 #endif
1266 default:
1267 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1268 errno = EADDRNOTAVAIL;
1269 return -1;
1273 if (bcast) *bcast = is_bcast;
1275 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1276 errno = EINVAL;
1277 return -1;
1280 if (prt == 0) {
1281 /* handle auto-allocation of ephemeral ports */
1282 for (prt = 5001; prt < 10000; prt++) {
1283 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1284 socket_wrapper_dir(), type, iface, prt);
1285 if (stat(un->sun_path, &st) == 0) continue;
1287 set_port(si->family, prt, &si->myname);
1288 set_port(si->family, prt, &si->bindname);
1290 break;
1292 if (prt == 10000) {
1293 errno = ENFILE;
1294 return -1;
1298 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1299 socket_wrapper_dir(), type, iface, prt);
1300 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1301 return 0;
1304 static struct socket_info *find_socket_info(int fd)
1306 struct socket_info *i;
1308 for (i = sockets; i; i = i->next) {
1309 struct socket_info_fd *f;
1310 for (f = i->fds; f; f = f->next) {
1311 if (f->fd == fd) {
1312 return i;
1317 return NULL;
1320 #if 0 /* FIXME */
1321 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1323 struct socket_info *s;
1325 /* first catch invalid input */
1326 switch (sa->sa_family) {
1327 case AF_INET:
1328 if (len < sizeof(struct sockaddr_in)) {
1329 return false;
1331 break;
1332 #if HAVE_IPV6
1333 case AF_INET6:
1334 if (len < sizeof(struct sockaddr_in6)) {
1335 return false;
1337 break;
1338 #endif
1339 default:
1340 return false;
1341 break;
1344 for (s = sockets; s != NULL; s = s->next) {
1345 if (s->myname == NULL) {
1346 continue;
1348 if (s->myname->sa_family != sa->sa_family) {
1349 continue;
1351 switch (s->myname->sa_family) {
1352 case AF_INET: {
1353 struct sockaddr_in *sin1, *sin2;
1355 sin1 = (struct sockaddr_in *)s->myname;
1356 sin2 = (struct sockaddr_in *)sa;
1358 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1359 continue;
1361 if (sin1->sin_port != sin2->sin_port) {
1362 continue;
1364 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1365 continue;
1368 /* found */
1369 return true;
1370 break;
1372 #if HAVE_IPV6
1373 case AF_INET6: {
1374 struct sockaddr_in6 *sin1, *sin2;
1376 sin1 = (struct sockaddr_in6 *)s->myname;
1377 sin2 = (struct sockaddr_in6 *)sa;
1379 if (sin1->sin6_port != sin2->sin6_port) {
1380 continue;
1382 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1383 &sin2->sin6_addr))
1385 continue;
1388 /* found */
1389 return true;
1390 break;
1392 #endif
1393 default:
1394 continue;
1395 break;
1400 return false;
1402 #endif
1404 static void swrap_remove_stale(int fd)
1406 struct socket_info *si = find_socket_info(fd);
1407 struct socket_info_fd *fi;
1409 if (si != NULL) {
1410 for (fi = si->fds; fi; fi = fi->next) {
1411 if (fi->fd == fd) {
1412 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1413 SWRAP_DLIST_REMOVE(si->fds, fi);
1414 free(fi);
1415 break;
1419 if (si->fds == NULL) {
1420 SWRAP_DLIST_REMOVE(sockets, si);
1421 if (si->un_addr.sun_path[0] != '\0') {
1422 unlink(si->un_addr.sun_path);
1424 free(si);
1429 static int sockaddr_convert_to_un(struct socket_info *si,
1430 const struct sockaddr *in_addr,
1431 socklen_t in_len,
1432 struct sockaddr_un *out_addr,
1433 int alloc_sock,
1434 int *bcast)
1436 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1438 (void) in_len; /* unused */
1440 if (out_addr == NULL) {
1441 return 0;
1444 out->sa_family = AF_UNIX;
1445 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1446 out->sa_len = sizeof(*out_addr);
1447 #endif
1449 switch (in_addr->sa_family) {
1450 case AF_UNSPEC: {
1451 const struct sockaddr_in *sin;
1452 if (si->family != AF_INET) {
1453 break;
1455 if (in_len < sizeof(struct sockaddr_in)) {
1456 break;
1458 sin = (const struct sockaddr_in *)(const void *)in_addr;
1459 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1460 break;
1464 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1465 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1468 /* FALL THROUGH */
1470 case AF_INET:
1471 #ifdef HAVE_IPV6
1472 case AF_INET6:
1473 #endif
1474 switch (si->type) {
1475 case SOCK_STREAM:
1476 case SOCK_DGRAM:
1477 break;
1478 default:
1479 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1480 errno = ESOCKTNOSUPPORT;
1481 return -1;
1483 if (alloc_sock) {
1484 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1485 } else {
1486 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1488 default:
1489 break;
1492 errno = EAFNOSUPPORT;
1493 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1494 return -1;
1497 static int sockaddr_convert_from_un(const struct socket_info *si,
1498 const struct sockaddr_un *in_addr,
1499 socklen_t un_addrlen,
1500 int family,
1501 struct sockaddr *out_addr,
1502 socklen_t *out_addrlen)
1504 int ret;
1506 if (out_addr == NULL || out_addrlen == NULL)
1507 return 0;
1509 if (un_addrlen == 0) {
1510 *out_addrlen = 0;
1511 return 0;
1514 switch (family) {
1515 case AF_INET:
1516 #ifdef HAVE_IPV6
1517 case AF_INET6:
1518 #endif
1519 switch (si->type) {
1520 case SOCK_STREAM:
1521 case SOCK_DGRAM:
1522 break;
1523 default:
1524 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1525 errno = ESOCKTNOSUPPORT;
1526 return -1;
1528 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1529 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1530 out_addr->sa_len = *out_addrlen;
1531 #endif
1532 return ret;
1533 default:
1534 break;
1537 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1538 errno = EAFNOSUPPORT;
1539 return -1;
1542 enum swrap_packet_type {
1543 SWRAP_CONNECT_SEND,
1544 SWRAP_CONNECT_UNREACH,
1545 SWRAP_CONNECT_RECV,
1546 SWRAP_CONNECT_ACK,
1547 SWRAP_ACCEPT_SEND,
1548 SWRAP_ACCEPT_RECV,
1549 SWRAP_ACCEPT_ACK,
1550 SWRAP_RECVFROM,
1551 SWRAP_SENDTO,
1552 SWRAP_SENDTO_UNREACH,
1553 SWRAP_PENDING_RST,
1554 SWRAP_RECV,
1555 SWRAP_RECV_RST,
1556 SWRAP_SEND,
1557 SWRAP_SEND_RST,
1558 SWRAP_CLOSE_SEND,
1559 SWRAP_CLOSE_RECV,
1560 SWRAP_CLOSE_ACK,
1563 struct swrap_file_hdr {
1564 uint32_t magic;
1565 uint16_t version_major;
1566 uint16_t version_minor;
1567 int32_t timezone;
1568 uint32_t sigfigs;
1569 uint32_t frame_max_len;
1570 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1571 uint32_t link_type;
1573 #define SWRAP_FILE_HDR_SIZE 24
1575 struct swrap_packet_frame {
1576 uint32_t seconds;
1577 uint32_t micro_seconds;
1578 uint32_t recorded_length;
1579 uint32_t full_length;
1581 #define SWRAP_PACKET_FRAME_SIZE 16
1583 union swrap_packet_ip {
1584 struct {
1585 uint8_t ver_hdrlen;
1586 uint8_t tos;
1587 uint16_t packet_length;
1588 uint16_t identification;
1589 uint8_t flags;
1590 uint8_t fragment;
1591 uint8_t ttl;
1592 uint8_t protocol;
1593 uint16_t hdr_checksum;
1594 uint32_t src_addr;
1595 uint32_t dest_addr;
1596 } v4;
1597 #define SWRAP_PACKET_IP_V4_SIZE 20
1598 struct {
1599 uint8_t ver_prio;
1600 uint8_t flow_label_high;
1601 uint16_t flow_label_low;
1602 uint16_t payload_length;
1603 uint8_t next_header;
1604 uint8_t hop_limit;
1605 uint8_t src_addr[16];
1606 uint8_t dest_addr[16];
1607 } v6;
1608 #define SWRAP_PACKET_IP_V6_SIZE 40
1610 #define SWRAP_PACKET_IP_SIZE 40
1612 union swrap_packet_payload {
1613 struct {
1614 uint16_t source_port;
1615 uint16_t dest_port;
1616 uint32_t seq_num;
1617 uint32_t ack_num;
1618 uint8_t hdr_length;
1619 uint8_t control;
1620 uint16_t window;
1621 uint16_t checksum;
1622 uint16_t urg;
1623 } tcp;
1624 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1625 struct {
1626 uint16_t source_port;
1627 uint16_t dest_port;
1628 uint16_t length;
1629 uint16_t checksum;
1630 } udp;
1631 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1632 struct {
1633 uint8_t type;
1634 uint8_t code;
1635 uint16_t checksum;
1636 uint32_t unused;
1637 } icmp4;
1638 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1639 struct {
1640 uint8_t type;
1641 uint8_t code;
1642 uint16_t checksum;
1643 uint32_t unused;
1644 } icmp6;
1645 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1647 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1649 #define SWRAP_PACKET_MIN_ALLOC \
1650 (SWRAP_PACKET_FRAME_SIZE + \
1651 SWRAP_PACKET_IP_SIZE + \
1652 SWRAP_PACKET_PAYLOAD_SIZE)
1654 static const char *swrap_pcap_init_file(void)
1656 static int initialized = 0;
1657 static const char *s = NULL;
1658 static const struct swrap_file_hdr h;
1659 static const struct swrap_packet_frame f;
1660 static const union swrap_packet_ip i;
1661 static const union swrap_packet_payload p;
1663 if (initialized == 1) {
1664 return s;
1666 initialized = 1;
1669 * TODO: don't use the structs use plain buffer offsets
1670 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1672 * for now make sure we disable PCAP support
1673 * if the struct has alignment!
1675 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1676 return NULL;
1678 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1679 return NULL;
1681 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1682 return NULL;
1684 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1685 return NULL;
1687 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1688 return NULL;
1690 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1691 return NULL;
1693 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1694 return NULL;
1696 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1697 return NULL;
1699 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1700 return NULL;
1702 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1703 return NULL;
1706 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1707 if (s == NULL) {
1708 return NULL;
1710 if (strncmp(s, "./", 2) == 0) {
1711 s += 2;
1713 return s;
1716 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1717 const struct sockaddr *src,
1718 const struct sockaddr *dest,
1719 int socket_type,
1720 const uint8_t *payload,
1721 size_t payload_len,
1722 unsigned long tcp_seqno,
1723 unsigned long tcp_ack,
1724 unsigned char tcp_ctl,
1725 int unreachable,
1726 size_t *_packet_len)
1728 uint8_t *base;
1729 uint8_t *buf;
1730 struct swrap_packet_frame *frame;
1731 union swrap_packet_ip *ip;
1732 union swrap_packet_payload *pay;
1733 size_t packet_len;
1734 size_t alloc_len;
1735 size_t nonwire_len = sizeof(*frame);
1736 size_t wire_hdr_len = 0;
1737 size_t wire_len = 0;
1738 size_t ip_hdr_len = 0;
1739 size_t icmp_hdr_len = 0;
1740 size_t icmp_truncate_len = 0;
1741 uint8_t protocol = 0, icmp_protocol = 0;
1742 const struct sockaddr_in *src_in = NULL;
1743 const struct sockaddr_in *dest_in = NULL;
1744 #ifdef HAVE_IPV6
1745 const struct sockaddr_in6 *src_in6 = NULL;
1746 const struct sockaddr_in6 *dest_in6 = NULL;
1747 #endif
1748 uint16_t src_port;
1749 uint16_t dest_port;
1751 switch (src->sa_family) {
1752 case AF_INET:
1753 src_in = (const struct sockaddr_in *)(const void *)src;
1754 dest_in = (const struct sockaddr_in *)(const void *)dest;
1755 src_port = src_in->sin_port;
1756 dest_port = dest_in->sin_port;
1757 ip_hdr_len = sizeof(ip->v4);
1758 break;
1759 #ifdef HAVE_IPV6
1760 case AF_INET6:
1761 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1762 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1763 src_port = src_in6->sin6_port;
1764 dest_port = dest_in6->sin6_port;
1765 ip_hdr_len = sizeof(ip->v6);
1766 break;
1767 #endif
1768 default:
1769 return NULL;
1772 switch (socket_type) {
1773 case SOCK_STREAM:
1774 protocol = 0x06; /* TCP */
1775 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1776 wire_len = wire_hdr_len + payload_len;
1777 break;
1779 case SOCK_DGRAM:
1780 protocol = 0x11; /* UDP */
1781 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1782 wire_len = wire_hdr_len + payload_len;
1783 break;
1785 default:
1786 return NULL;
1789 if (unreachable) {
1790 icmp_protocol = protocol;
1791 switch (src->sa_family) {
1792 case AF_INET:
1793 protocol = 0x01; /* ICMPv4 */
1794 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1795 break;
1796 #ifdef HAVE_IPV6
1797 case AF_INET6:
1798 protocol = 0x3A; /* ICMPv6 */
1799 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1800 break;
1801 #endif
1803 if (wire_len > 64 ) {
1804 icmp_truncate_len = wire_len - 64;
1806 wire_hdr_len += icmp_hdr_len;
1807 wire_len += icmp_hdr_len;
1810 packet_len = nonwire_len + wire_len;
1811 alloc_len = packet_len;
1812 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1813 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1816 base = (uint8_t *)malloc(alloc_len);
1817 if (base == NULL) {
1818 return NULL;
1820 memset(base, 0x0, alloc_len);
1822 buf = base;
1824 frame = (struct swrap_packet_frame *)(void *)buf;
1825 frame->seconds = tval->tv_sec;
1826 frame->micro_seconds = tval->tv_usec;
1827 frame->recorded_length = wire_len - icmp_truncate_len;
1828 frame->full_length = wire_len - icmp_truncate_len;
1829 buf += SWRAP_PACKET_FRAME_SIZE;
1831 ip = (union swrap_packet_ip *)(void *)buf;
1832 switch (src->sa_family) {
1833 case AF_INET:
1834 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1835 ip->v4.tos = 0x00;
1836 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1837 ip->v4.identification = htons(0xFFFF);
1838 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1839 ip->v4.fragment = htons(0x0000);
1840 ip->v4.ttl = 0xFF;
1841 ip->v4.protocol = protocol;
1842 ip->v4.hdr_checksum = htons(0x0000);
1843 ip->v4.src_addr = src_in->sin_addr.s_addr;
1844 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1845 buf += SWRAP_PACKET_IP_V4_SIZE;
1846 break;
1847 #ifdef HAVE_IPV6
1848 case AF_INET6:
1849 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1850 ip->v6.flow_label_high = 0x00;
1851 ip->v6.flow_label_low = 0x0000;
1852 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1853 ip->v6.next_header = protocol;
1854 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1855 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1856 buf += SWRAP_PACKET_IP_V6_SIZE;
1857 break;
1858 #endif
1861 if (unreachable) {
1862 pay = (union swrap_packet_payload *)(void *)buf;
1863 switch (src->sa_family) {
1864 case AF_INET:
1865 pay->icmp4.type = 0x03; /* destination unreachable */
1866 pay->icmp4.code = 0x01; /* host unreachable */
1867 pay->icmp4.checksum = htons(0x0000);
1868 pay->icmp4.unused = htonl(0x00000000);
1869 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1871 /* set the ip header in the ICMP payload */
1872 ip = (union swrap_packet_ip *)(void *)buf;
1873 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1874 ip->v4.tos = 0x00;
1875 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1876 ip->v4.identification = htons(0xFFFF);
1877 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1878 ip->v4.fragment = htons(0x0000);
1879 ip->v4.ttl = 0xFF;
1880 ip->v4.protocol = icmp_protocol;
1881 ip->v4.hdr_checksum = htons(0x0000);
1882 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1883 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1884 buf += SWRAP_PACKET_IP_V4_SIZE;
1886 src_port = dest_in->sin_port;
1887 dest_port = src_in->sin_port;
1888 break;
1889 #ifdef HAVE_IPV6
1890 case AF_INET6:
1891 pay->icmp6.type = 0x01; /* destination unreachable */
1892 pay->icmp6.code = 0x03; /* address unreachable */
1893 pay->icmp6.checksum = htons(0x0000);
1894 pay->icmp6.unused = htonl(0x00000000);
1895 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1897 /* set the ip header in the ICMP payload */
1898 ip = (union swrap_packet_ip *)(void *)buf;
1899 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1900 ip->v6.flow_label_high = 0x00;
1901 ip->v6.flow_label_low = 0x0000;
1902 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1903 ip->v6.next_header = protocol;
1904 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1905 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1906 buf += SWRAP_PACKET_IP_V6_SIZE;
1908 src_port = dest_in6->sin6_port;
1909 dest_port = src_in6->sin6_port;
1910 break;
1911 #endif
1915 pay = (union swrap_packet_payload *)(void *)buf;
1917 switch (socket_type) {
1918 case SOCK_STREAM:
1919 pay->tcp.source_port = src_port;
1920 pay->tcp.dest_port = dest_port;
1921 pay->tcp.seq_num = htonl(tcp_seqno);
1922 pay->tcp.ack_num = htonl(tcp_ack);
1923 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1924 pay->tcp.control = tcp_ctl;
1925 pay->tcp.window = htons(0x7FFF);
1926 pay->tcp.checksum = htons(0x0000);
1927 pay->tcp.urg = htons(0x0000);
1928 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1930 break;
1932 case SOCK_DGRAM:
1933 pay->udp.source_port = src_port;
1934 pay->udp.dest_port = dest_port;
1935 pay->udp.length = htons(8 + payload_len);
1936 pay->udp.checksum = htons(0x0000);
1937 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1939 break;
1942 if (payload && payload_len > 0) {
1943 memcpy(buf, payload, payload_len);
1946 *_packet_len = packet_len - icmp_truncate_len;
1947 return base;
1950 static int swrap_pcap_get_fd(const char *fname)
1952 static int fd = -1;
1954 if (fd != -1) return fd;
1956 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1957 if (fd != -1) {
1958 struct swrap_file_hdr file_hdr;
1959 file_hdr.magic = 0xA1B2C3D4;
1960 file_hdr.version_major = 0x0002;
1961 file_hdr.version_minor = 0x0004;
1962 file_hdr.timezone = 0x00000000;
1963 file_hdr.sigfigs = 0x00000000;
1964 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1965 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1967 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1968 close(fd);
1969 fd = -1;
1971 return fd;
1974 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1976 return fd;
1979 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
1980 const struct sockaddr *addr,
1981 enum swrap_packet_type type,
1982 const void *buf, size_t len,
1983 size_t *packet_len)
1985 const struct sockaddr *src_addr;
1986 const struct sockaddr *dest_addr;
1987 unsigned long tcp_seqno = 0;
1988 unsigned long tcp_ack = 0;
1989 unsigned char tcp_ctl = 0;
1990 int unreachable = 0;
1992 struct timeval tv;
1994 switch (si->family) {
1995 case AF_INET:
1996 break;
1997 #ifdef HAVE_IPV6
1998 case AF_INET6:
1999 break;
2000 #endif
2001 default:
2002 return NULL;
2005 switch (type) {
2006 case SWRAP_CONNECT_SEND:
2007 if (si->type != SOCK_STREAM) return NULL;
2009 src_addr = &si->myname.sa.s;
2010 dest_addr = addr;
2012 tcp_seqno = si->io.pck_snd;
2013 tcp_ack = si->io.pck_rcv;
2014 tcp_ctl = 0x02; /* SYN */
2016 si->io.pck_snd += 1;
2018 break;
2020 case SWRAP_CONNECT_RECV:
2021 if (si->type != SOCK_STREAM) return NULL;
2023 dest_addr = &si->myname.sa.s;
2024 src_addr = addr;
2026 tcp_seqno = si->io.pck_rcv;
2027 tcp_ack = si->io.pck_snd;
2028 tcp_ctl = 0x12; /** SYN,ACK */
2030 si->io.pck_rcv += 1;
2032 break;
2034 case SWRAP_CONNECT_UNREACH:
2035 if (si->type != SOCK_STREAM) return NULL;
2037 dest_addr = &si->myname.sa.s;
2038 src_addr = addr;
2040 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2041 tcp_seqno = si->io.pck_snd - 1;
2042 tcp_ack = si->io.pck_rcv;
2043 tcp_ctl = 0x02; /* SYN */
2044 unreachable = 1;
2046 break;
2048 case SWRAP_CONNECT_ACK:
2049 if (si->type != SOCK_STREAM) return NULL;
2051 src_addr = &si->myname.sa.s;
2052 dest_addr = addr;
2054 tcp_seqno = si->io.pck_snd;
2055 tcp_ack = si->io.pck_rcv;
2056 tcp_ctl = 0x10; /* ACK */
2058 break;
2060 case SWRAP_ACCEPT_SEND:
2061 if (si->type != SOCK_STREAM) return NULL;
2063 dest_addr = &si->myname.sa.s;
2064 src_addr = addr;
2066 tcp_seqno = si->io.pck_rcv;
2067 tcp_ack = si->io.pck_snd;
2068 tcp_ctl = 0x02; /* SYN */
2070 si->io.pck_rcv += 1;
2072 break;
2074 case SWRAP_ACCEPT_RECV:
2075 if (si->type != SOCK_STREAM) return NULL;
2077 src_addr = &si->myname.sa.s;
2078 dest_addr = addr;
2080 tcp_seqno = si->io.pck_snd;
2081 tcp_ack = si->io.pck_rcv;
2082 tcp_ctl = 0x12; /* SYN,ACK */
2084 si->io.pck_snd += 1;
2086 break;
2088 case SWRAP_ACCEPT_ACK:
2089 if (si->type != SOCK_STREAM) return NULL;
2091 dest_addr = &si->myname.sa.s;
2092 src_addr = addr;
2094 tcp_seqno = si->io.pck_rcv;
2095 tcp_ack = si->io.pck_snd;
2096 tcp_ctl = 0x10; /* ACK */
2098 break;
2100 case SWRAP_SEND:
2101 src_addr = &si->myname.sa.s;
2102 dest_addr = &si->peername.sa.s;
2104 tcp_seqno = si->io.pck_snd;
2105 tcp_ack = si->io.pck_rcv;
2106 tcp_ctl = 0x18; /* PSH,ACK */
2108 si->io.pck_snd += len;
2110 break;
2112 case SWRAP_SEND_RST:
2113 dest_addr = &si->myname.sa.s;
2114 src_addr = &si->peername.sa.s;
2116 if (si->type == SOCK_DGRAM) {
2117 return swrap_pcap_marshall_packet(si,
2118 &si->peername.sa.s,
2119 SWRAP_SENDTO_UNREACH,
2120 buf,
2121 len,
2122 packet_len);
2125 tcp_seqno = si->io.pck_rcv;
2126 tcp_ack = si->io.pck_snd;
2127 tcp_ctl = 0x14; /** RST,ACK */
2129 break;
2131 case SWRAP_PENDING_RST:
2132 dest_addr = &si->myname.sa.s;
2133 src_addr = &si->peername.sa.s;
2135 if (si->type == SOCK_DGRAM) {
2136 return NULL;
2139 tcp_seqno = si->io.pck_rcv;
2140 tcp_ack = si->io.pck_snd;
2141 tcp_ctl = 0x14; /* RST,ACK */
2143 break;
2145 case SWRAP_RECV:
2146 dest_addr = &si->myname.sa.s;
2147 src_addr = &si->peername.sa.s;
2149 tcp_seqno = si->io.pck_rcv;
2150 tcp_ack = si->io.pck_snd;
2151 tcp_ctl = 0x18; /* PSH,ACK */
2153 si->io.pck_rcv += len;
2155 break;
2157 case SWRAP_RECV_RST:
2158 dest_addr = &si->myname.sa.s;
2159 src_addr = &si->peername.sa.s;
2161 if (si->type == SOCK_DGRAM) {
2162 return NULL;
2165 tcp_seqno = si->io.pck_rcv;
2166 tcp_ack = si->io.pck_snd;
2167 tcp_ctl = 0x14; /* RST,ACK */
2169 break;
2171 case SWRAP_SENDTO:
2172 src_addr = &si->myname.sa.s;
2173 dest_addr = addr;
2175 si->io.pck_snd += len;
2177 break;
2179 case SWRAP_SENDTO_UNREACH:
2180 dest_addr = &si->myname.sa.s;
2181 src_addr = addr;
2183 unreachable = 1;
2185 break;
2187 case SWRAP_RECVFROM:
2188 dest_addr = &si->myname.sa.s;
2189 src_addr = addr;
2191 si->io.pck_rcv += len;
2193 break;
2195 case SWRAP_CLOSE_SEND:
2196 if (si->type != SOCK_STREAM) return NULL;
2198 src_addr = &si->myname.sa.s;
2199 dest_addr = &si->peername.sa.s;
2201 tcp_seqno = si->io.pck_snd;
2202 tcp_ack = si->io.pck_rcv;
2203 tcp_ctl = 0x11; /* FIN, ACK */
2205 si->io.pck_snd += 1;
2207 break;
2209 case SWRAP_CLOSE_RECV:
2210 if (si->type != SOCK_STREAM) return NULL;
2212 dest_addr = &si->myname.sa.s;
2213 src_addr = &si->peername.sa.s;
2215 tcp_seqno = si->io.pck_rcv;
2216 tcp_ack = si->io.pck_snd;
2217 tcp_ctl = 0x11; /* FIN,ACK */
2219 si->io.pck_rcv += 1;
2221 break;
2223 case SWRAP_CLOSE_ACK:
2224 if (si->type != SOCK_STREAM) return NULL;
2226 src_addr = &si->myname.sa.s;
2227 dest_addr = &si->peername.sa.s;
2229 tcp_seqno = si->io.pck_snd;
2230 tcp_ack = si->io.pck_rcv;
2231 tcp_ctl = 0x10; /* ACK */
2233 break;
2234 default:
2235 return NULL;
2238 swrapGetTimeOfDay(&tv);
2240 return swrap_pcap_packet_init(&tv,
2241 src_addr,
2242 dest_addr,
2243 si->type,
2244 (const uint8_t *)buf,
2245 len,
2246 tcp_seqno,
2247 tcp_ack,
2248 tcp_ctl,
2249 unreachable,
2250 packet_len);
2253 static void swrap_pcap_dump_packet(struct socket_info *si,
2254 const struct sockaddr *addr,
2255 enum swrap_packet_type type,
2256 const void *buf, size_t len)
2258 const char *file_name;
2259 uint8_t *packet;
2260 size_t packet_len = 0;
2261 int fd;
2263 file_name = swrap_pcap_init_file();
2264 if (!file_name) {
2265 return;
2268 packet = swrap_pcap_marshall_packet(si,
2269 addr,
2270 type,
2271 buf,
2272 len,
2273 &packet_len);
2274 if (packet == NULL) {
2275 return;
2278 fd = swrap_pcap_get_fd(file_name);
2279 if (fd != -1) {
2280 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2281 free(packet);
2282 return;
2286 free(packet);
2289 /****************************************************************************
2290 * SIGNALFD
2291 ***************************************************************************/
2293 #ifdef HAVE_SIGNALFD
2294 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2296 int rc;
2298 rc = libc_signalfd(fd, mask, flags);
2299 if (rc != -1) {
2300 swrap_remove_stale(fd);
2303 return rc;
2306 int signalfd(int fd, const sigset_t *mask, int flags)
2308 return swrap_signalfd(fd, mask, flags);
2310 #endif
2312 /****************************************************************************
2313 * SOCKET
2314 ***************************************************************************/
2316 static int swrap_socket(int family, int type, int protocol)
2318 struct socket_info *si;
2319 struct socket_info_fd *fi;
2320 int fd;
2321 int real_type = type;
2324 * Remove possible addition flags passed to socket() so
2325 * do not fail checking the type.
2326 * See https://lwn.net/Articles/281965/
2328 #ifdef SOCK_CLOEXEC
2329 real_type &= ~SOCK_CLOEXEC;
2330 #endif
2331 #ifdef SOCK_NONBLOCK
2332 real_type &= ~SOCK_NONBLOCK;
2333 #endif
2335 if (!socket_wrapper_enabled()) {
2336 return libc_socket(family, type, protocol);
2339 switch (family) {
2340 case AF_INET:
2341 #ifdef HAVE_IPV6
2342 case AF_INET6:
2343 #endif
2344 break;
2345 case AF_UNIX:
2346 return libc_socket(family, type, protocol);
2347 default:
2348 errno = EAFNOSUPPORT;
2349 return -1;
2352 switch (real_type) {
2353 case SOCK_STREAM:
2354 break;
2355 case SOCK_DGRAM:
2356 break;
2357 default:
2358 errno = EPROTONOSUPPORT;
2359 return -1;
2362 switch (protocol) {
2363 case 0:
2364 break;
2365 case 6:
2366 if (real_type == SOCK_STREAM) {
2367 break;
2369 /*fall through*/
2370 case 17:
2371 if (real_type == SOCK_DGRAM) {
2372 break;
2374 /*fall through*/
2375 default:
2376 errno = EPROTONOSUPPORT;
2377 return -1;
2381 * We must call libc_socket with type, from the caller, not the version
2382 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2384 fd = libc_socket(AF_UNIX, type, 0);
2386 if (fd == -1) {
2387 return -1;
2390 /* Check if we have a stale fd and remove it */
2391 si = find_socket_info(fd);
2392 if (si != NULL) {
2393 swrap_remove_stale(fd);
2396 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2397 memset(si, 0, sizeof(struct socket_info));
2398 if (si == NULL) {
2399 errno = ENOMEM;
2400 return -1;
2403 si->family = family;
2405 /* however, the rest of the socket_wrapper code expects just
2406 * the type, not the flags */
2407 si->type = real_type;
2408 si->protocol = protocol;
2411 * Setup myname so getsockname() can succeed to find out the socket
2412 * type.
2414 switch(si->family) {
2415 case AF_INET: {
2416 struct sockaddr_in sin = {
2417 .sin_family = AF_INET,
2420 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2421 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2422 break;
2424 case AF_INET6: {
2425 struct sockaddr_in6 sin6 = {
2426 .sin6_family = AF_INET6,
2429 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2430 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2431 break;
2433 default:
2434 free(si);
2435 errno = EINVAL;
2436 return -1;
2439 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2440 if (fi == NULL) {
2441 free(si);
2442 errno = ENOMEM;
2443 return -1;
2446 fi->fd = fd;
2448 SWRAP_DLIST_ADD(si->fds, fi);
2449 SWRAP_DLIST_ADD(sockets, si);
2451 SWRAP_LOG(SWRAP_LOG_TRACE,
2452 "Created %s socket for protocol %s",
2453 si->family == AF_INET ? "IPv4" : "IPv6",
2454 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2456 return fd;
2459 int socket(int family, int type, int protocol)
2461 return swrap_socket(family, type, protocol);
2464 /****************************************************************************
2465 * SOCKETPAIR
2466 ***************************************************************************/
2468 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2470 int rc;
2472 rc = libc_socketpair(family, type, protocol, sv);
2473 if (rc != -1) {
2474 swrap_remove_stale(sv[0]);
2475 swrap_remove_stale(sv[1]);
2478 return rc;
2481 int socketpair(int family, int type, int protocol, int sv[2])
2483 return swrap_socketpair(family, type, protocol, sv);
2486 /****************************************************************************
2487 * SOCKETPAIR
2488 ***************************************************************************/
2490 #ifdef HAVE_TIMERFD_CREATE
2491 static int swrap_timerfd_create(int clockid, int flags)
2493 int fd;
2495 fd = libc_timerfd_create(clockid, flags);
2496 if (fd != -1) {
2497 swrap_remove_stale(fd);
2500 return fd;
2503 int timerfd_create(int clockid, int flags)
2505 return swrap_timerfd_create(clockid, flags);
2507 #endif
2509 /****************************************************************************
2510 * PIPE
2511 ***************************************************************************/
2513 static int swrap_pipe(int pipefd[2])
2515 int rc;
2517 rc = libc_pipe(pipefd);
2518 if (rc != -1) {
2519 swrap_remove_stale(pipefd[0]);
2520 swrap_remove_stale(pipefd[1]);
2523 return rc;
2526 int pipe(int pipefd[2])
2528 return swrap_pipe(pipefd);
2531 /****************************************************************************
2532 * ACCEPT
2533 ***************************************************************************/
2535 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2537 struct socket_info *parent_si, *child_si;
2538 struct socket_info_fd *child_fi;
2539 int fd;
2540 struct swrap_address un_addr = {
2541 .sa_socklen = sizeof(struct sockaddr_un),
2543 struct swrap_address un_my_addr = {
2544 .sa_socklen = sizeof(struct sockaddr_un),
2546 struct swrap_address in_addr = {
2547 .sa_socklen = sizeof(struct sockaddr_storage),
2549 struct swrap_address in_my_addr = {
2550 .sa_socklen = sizeof(struct sockaddr_storage),
2552 int ret;
2554 parent_si = find_socket_info(s);
2555 if (!parent_si) {
2556 return libc_accept(s, addr, addrlen);
2560 * assume out sockaddr have the same size as the in parent
2561 * socket family
2563 in_addr.sa_socklen = socket_length(parent_si->family);
2564 if (in_addr.sa_socklen <= 0) {
2565 errno = EINVAL;
2566 return -1;
2569 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2570 if (ret == -1) {
2571 if (errno == ENOTSOCK) {
2572 /* Remove stale fds */
2573 swrap_remove_stale(s);
2575 return ret;
2578 fd = ret;
2580 ret = sockaddr_convert_from_un(parent_si,
2581 &un_addr.sa.un,
2582 un_addr.sa_socklen,
2583 parent_si->family,
2584 &in_addr.sa.s,
2585 &in_addr.sa_socklen);
2586 if (ret == -1) {
2587 close(fd);
2588 return ret;
2591 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2592 memset(child_si, 0, sizeof(struct socket_info));
2594 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2595 if (child_fi == NULL) {
2596 free(child_si);
2597 close(fd);
2598 errno = ENOMEM;
2599 return -1;
2602 child_fi->fd = fd;
2604 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2606 child_si->family = parent_si->family;
2607 child_si->type = parent_si->type;
2608 child_si->protocol = parent_si->protocol;
2609 child_si->bound = 1;
2610 child_si->is_server = 1;
2611 child_si->connected = 1;
2613 child_si->peername = (struct swrap_address) {
2614 .sa_socklen = in_addr.sa_socklen,
2616 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2618 if (addr != NULL && addrlen != NULL) {
2619 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2620 if (copy_len > 0) {
2621 memcpy(addr, &in_addr.sa.ss, copy_len);
2623 *addrlen = in_addr.sa_socklen;
2626 ret = libc_getsockname(fd,
2627 &un_my_addr.sa.s,
2628 &un_my_addr.sa_socklen);
2629 if (ret == -1) {
2630 free(child_fi);
2631 free(child_si);
2632 close(fd);
2633 return ret;
2636 ret = sockaddr_convert_from_un(child_si,
2637 &un_my_addr.sa.un,
2638 un_my_addr.sa_socklen,
2639 child_si->family,
2640 &in_my_addr.sa.s,
2641 &in_my_addr.sa_socklen);
2642 if (ret == -1) {
2643 free(child_fi);
2644 free(child_si);
2645 close(fd);
2646 return ret;
2649 SWRAP_LOG(SWRAP_LOG_TRACE,
2650 "accept() path=%s, fd=%d",
2651 un_my_addr.sa.un.sun_path, s);
2653 child_si->myname = (struct swrap_address) {
2654 .sa_socklen = in_my_addr.sa_socklen,
2656 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2658 SWRAP_DLIST_ADD(sockets, child_si);
2660 if (addr != NULL) {
2661 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2662 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2663 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2666 return fd;
2669 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2670 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2671 #else
2672 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2673 #endif
2675 return swrap_accept(s, addr, (socklen_t *)addrlen);
2678 static int autobind_start_init;
2679 static int autobind_start;
2681 /* using sendto() or connect() on an unbound socket would give the
2682 recipient no way to reply, as unlike UDP and TCP, a unix domain
2683 socket can't auto-assign ephemeral port numbers, so we need to
2684 assign it here.
2685 Note: this might change the family from ipv6 to ipv4
2687 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2689 struct swrap_address un_addr = {
2690 .sa_socklen = sizeof(struct sockaddr_un),
2692 int i;
2693 char type;
2694 int ret;
2695 int port;
2696 struct stat st;
2698 if (autobind_start_init != 1) {
2699 autobind_start_init = 1;
2700 autobind_start = getpid();
2701 autobind_start %= 50000;
2702 autobind_start += 10000;
2705 un_addr.sa.un.sun_family = AF_UNIX;
2707 switch (family) {
2708 case AF_INET: {
2709 struct sockaddr_in in;
2711 switch (si->type) {
2712 case SOCK_STREAM:
2713 type = SOCKET_TYPE_CHAR_TCP;
2714 break;
2715 case SOCK_DGRAM:
2716 type = SOCKET_TYPE_CHAR_UDP;
2717 break;
2718 default:
2719 errno = ESOCKTNOSUPPORT;
2720 return -1;
2723 memset(&in, 0, sizeof(in));
2724 in.sin_family = AF_INET;
2725 in.sin_addr.s_addr = htonl(127<<24 |
2726 socket_wrapper_default_iface());
2728 si->myname = (struct swrap_address) {
2729 .sa_socklen = sizeof(in),
2731 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2732 break;
2734 #ifdef HAVE_IPV6
2735 case AF_INET6: {
2736 struct sockaddr_in6 in6;
2738 if (si->family != family) {
2739 errno = ENETUNREACH;
2740 return -1;
2743 switch (si->type) {
2744 case SOCK_STREAM:
2745 type = SOCKET_TYPE_CHAR_TCP_V6;
2746 break;
2747 case SOCK_DGRAM:
2748 type = SOCKET_TYPE_CHAR_UDP_V6;
2749 break;
2750 default:
2751 errno = ESOCKTNOSUPPORT;
2752 return -1;
2755 memset(&in6, 0, sizeof(in6));
2756 in6.sin6_family = AF_INET6;
2757 in6.sin6_addr = *swrap_ipv6();
2758 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2760 si->myname = (struct swrap_address) {
2761 .sa_socklen = sizeof(in6),
2763 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2764 break;
2766 #endif
2767 default:
2768 errno = ESOCKTNOSUPPORT;
2769 return -1;
2772 if (autobind_start > 60000) {
2773 autobind_start = 10000;
2776 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2777 port = autobind_start + i;
2778 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2779 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2780 type, socket_wrapper_default_iface(), port);
2781 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2783 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2784 if (ret == -1) return ret;
2786 si->un_addr = un_addr.sa.un;
2788 si->bound = 1;
2789 autobind_start = port + 1;
2790 break;
2792 if (i == SOCKET_MAX_SOCKETS) {
2793 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2794 "interface "SOCKET_FORMAT,
2795 SOCKET_MAX_SOCKETS,
2796 type,
2797 socket_wrapper_default_iface(),
2799 errno = ENFILE;
2800 return -1;
2803 si->family = family;
2804 set_port(si->family, port, &si->myname);
2806 return 0;
2809 /****************************************************************************
2810 * CONNECT
2811 ***************************************************************************/
2813 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2814 socklen_t addrlen)
2816 int ret;
2817 struct swrap_address un_addr = {
2818 .sa_socklen = sizeof(struct sockaddr_un),
2820 struct socket_info *si = find_socket_info(s);
2821 int bcast = 0;
2823 if (!si) {
2824 return libc_connect(s, serv_addr, addrlen);
2827 if (si->bound == 0) {
2828 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2829 if (ret == -1) return -1;
2832 if (si->family != serv_addr->sa_family) {
2833 errno = EINVAL;
2834 return -1;
2837 ret = sockaddr_convert_to_un(si, serv_addr,
2838 addrlen, &un_addr.sa.un, 0, &bcast);
2839 if (ret == -1) return -1;
2841 if (bcast) {
2842 errno = ENETUNREACH;
2843 return -1;
2846 if (si->type == SOCK_DGRAM) {
2847 si->defer_connect = 1;
2848 ret = 0;
2849 } else {
2850 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2852 ret = libc_connect(s,
2853 &un_addr.sa.s,
2854 un_addr.sa_socklen);
2857 SWRAP_LOG(SWRAP_LOG_TRACE,
2858 "connect() path=%s, fd=%d",
2859 un_addr.sa.un.sun_path, s);
2862 /* to give better errors */
2863 if (ret == -1 && errno == ENOENT) {
2864 errno = EHOSTUNREACH;
2867 if (ret == 0) {
2868 si->peername = (struct swrap_address) {
2869 .sa_socklen = addrlen,
2872 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2873 si->connected = 1;
2876 * When we connect() on a socket than we have to bind the
2877 * outgoing connection on the interface we use for the
2878 * transport. We already bound it on the right interface
2879 * but here we have to update the name so getsockname()
2880 * returns correct information.
2882 if (si->bindname.sa_socklen > 0) {
2883 si->myname = (struct swrap_address) {
2884 .sa_socklen = si->bindname.sa_socklen,
2887 memcpy(&si->myname.sa.ss,
2888 &si->bindname.sa.ss,
2889 si->bindname.sa_socklen);
2891 /* Cleanup bindname */
2892 si->bindname = (struct swrap_address) {
2893 .sa_socklen = 0,
2897 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2898 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2899 } else {
2900 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2903 return ret;
2906 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2908 return swrap_connect(s, serv_addr, addrlen);
2911 /****************************************************************************
2912 * BIND
2913 ***************************************************************************/
2915 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2917 int ret;
2918 struct swrap_address un_addr = {
2919 .sa_socklen = sizeof(struct sockaddr_un),
2921 struct socket_info *si = find_socket_info(s);
2922 int bind_error = 0;
2923 #if 0 /* FIXME */
2924 bool in_use;
2925 #endif
2927 if (!si) {
2928 return libc_bind(s, myaddr, addrlen);
2931 switch (si->family) {
2932 case AF_INET: {
2933 const struct sockaddr_in *sin;
2934 if (addrlen < sizeof(struct sockaddr_in)) {
2935 bind_error = EINVAL;
2936 break;
2939 sin = (const struct sockaddr_in *)(const void *)myaddr;
2941 if (sin->sin_family != AF_INET) {
2942 bind_error = EAFNOSUPPORT;
2945 /* special case for AF_UNSPEC */
2946 if (sin->sin_family == AF_UNSPEC &&
2947 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2949 bind_error = 0;
2952 break;
2954 #ifdef HAVE_IPV6
2955 case AF_INET6: {
2956 const struct sockaddr_in6 *sin6;
2957 if (addrlen < sizeof(struct sockaddr_in6)) {
2958 bind_error = EINVAL;
2959 break;
2962 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
2964 if (sin6->sin6_family != AF_INET6) {
2965 bind_error = EAFNOSUPPORT;
2968 break;
2970 #endif
2971 default:
2972 bind_error = EINVAL;
2973 break;
2976 if (bind_error != 0) {
2977 errno = bind_error;
2978 return -1;
2981 #if 0 /* FIXME */
2982 in_use = check_addr_port_in_use(myaddr, addrlen);
2983 if (in_use) {
2984 errno = EADDRINUSE;
2985 return -1;
2987 #endif
2989 si->myname.sa_socklen = addrlen;
2990 memcpy(&si->myname.sa.ss, myaddr, addrlen);
2992 ret = sockaddr_convert_to_un(si,
2993 myaddr,
2994 addrlen,
2995 &un_addr.sa.un,
2997 &si->bcast);
2998 if (ret == -1) return -1;
3000 unlink(un_addr.sa.un.sun_path);
3002 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3004 SWRAP_LOG(SWRAP_LOG_TRACE,
3005 "bind() path=%s, fd=%d",
3006 un_addr.sa.un.sun_path, s);
3008 if (ret == 0) {
3009 si->bound = 1;
3012 return ret;
3015 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3017 return swrap_bind(s, myaddr, addrlen);
3020 /****************************************************************************
3021 * BINDRESVPORT
3022 ***************************************************************************/
3024 #ifdef HAVE_BINDRESVPORT
3025 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3027 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3029 struct swrap_address myaddr = {
3030 .sa_socklen = sizeof(struct sockaddr_storage),
3032 socklen_t salen;
3033 static uint16_t port;
3034 uint16_t i;
3035 int rc = -1;
3036 int af;
3038 #define SWRAP_STARTPORT 600
3039 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3040 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3042 if (port == 0) {
3043 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3046 if (sa == NULL) {
3047 salen = myaddr.sa_socklen;
3048 sa = &myaddr.sa.s;
3050 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3051 if (rc < 0) {
3052 return -1;
3055 af = sa->sa_family;
3056 memset(&myaddr.sa.ss, 0, salen);
3057 } else {
3058 af = sa->sa_family;
3061 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3062 switch(af) {
3063 case AF_INET: {
3064 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3066 salen = sizeof(struct sockaddr_in);
3067 sinp->sin_port = htons(port);
3068 break;
3070 case AF_INET6: {
3071 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3073 salen = sizeof(struct sockaddr_in6);
3074 sin6p->sin6_port = htons(port);
3075 break;
3077 default:
3078 errno = EAFNOSUPPORT;
3079 return -1;
3081 sa->sa_family = af;
3083 if (port > SWRAP_ENDPORT) {
3084 port = SWRAP_STARTPORT;
3087 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3088 if (rc == 0 || errno != EADDRINUSE) {
3089 break;
3093 return rc;
3096 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3098 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3100 #endif
3102 /****************************************************************************
3103 * LISTEN
3104 ***************************************************************************/
3106 static int swrap_listen(int s, int backlog)
3108 int ret;
3109 struct socket_info *si = find_socket_info(s);
3111 if (!si) {
3112 return libc_listen(s, backlog);
3115 ret = libc_listen(s, backlog);
3117 return ret;
3120 int listen(int s, int backlog)
3122 return swrap_listen(s, backlog);
3125 /****************************************************************************
3126 * FOPEN
3127 ***************************************************************************/
3129 static FILE *swrap_fopen(const char *name, const char *mode)
3131 FILE *fp;
3133 fp = libc_fopen(name, mode);
3134 if (fp != NULL) {
3135 int fd = fileno(fp);
3137 swrap_remove_stale(fd);
3140 return fp;
3143 FILE *fopen(const char *name, const char *mode)
3145 return swrap_fopen(name, mode);
3148 /****************************************************************************
3149 * OPEN
3150 ***************************************************************************/
3152 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3154 int ret;
3156 ret = libc_vopen(pathname, flags, ap);
3157 if (ret != -1) {
3159 * There are methods for closing descriptors (libc-internal code
3160 * paths, direct syscalls) which close descriptors in ways that
3161 * we can't intercept, so try to recover when we notice that
3162 * that's happened
3164 swrap_remove_stale(ret);
3166 return ret;
3169 int open(const char *pathname, int flags, ...)
3171 va_list ap;
3172 int fd;
3174 va_start(ap, flags);
3175 fd = swrap_vopen(pathname, flags, ap);
3176 va_end(ap);
3178 return fd;
3181 /****************************************************************************
3182 * GETPEERNAME
3183 ***************************************************************************/
3185 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3187 struct socket_info *si = find_socket_info(s);
3188 socklen_t len;
3190 if (!si) {
3191 return libc_getpeername(s, name, addrlen);
3194 if (si->peername.sa_socklen == 0)
3196 errno = ENOTCONN;
3197 return -1;
3200 len = MIN(*addrlen, si->peername.sa_socklen);
3201 if (len == 0) {
3202 return 0;
3205 memcpy(name, &si->peername.sa.ss, len);
3206 *addrlen = si->peername.sa_socklen;
3208 return 0;
3211 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3212 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3213 #else
3214 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3215 #endif
3217 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3220 /****************************************************************************
3221 * GETSOCKNAME
3222 ***************************************************************************/
3224 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3226 struct socket_info *si = find_socket_info(s);
3227 socklen_t len;
3229 if (!si) {
3230 return libc_getsockname(s, name, addrlen);
3233 len = MIN(*addrlen, si->myname.sa_socklen);
3234 if (len == 0) {
3235 return 0;
3238 memcpy(name, &si->myname.sa.ss, len);
3239 *addrlen = si->myname.sa_socklen;
3241 return 0;
3244 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3245 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3246 #else
3247 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3248 #endif
3250 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3253 /****************************************************************************
3254 * GETSOCKOPT
3255 ***************************************************************************/
3257 #ifndef SO_PROTOCOL
3258 # ifdef SO_PROTOTYPE /* The Solaris name */
3259 # define SO_PROTOCOL SO_PROTOTYPE
3260 # endif /* SO_PROTOTYPE */
3261 #endif /* SO_PROTOCOL */
3263 static int swrap_getsockopt(int s, int level, int optname,
3264 void *optval, socklen_t *optlen)
3266 struct socket_info *si = find_socket_info(s);
3268 if (!si) {
3269 return libc_getsockopt(s,
3270 level,
3271 optname,
3272 optval,
3273 optlen);
3276 if (level == SOL_SOCKET) {
3277 switch (optname) {
3278 #ifdef SO_DOMAIN
3279 case SO_DOMAIN:
3280 if (optval == NULL || optlen == NULL ||
3281 *optlen < (socklen_t)sizeof(int)) {
3282 errno = EINVAL;
3283 return -1;
3286 *optlen = sizeof(int);
3287 *(int *)optval = si->family;
3288 return 0;
3289 #endif /* SO_DOMAIN */
3291 #ifdef SO_PROTOCOL
3292 case SO_PROTOCOL:
3293 if (optval == NULL || optlen == NULL ||
3294 *optlen < (socklen_t)sizeof(int)) {
3295 errno = EINVAL;
3296 return -1;
3299 *optlen = sizeof(int);
3300 *(int *)optval = si->protocol;
3301 return 0;
3302 #endif /* SO_PROTOCOL */
3303 case SO_TYPE:
3304 if (optval == NULL || optlen == NULL ||
3305 *optlen < (socklen_t)sizeof(int)) {
3306 errno = EINVAL;
3307 return -1;
3310 *optlen = sizeof(int);
3311 *(int *)optval = si->type;
3312 return 0;
3313 default:
3314 return libc_getsockopt(s,
3315 level,
3316 optname,
3317 optval,
3318 optlen);
3322 errno = ENOPROTOOPT;
3323 return -1;
3326 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3327 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3328 #else
3329 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3330 #endif
3332 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3335 /****************************************************************************
3336 * SETSOCKOPT
3337 ***************************************************************************/
3339 static int swrap_setsockopt(int s, int level, int optname,
3340 const void *optval, socklen_t optlen)
3342 struct socket_info *si = find_socket_info(s);
3344 if (!si) {
3345 return libc_setsockopt(s,
3346 level,
3347 optname,
3348 optval,
3349 optlen);
3352 if (level == SOL_SOCKET) {
3353 return libc_setsockopt(s,
3354 level,
3355 optname,
3356 optval,
3357 optlen);
3360 switch (si->family) {
3361 case AF_INET:
3362 if (level == IPPROTO_IP) {
3363 #ifdef IP_PKTINFO
3364 if (optname == IP_PKTINFO) {
3365 si->pktinfo = AF_INET;
3367 #endif /* IP_PKTINFO */
3369 return 0;
3370 #ifdef HAVE_IPV6
3371 case AF_INET6:
3372 if (level == IPPROTO_IPV6) {
3373 #ifdef IPV6_RECVPKTINFO
3374 if (optname == IPV6_RECVPKTINFO) {
3375 si->pktinfo = AF_INET6;
3377 #endif /* IPV6_PKTINFO */
3379 return 0;
3380 #endif
3381 default:
3382 errno = ENOPROTOOPT;
3383 return -1;
3387 int setsockopt(int s, int level, int optname,
3388 const void *optval, socklen_t optlen)
3390 return swrap_setsockopt(s, level, optname, optval, optlen);
3393 /****************************************************************************
3394 * IOCTL
3395 ***************************************************************************/
3397 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3399 struct socket_info *si = find_socket_info(s);
3400 va_list ap;
3401 int value;
3402 int rc;
3404 if (!si) {
3405 return libc_vioctl(s, r, va);
3408 va_copy(ap, va);
3410 rc = libc_vioctl(s, r, va);
3412 switch (r) {
3413 case FIONREAD:
3414 value = *((int *)va_arg(ap, int *));
3416 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3417 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3418 } else if (value == 0) { /* END OF FILE */
3419 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3421 break;
3424 va_end(ap);
3426 return rc;
3429 #ifdef HAVE_IOCTL_INT
3430 int ioctl(int s, int r, ...)
3431 #else
3432 int ioctl(int s, unsigned long int r, ...)
3433 #endif
3435 va_list va;
3436 int rc;
3438 va_start(va, r);
3440 rc = swrap_vioctl(s, (unsigned long int) r, va);
3442 va_end(va);
3444 return rc;
3447 /*****************
3448 * CMSG
3449 *****************/
3451 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3453 #ifndef CMSG_ALIGN
3454 # ifdef _ALIGN /* BSD */
3455 #define CMSG_ALIGN _ALIGN
3456 # else
3457 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3458 # endif /* _ALIGN */
3459 #endif /* CMSG_ALIGN */
3462 * @brief Add a cmsghdr to a msghdr.
3464 * This is an function to add any type of cmsghdr. It will operate on the
3465 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3466 * the buffer position after the added cmsg element. Hence, this function is
3467 * intended to be used with an intermediate msghdr and not on the original
3468 * one handed in by the client.
3470 * @param[in] msg The msghdr to which to add the cmsg.
3472 * @param[in] level The cmsg level to set.
3474 * @param[in] type The cmsg type to set.
3476 * @param[in] data The cmsg data to set.
3478 * @param[in] len the length of the data to set.
3480 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3481 int level,
3482 int type,
3483 const void *data,
3484 size_t len)
3486 size_t cmlen = CMSG_LEN(len);
3487 size_t cmspace = CMSG_SPACE(len);
3488 uint8_t cmbuf[cmspace];
3489 void *cast_ptr = (void *)cmbuf;
3490 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3491 uint8_t *p;
3493 memset(cmbuf, 0, cmspace);
3495 if (msg->msg_controllen < cmlen) {
3496 cmlen = msg->msg_controllen;
3497 msg->msg_flags |= MSG_CTRUNC;
3500 if (msg->msg_controllen < cmspace) {
3501 cmspace = msg->msg_controllen;
3505 * We copy the full input data into an intermediate cmsghdr first
3506 * in order to more easily cope with truncation.
3508 cm->cmsg_len = cmlen;
3509 cm->cmsg_level = level;
3510 cm->cmsg_type = type;
3511 memcpy(CMSG_DATA(cm), data, len);
3514 * We now copy the possibly truncated buffer.
3515 * We copy cmlen bytes, but consume cmspace bytes,
3516 * leaving the possible padding uninitialiazed.
3518 p = (uint8_t *)msg->msg_control;
3519 memcpy(p, cm, cmlen);
3520 p += cmspace;
3521 msg->msg_control = p;
3522 msg->msg_controllen -= cmspace;
3524 return;
3527 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3528 struct msghdr *msg)
3530 /* Add packet info */
3531 switch (si->pktinfo) {
3532 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3533 case AF_INET: {
3534 struct sockaddr_in *sin;
3535 #if defined(HAVE_STRUCT_IN_PKTINFO)
3536 struct in_pktinfo pkt;
3537 #elif defined(IP_RECVDSTADDR)
3538 struct in_addr pkt;
3539 #endif
3541 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3542 sin = &si->bindname.sa.in;
3543 } else {
3544 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3545 return 0;
3547 sin = &si->myname.sa.in;
3550 ZERO_STRUCT(pkt);
3552 #if defined(HAVE_STRUCT_IN_PKTINFO)
3553 pkt.ipi_ifindex = socket_wrapper_default_iface();
3554 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3555 #elif defined(IP_RECVDSTADDR)
3556 pkt = sin->sin_addr;
3557 #endif
3559 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3560 &pkt, sizeof(pkt));
3562 break;
3564 #endif /* IP_PKTINFO */
3565 #if defined(HAVE_IPV6)
3566 case AF_INET6: {
3567 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3568 struct sockaddr_in6 *sin6;
3569 struct in6_pktinfo pkt6;
3571 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3572 sin6 = &si->bindname.sa.in6;
3573 } else {
3574 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3575 return 0;
3577 sin6 = &si->myname.sa.in6;
3580 ZERO_STRUCT(pkt6);
3582 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3583 pkt6.ipi6_addr = sin6->sin6_addr;
3585 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3586 &pkt6, sizeof(pkt6));
3587 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3589 break;
3591 #endif /* IPV6_PKTINFO */
3592 default:
3593 return -1;
3596 return 0;
3599 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3600 struct msghdr *omsg)
3602 int rc = 0;
3604 if (si->pktinfo > 0) {
3605 rc = swrap_msghdr_add_pktinfo(si, omsg);
3608 return rc;
3611 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3612 uint8_t **cm_data,
3613 size_t *cm_data_space);
3614 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3615 uint8_t **cm_data,
3616 size_t *cm_data_space);
3618 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3619 uint8_t **cm_data,
3620 size_t *cm_data_space) {
3621 struct cmsghdr *cmsg;
3622 int rc = -1;
3624 /* Nothing to do */
3625 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3626 return 0;
3629 for (cmsg = CMSG_FIRSTHDR(msg);
3630 cmsg != NULL;
3631 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3632 switch (cmsg->cmsg_level) {
3633 case IPPROTO_IP:
3634 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3635 cm_data,
3636 cm_data_space);
3637 break;
3638 default:
3639 rc = swrap_sendmsg_copy_cmsg(cmsg,
3640 cm_data,
3641 cm_data_space);
3642 break;
3646 return rc;
3649 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3650 uint8_t **cm_data,
3651 size_t *cm_data_space)
3653 size_t cmspace;
3654 uint8_t *p;
3656 cmspace =
3657 (*cm_data_space) +
3658 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3660 p = realloc((*cm_data), cmspace);
3661 if (p == NULL) {
3662 return -1;
3664 (*cm_data) = p;
3666 p = (*cm_data) + (*cm_data_space);
3667 *cm_data_space = cmspace;
3669 memcpy(p, cmsg, cmsg->cmsg_len);
3671 return 0;
3674 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3675 uint8_t **cm_data,
3676 size_t *cm_data_space);
3679 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3680 uint8_t **cm_data,
3681 size_t *cm_data_space)
3683 int rc = -1;
3685 switch(cmsg->cmsg_type) {
3686 #ifdef IP_PKTINFO
3687 case IP_PKTINFO:
3688 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3689 cm_data,
3690 cm_data_space);
3691 break;
3692 #endif
3693 #ifdef IPV6_PKTINFO
3694 case IPV6_PKTINFO:
3695 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3696 cm_data,
3697 cm_data_space);
3698 break;
3699 #endif
3700 default:
3701 break;
3704 return rc;
3707 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3708 uint8_t **cm_data,
3709 size_t *cm_data_space)
3711 (void)cmsg; /* unused */
3712 (void)cm_data; /* unused */
3713 (void)cm_data_space; /* unused */
3716 * Passing a IP pktinfo to a unix socket might be rejected by the
3717 * Kernel, at least on FreeBSD. So skip this cmsg.
3719 return 0;
3721 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3723 static ssize_t swrap_sendmsg_before(int fd,
3724 struct socket_info *si,
3725 struct msghdr *msg,
3726 struct iovec *tmp_iov,
3727 struct sockaddr_un *tmp_un,
3728 const struct sockaddr_un **to_un,
3729 const struct sockaddr **to,
3730 int *bcast)
3732 size_t i, len = 0;
3733 ssize_t ret;
3735 if (to_un) {
3736 *to_un = NULL;
3738 if (to) {
3739 *to = NULL;
3741 if (bcast) {
3742 *bcast = 0;
3745 switch (si->type) {
3746 case SOCK_STREAM:
3747 if (!si->connected) {
3748 errno = ENOTCONN;
3749 return -1;
3752 if (msg->msg_iovlen == 0) {
3753 break;
3756 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3757 size_t nlen;
3758 nlen = len + msg->msg_iov[i].iov_len;
3759 if (nlen > SOCKET_MAX_PACKET) {
3760 break;
3763 msg->msg_iovlen = i;
3764 if (msg->msg_iovlen == 0) {
3765 *tmp_iov = msg->msg_iov[0];
3766 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3767 msg->msg_iov = tmp_iov;
3768 msg->msg_iovlen = 1;
3770 break;
3772 case SOCK_DGRAM:
3773 if (si->connected) {
3774 if (msg->msg_name) {
3775 errno = EISCONN;
3776 return -1;
3778 } else {
3779 const struct sockaddr *msg_name;
3780 msg_name = (const struct sockaddr *)msg->msg_name;
3782 if (msg_name == NULL) {
3783 errno = ENOTCONN;
3784 return -1;
3788 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3789 tmp_un, 0, bcast);
3790 if (ret == -1) return -1;
3792 if (to_un) {
3793 *to_un = tmp_un;
3795 if (to) {
3796 *to = msg_name;
3798 msg->msg_name = tmp_un;
3799 msg->msg_namelen = sizeof(*tmp_un);
3802 if (si->bound == 0) {
3803 ret = swrap_auto_bind(fd, si, si->family);
3804 if (ret == -1) {
3805 if (errno == ENOTSOCK) {
3806 swrap_remove_stale(fd);
3807 return -ENOTSOCK;
3808 } else {
3809 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3810 return -1;
3815 if (!si->defer_connect) {
3816 break;
3819 ret = sockaddr_convert_to_un(si,
3820 &si->peername.sa.s,
3821 si->peername.sa_socklen,
3822 tmp_un,
3824 NULL);
3825 if (ret == -1) return -1;
3827 ret = libc_connect(fd,
3828 (struct sockaddr *)(void *)tmp_un,
3829 sizeof(*tmp_un));
3831 /* to give better errors */
3832 if (ret == -1 && errno == ENOENT) {
3833 errno = EHOSTUNREACH;
3836 if (ret == -1) {
3837 return ret;
3840 si->defer_connect = 0;
3841 break;
3842 default:
3843 errno = EHOSTUNREACH;
3844 return -1;
3847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3848 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3849 uint8_t *cmbuf = NULL;
3850 size_t cmlen = 0;
3852 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3853 if (ret < 0) {
3854 free(cmbuf);
3855 return -1;
3858 if (cmlen == 0) {
3859 msg->msg_controllen = 0;
3860 msg->msg_control = NULL;
3861 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3862 memcpy(msg->msg_control, cmbuf, cmlen);
3863 msg->msg_controllen = cmlen;
3865 free(cmbuf);
3867 #endif
3869 return 0;
3872 static void swrap_sendmsg_after(int fd,
3873 struct socket_info *si,
3874 struct msghdr *msg,
3875 const struct sockaddr *to,
3876 ssize_t ret)
3878 int saved_errno = errno;
3879 size_t i, len = 0;
3880 uint8_t *buf;
3881 off_t ofs = 0;
3882 size_t avail = 0;
3883 size_t remain;
3885 /* to give better errors */
3886 if (ret == -1) {
3887 if (saved_errno == ENOENT) {
3888 saved_errno = EHOSTUNREACH;
3889 } else if (saved_errno == ENOTSOCK) {
3890 /* If the fd is not a socket, remove it */
3891 swrap_remove_stale(fd);
3895 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3896 avail += msg->msg_iov[i].iov_len;
3899 if (ret == -1) {
3900 remain = MIN(80, avail);
3901 } else {
3902 remain = ret;
3905 /* we capture it as one single packet */
3906 buf = (uint8_t *)malloc(remain);
3907 if (!buf) {
3908 /* we just not capture the packet */
3909 errno = saved_errno;
3910 return;
3913 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3914 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3915 memcpy(buf + ofs,
3916 msg->msg_iov[i].iov_base,
3917 this_time);
3918 ofs += this_time;
3919 remain -= this_time;
3921 len = ofs;
3923 switch (si->type) {
3924 case SOCK_STREAM:
3925 if (ret == -1) {
3926 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3927 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3928 } else {
3929 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3931 break;
3933 case SOCK_DGRAM:
3934 if (si->connected) {
3935 to = &si->peername.sa.s;
3937 if (ret == -1) {
3938 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3939 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3940 } else {
3941 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3943 break;
3946 free(buf);
3947 errno = saved_errno;
3950 static int swrap_recvmsg_before(int fd,
3951 struct socket_info *si,
3952 struct msghdr *msg,
3953 struct iovec *tmp_iov)
3955 size_t i, len = 0;
3956 ssize_t ret;
3958 (void)fd; /* unused */
3960 switch (si->type) {
3961 case SOCK_STREAM:
3962 if (!si->connected) {
3963 errno = ENOTCONN;
3964 return -1;
3967 if (msg->msg_iovlen == 0) {
3968 break;
3971 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3972 size_t nlen;
3973 nlen = len + msg->msg_iov[i].iov_len;
3974 if (nlen > SOCKET_MAX_PACKET) {
3975 break;
3978 msg->msg_iovlen = i;
3979 if (msg->msg_iovlen == 0) {
3980 *tmp_iov = msg->msg_iov[0];
3981 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3982 msg->msg_iov = tmp_iov;
3983 msg->msg_iovlen = 1;
3985 break;
3987 case SOCK_DGRAM:
3988 if (msg->msg_name == NULL) {
3989 errno = EINVAL;
3990 return -1;
3993 if (msg->msg_iovlen == 0) {
3994 break;
3997 if (si->bound == 0) {
3998 ret = swrap_auto_bind(fd, si, si->family);
3999 if (ret == -1) {
4001 * When attempting to read or write to a
4002 * descriptor, if an underlying autobind fails
4003 * because it's not a socket, stop intercepting
4004 * uses of that descriptor.
4006 if (errno == ENOTSOCK) {
4007 swrap_remove_stale(fd);
4008 return -ENOTSOCK;
4009 } else {
4010 SWRAP_LOG(SWRAP_LOG_ERROR,
4011 "swrap_recvmsg_before failed");
4012 return -1;
4016 break;
4017 default:
4018 errno = EHOSTUNREACH;
4019 return -1;
4022 return 0;
4025 static int swrap_recvmsg_after(int fd,
4026 struct socket_info *si,
4027 struct msghdr *msg,
4028 const struct sockaddr_un *un_addr,
4029 socklen_t un_addrlen,
4030 ssize_t ret)
4032 int saved_errno = errno;
4033 size_t i;
4034 uint8_t *buf = NULL;
4035 off_t ofs = 0;
4036 size_t avail = 0;
4037 size_t remain;
4038 int rc;
4040 /* to give better errors */
4041 if (ret == -1) {
4042 if (saved_errno == ENOENT) {
4043 saved_errno = EHOSTUNREACH;
4044 } else if (saved_errno == ENOTSOCK) {
4045 /* If the fd is not a socket, remove it */
4046 swrap_remove_stale(fd);
4050 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4051 avail += msg->msg_iov[i].iov_len;
4054 if (avail == 0) {
4055 rc = 0;
4056 goto done;
4059 if (ret == -1) {
4060 remain = MIN(80, avail);
4061 } else {
4062 remain = ret;
4065 /* we capture it as one single packet */
4066 buf = (uint8_t *)malloc(remain);
4067 if (buf == NULL) {
4068 /* we just not capture the packet */
4069 errno = saved_errno;
4070 return -1;
4073 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4074 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4075 memcpy(buf + ofs,
4076 msg->msg_iov[i].iov_base,
4077 this_time);
4078 ofs += this_time;
4079 remain -= this_time;
4082 switch (si->type) {
4083 case SOCK_STREAM:
4084 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4085 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4086 } else if (ret == 0) { /* END OF FILE */
4087 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4088 } else if (ret > 0) {
4089 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4091 break;
4093 case SOCK_DGRAM:
4094 if (ret == -1) {
4095 break;
4098 if (un_addr != NULL) {
4099 rc = sockaddr_convert_from_un(si,
4100 un_addr,
4101 un_addrlen,
4102 si->family,
4103 msg->msg_name,
4104 &msg->msg_namelen);
4105 if (rc == -1) {
4106 goto done;
4109 swrap_pcap_dump_packet(si,
4110 msg->msg_name,
4111 SWRAP_RECVFROM,
4112 buf,
4113 ret);
4114 } else {
4115 swrap_pcap_dump_packet(si,
4116 msg->msg_name,
4117 SWRAP_RECV,
4118 buf,
4119 ret);
4122 break;
4125 rc = 0;
4126 done:
4127 free(buf);
4128 errno = saved_errno;
4130 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4131 if (rc == 0 &&
4132 msg->msg_controllen > 0 &&
4133 msg->msg_control != NULL) {
4134 rc = swrap_msghdr_add_socket_info(si, msg);
4135 if (rc < 0) {
4136 return -1;
4139 #endif
4141 return rc;
4144 /****************************************************************************
4145 * RECVFROM
4146 ***************************************************************************/
4148 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4149 struct sockaddr *from, socklen_t *fromlen)
4151 struct swrap_address from_addr = {
4152 .sa_socklen = sizeof(struct sockaddr_un),
4154 ssize_t ret;
4155 struct socket_info *si = find_socket_info(s);
4156 struct swrap_address saddr = {
4157 .sa_socklen = sizeof(struct sockaddr_storage),
4159 struct msghdr msg;
4160 struct iovec tmp;
4161 int tret;
4163 if (!si) {
4164 return libc_recvfrom(s,
4165 buf,
4166 len,
4167 flags,
4168 from,
4169 fromlen);
4172 tmp.iov_base = buf;
4173 tmp.iov_len = len;
4175 ZERO_STRUCT(msg);
4176 if (from != NULL && fromlen != NULL) {
4177 msg.msg_name = from; /* optional address */
4178 msg.msg_namelen = *fromlen; /* size of address */
4179 } else {
4180 msg.msg_name = &saddr.sa.s; /* optional address */
4181 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4183 msg.msg_iov = &tmp; /* scatter/gather array */
4184 msg.msg_iovlen = 1; /* # elements in msg_iov */
4185 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4186 msg.msg_control = NULL; /* ancillary data, see below */
4187 msg.msg_controllen = 0; /* ancillary data buffer len */
4188 msg.msg_flags = 0; /* flags on received message */
4189 #endif
4191 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4192 if (tret < 0) {
4193 return -1;
4196 buf = msg.msg_iov[0].iov_base;
4197 len = msg.msg_iov[0].iov_len;
4199 ret = libc_recvfrom(s,
4200 buf,
4201 len,
4202 flags,
4203 &from_addr.sa.s,
4204 &from_addr.sa_socklen);
4205 if (ret == -1) {
4206 return ret;
4209 tret = swrap_recvmsg_after(s,
4211 &msg,
4212 &from_addr.sa.un,
4213 from_addr.sa_socklen,
4214 ret);
4215 if (tret != 0) {
4216 return tret;
4219 if (from != NULL && fromlen != NULL) {
4220 *fromlen = msg.msg_namelen;
4223 return ret;
4226 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4227 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4228 struct sockaddr *from, Psocklen_t fromlen)
4229 #else
4230 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4231 struct sockaddr *from, socklen_t *fromlen)
4232 #endif
4234 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4237 /****************************************************************************
4238 * SENDTO
4239 ***************************************************************************/
4241 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4242 const struct sockaddr *to, socklen_t tolen)
4244 struct msghdr msg;
4245 struct iovec tmp;
4246 struct swrap_address un_addr = {
4247 .sa_socklen = sizeof(struct sockaddr_un),
4249 const struct sockaddr_un *to_un = NULL;
4250 ssize_t ret;
4251 int rc;
4252 struct socket_info *si = find_socket_info(s);
4253 int bcast = 0;
4255 if (!si) {
4256 return libc_sendto(s, buf, len, flags, to, tolen);
4259 tmp.iov_base = discard_const_p(char, buf);
4260 tmp.iov_len = len;
4262 ZERO_STRUCT(msg);
4263 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4264 msg.msg_namelen = tolen; /* size of address */
4265 msg.msg_iov = &tmp; /* scatter/gather array */
4266 msg.msg_iovlen = 1; /* # elements in msg_iov */
4267 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4268 msg.msg_control = NULL; /* ancillary data, see below */
4269 msg.msg_controllen = 0; /* ancillary data buffer len */
4270 msg.msg_flags = 0; /* flags on received message */
4271 #endif
4273 rc = swrap_sendmsg_before(s,
4275 &msg,
4276 &tmp,
4277 &un_addr.sa.un,
4278 &to_un,
4279 &to,
4280 &bcast);
4281 if (rc < 0) {
4282 return -1;
4285 buf = msg.msg_iov[0].iov_base;
4286 len = msg.msg_iov[0].iov_len;
4288 if (bcast) {
4289 struct stat st;
4290 unsigned int iface;
4291 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4292 char type;
4294 type = SOCKET_TYPE_CHAR_UDP;
4296 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4297 snprintf(un_addr.sa.un.sun_path,
4298 sizeof(un_addr.sa.un.sun_path),
4299 "%s/"SOCKET_FORMAT,
4300 socket_wrapper_dir(), type, iface, prt);
4301 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4303 /* ignore the any errors in broadcast sends */
4304 libc_sendto(s,
4305 buf,
4306 len,
4307 flags,
4308 &un_addr.sa.s,
4309 un_addr.sa_socklen);
4312 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4314 return len;
4317 ret = libc_sendto(s,
4318 buf,
4319 len,
4320 flags,
4321 (struct sockaddr *)msg.msg_name,
4322 msg.msg_namelen);
4324 swrap_sendmsg_after(s, si, &msg, to, ret);
4326 return ret;
4329 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4330 const struct sockaddr *to, socklen_t tolen)
4332 return swrap_sendto(s, buf, len, flags, to, tolen);
4335 /****************************************************************************
4336 * READV
4337 ***************************************************************************/
4339 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4341 struct socket_info *si;
4342 struct msghdr msg;
4343 struct swrap_address saddr = {
4344 .sa_socklen = sizeof(struct sockaddr_storage),
4346 struct iovec tmp;
4347 ssize_t ret;
4348 int tret;
4350 si = find_socket_info(s);
4351 if (si == NULL) {
4352 return libc_recv(s, buf, len, flags);
4355 tmp.iov_base = buf;
4356 tmp.iov_len = len;
4358 ZERO_STRUCT(msg);
4359 msg.msg_name = &saddr.sa.s; /* optional address */
4360 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4361 msg.msg_iov = &tmp; /* scatter/gather array */
4362 msg.msg_iovlen = 1; /* # elements in msg_iov */
4363 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4364 msg.msg_control = NULL; /* ancillary data, see below */
4365 msg.msg_controllen = 0; /* ancillary data buffer len */
4366 msg.msg_flags = 0; /* flags on received message */
4367 #endif
4369 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4370 if (tret < 0) {
4371 return -1;
4374 buf = msg.msg_iov[0].iov_base;
4375 len = msg.msg_iov[0].iov_len;
4377 ret = libc_recv(s, buf, len, flags);
4379 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4380 if (tret != 0) {
4381 return tret;
4384 return ret;
4387 ssize_t recv(int s, void *buf, size_t len, int flags)
4389 return swrap_recv(s, buf, len, flags);
4392 /****************************************************************************
4393 * READ
4394 ***************************************************************************/
4396 static ssize_t swrap_read(int s, void *buf, size_t len)
4398 struct socket_info *si;
4399 struct msghdr msg;
4400 struct iovec tmp;
4401 struct swrap_address saddr = {
4402 .sa_socklen = sizeof(struct sockaddr_storage),
4404 ssize_t ret;
4405 int tret;
4407 si = find_socket_info(s);
4408 if (si == NULL) {
4409 return libc_read(s, buf, len);
4412 tmp.iov_base = buf;
4413 tmp.iov_len = len;
4415 ZERO_STRUCT(msg);
4416 msg.msg_name = &saddr.sa.ss; /* optional address */
4417 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4418 msg.msg_iov = &tmp; /* scatter/gather array */
4419 msg.msg_iovlen = 1; /* # elements in msg_iov */
4420 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4421 msg.msg_control = NULL; /* ancillary data, see below */
4422 msg.msg_controllen = 0; /* ancillary data buffer len */
4423 msg.msg_flags = 0; /* flags on received message */
4424 #endif
4426 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4427 if (tret < 0) {
4428 if (tret == -ENOTSOCK) {
4429 return libc_read(s, buf, len);
4431 return -1;
4434 buf = msg.msg_iov[0].iov_base;
4435 len = msg.msg_iov[0].iov_len;
4437 ret = libc_read(s, buf, len);
4439 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4440 if (tret != 0) {
4441 return tret;
4444 return ret;
4447 ssize_t read(int s, void *buf, size_t len)
4449 return swrap_read(s, buf, len);
4452 /****************************************************************************
4453 * SEND
4454 ***************************************************************************/
4456 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4458 struct msghdr msg;
4459 struct iovec tmp;
4460 struct sockaddr_un un_addr;
4461 ssize_t ret;
4462 int rc;
4463 struct socket_info *si = find_socket_info(s);
4465 if (!si) {
4466 return libc_send(s, buf, len, flags);
4469 tmp.iov_base = discard_const_p(char, buf);
4470 tmp.iov_len = len;
4472 ZERO_STRUCT(msg);
4473 msg.msg_name = NULL; /* optional address */
4474 msg.msg_namelen = 0; /* size of address */
4475 msg.msg_iov = &tmp; /* scatter/gather array */
4476 msg.msg_iovlen = 1; /* # elements in msg_iov */
4477 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4478 msg.msg_control = NULL; /* ancillary data, see below */
4479 msg.msg_controllen = 0; /* ancillary data buffer len */
4480 msg.msg_flags = 0; /* flags on received message */
4481 #endif
4483 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4484 if (rc < 0) {
4485 return -1;
4488 buf = msg.msg_iov[0].iov_base;
4489 len = msg.msg_iov[0].iov_len;
4491 ret = libc_send(s, buf, len, flags);
4493 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4495 return ret;
4498 ssize_t send(int s, const void *buf, size_t len, int flags)
4500 return swrap_send(s, buf, len, flags);
4503 /****************************************************************************
4504 * RECVMSG
4505 ***************************************************************************/
4507 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4509 struct swrap_address from_addr = {
4510 .sa_socklen = sizeof(struct sockaddr_un),
4512 struct socket_info *si;
4513 struct msghdr msg;
4514 struct iovec tmp;
4515 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4516 size_t msg_ctrllen_filled;
4517 size_t msg_ctrllen_left;
4518 #endif
4520 ssize_t ret;
4521 int rc;
4523 si = find_socket_info(s);
4524 if (si == NULL) {
4525 return libc_recvmsg(s, omsg, flags);
4528 tmp.iov_base = NULL;
4529 tmp.iov_len = 0;
4531 ZERO_STRUCT(msg);
4532 msg.msg_name = &from_addr.sa; /* optional address */
4533 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4534 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4535 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4536 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4537 msg_ctrllen_filled = 0;
4538 msg_ctrllen_left = omsg->msg_controllen;
4540 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4541 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4542 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4543 #endif
4545 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4546 if (rc < 0) {
4547 return -1;
4550 ret = libc_recvmsg(s, &msg, flags);
4552 msg.msg_name = omsg->msg_name;
4553 msg.msg_namelen = omsg->msg_namelen;
4555 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4556 msg_ctrllen_filled += msg.msg_controllen;
4557 msg_ctrllen_left -= msg.msg_controllen;
4559 if (omsg->msg_control != NULL) {
4560 uint8_t *p;
4562 p = omsg->msg_control;
4563 p += msg_ctrllen_filled;
4565 msg.msg_control = p;
4566 msg.msg_controllen = msg_ctrllen_left;
4567 } else {
4568 msg.msg_control = NULL;
4569 msg.msg_controllen = 0;
4571 #endif
4573 rc = swrap_recvmsg_after(s,
4575 &msg,
4576 &from_addr.sa.un,
4577 from_addr.sa_socklen,
4578 ret);
4579 if (rc != 0) {
4580 return rc;
4583 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4584 if (omsg->msg_control != NULL) {
4585 /* msg.msg_controllen = space left */
4586 msg_ctrllen_left = msg.msg_controllen;
4587 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4590 /* Update the original message length */
4591 omsg->msg_controllen = msg_ctrllen_filled;
4592 omsg->msg_flags = msg.msg_flags;
4593 #endif
4594 omsg->msg_iovlen = msg.msg_iovlen;
4596 return ret;
4599 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4601 return swrap_recvmsg(sockfd, msg, flags);
4604 /****************************************************************************
4605 * SENDMSG
4606 ***************************************************************************/
4608 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4610 struct msghdr msg;
4611 struct iovec tmp;
4612 struct sockaddr_un un_addr;
4613 const struct sockaddr_un *to_un = NULL;
4614 const struct sockaddr *to = NULL;
4615 ssize_t ret;
4616 int rc;
4617 struct socket_info *si = find_socket_info(s);
4618 int bcast = 0;
4620 if (!si) {
4621 return libc_sendmsg(s, omsg, flags);
4624 ZERO_STRUCT(un_addr);
4626 tmp.iov_base = NULL;
4627 tmp.iov_len = 0;
4629 ZERO_STRUCT(msg);
4630 msg.msg_name = omsg->msg_name; /* optional address */
4631 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4632 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4633 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4634 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4635 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4636 /* omsg is a const so use a local buffer for modifications */
4637 uint8_t cmbuf[omsg->msg_controllen];
4639 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4641 msg.msg_control = cmbuf; /* ancillary data, see below */
4642 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4644 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4645 #endif
4647 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4648 if (rc < 0) {
4649 return -1;
4652 if (bcast) {
4653 struct stat st;
4654 unsigned int iface;
4655 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4656 char type;
4657 size_t i, len = 0;
4658 uint8_t *buf;
4659 off_t ofs = 0;
4660 size_t avail = 0;
4661 size_t remain;
4663 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4664 avail += msg.msg_iov[i].iov_len;
4667 len = avail;
4668 remain = avail;
4670 /* we capture it as one single packet */
4671 buf = (uint8_t *)malloc(remain);
4672 if (!buf) {
4673 return -1;
4676 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4677 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4678 memcpy(buf + ofs,
4679 msg.msg_iov[i].iov_base,
4680 this_time);
4681 ofs += this_time;
4682 remain -= this_time;
4685 type = SOCKET_TYPE_CHAR_UDP;
4687 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4688 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4689 socket_wrapper_dir(), type, iface, prt);
4690 if (stat(un_addr.sun_path, &st) != 0) continue;
4692 msg.msg_name = &un_addr; /* optional address */
4693 msg.msg_namelen = sizeof(un_addr); /* size of address */
4695 /* ignore the any errors in broadcast sends */
4696 libc_sendmsg(s, &msg, flags);
4699 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4700 free(buf);
4702 return len;
4705 ret = libc_sendmsg(s, &msg, flags);
4707 swrap_sendmsg_after(s, si, &msg, to, ret);
4709 return ret;
4712 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4714 return swrap_sendmsg(s, omsg, flags);
4717 /****************************************************************************
4718 * READV
4719 ***************************************************************************/
4721 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4723 struct socket_info *si;
4724 struct msghdr msg;
4725 struct iovec tmp;
4726 struct swrap_address saddr = {
4727 .sa_socklen = sizeof(struct sockaddr_storage)
4729 ssize_t ret;
4730 int rc;
4732 si = find_socket_info(s);
4733 if (si == NULL) {
4734 return libc_readv(s, vector, count);
4737 tmp.iov_base = NULL;
4738 tmp.iov_len = 0;
4740 ZERO_STRUCT(msg);
4741 msg.msg_name = &saddr.sa.s; /* optional address */
4742 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4743 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4744 msg.msg_iovlen = count; /* # elements in msg_iov */
4745 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4746 msg.msg_control = NULL; /* ancillary data, see below */
4747 msg.msg_controllen = 0; /* ancillary data buffer len */
4748 msg.msg_flags = 0; /* flags on received message */
4749 #endif
4751 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4752 if (rc < 0) {
4753 if (rc == -ENOTSOCK) {
4754 return libc_readv(s, vector, count);
4756 return -1;
4759 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4761 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4762 if (rc != 0) {
4763 return rc;
4766 return ret;
4769 ssize_t readv(int s, const struct iovec *vector, int count)
4771 return swrap_readv(s, vector, count);
4774 /****************************************************************************
4775 * WRITEV
4776 ***************************************************************************/
4778 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4780 struct msghdr msg;
4781 struct iovec tmp;
4782 struct sockaddr_un un_addr;
4783 ssize_t ret;
4784 int rc;
4785 struct socket_info *si = find_socket_info(s);
4787 if (!si) {
4788 return libc_writev(s, vector, count);
4791 tmp.iov_base = NULL;
4792 tmp.iov_len = 0;
4794 ZERO_STRUCT(msg);
4795 msg.msg_name = NULL; /* optional address */
4796 msg.msg_namelen = 0; /* size of address */
4797 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4798 msg.msg_iovlen = count; /* # elements in msg_iov */
4799 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4800 msg.msg_control = NULL; /* ancillary data, see below */
4801 msg.msg_controllen = 0; /* ancillary data buffer len */
4802 msg.msg_flags = 0; /* flags on received message */
4803 #endif
4805 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4806 if (rc < 0) {
4807 if (rc == -ENOTSOCK) {
4808 return libc_readv(s, vector, count);
4810 return -1;
4813 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4815 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4817 return ret;
4820 ssize_t writev(int s, const struct iovec *vector, int count)
4822 return swrap_writev(s, vector, count);
4825 /****************************
4826 * CLOSE
4827 ***************************/
4829 static int swrap_close(int fd)
4831 struct socket_info *si = find_socket_info(fd);
4832 struct socket_info_fd *fi;
4833 int ret;
4835 if (!si) {
4836 return libc_close(fd);
4839 for (fi = si->fds; fi; fi = fi->next) {
4840 if (fi->fd == fd) {
4841 SWRAP_DLIST_REMOVE(si->fds, fi);
4842 free(fi);
4843 break;
4847 if (si->fds) {
4848 /* there are still references left */
4849 return libc_close(fd);
4852 SWRAP_DLIST_REMOVE(sockets, si);
4854 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4855 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4858 ret = libc_close(fd);
4860 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4861 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4862 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4865 if (si->un_addr.sun_path[0] != '\0') {
4866 unlink(si->un_addr.sun_path);
4868 free(si);
4870 return ret;
4873 int close(int fd)
4875 return swrap_close(fd);
4878 /****************************
4879 * DUP
4880 ***************************/
4882 static int swrap_dup(int fd)
4884 struct socket_info *si;
4885 struct socket_info_fd *fi;
4887 si = find_socket_info(fd);
4889 if (!si) {
4890 return libc_dup(fd);
4893 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4894 if (fi == NULL) {
4895 errno = ENOMEM;
4896 return -1;
4899 fi->fd = libc_dup(fd);
4900 if (fi->fd == -1) {
4901 int saved_errno = errno;
4902 free(fi);
4903 errno = saved_errno;
4904 return -1;
4907 /* Make sure we don't have an entry for the fd */
4908 swrap_remove_stale(fi->fd);
4910 SWRAP_DLIST_ADD(si->fds, fi);
4911 return fi->fd;
4914 int dup(int fd)
4916 return swrap_dup(fd);
4919 /****************************
4920 * DUP2
4921 ***************************/
4923 static int swrap_dup2(int fd, int newfd)
4925 struct socket_info *si;
4926 struct socket_info_fd *fi;
4928 si = find_socket_info(fd);
4930 if (!si) {
4931 return libc_dup2(fd, newfd);
4934 if (find_socket_info(newfd)) {
4935 /* dup2() does an implicit close of newfd, which we
4936 * need to emulate */
4937 swrap_close(newfd);
4940 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4941 if (fi == NULL) {
4942 errno = ENOMEM;
4943 return -1;
4946 fi->fd = libc_dup2(fd, newfd);
4947 if (fi->fd == -1) {
4948 int saved_errno = errno;
4949 free(fi);
4950 errno = saved_errno;
4951 return -1;
4954 /* Make sure we don't have an entry for the fd */
4955 swrap_remove_stale(fi->fd);
4957 SWRAP_DLIST_ADD(si->fds, fi);
4958 return fi->fd;
4961 int dup2(int fd, int newfd)
4963 return swrap_dup2(fd, newfd);
4966 /****************************
4967 * FCNTL
4968 ***************************/
4970 static int swrap_vfcntl(int fd, int cmd, va_list va)
4972 struct socket_info_fd *fi;
4973 struct socket_info *si;
4974 int rc;
4976 si = find_socket_info(fd);
4977 if (si == NULL) {
4978 rc = libc_vfcntl(fd, cmd, va);
4980 return rc;
4983 switch (cmd) {
4984 case F_DUPFD:
4985 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4986 if (fi == NULL) {
4987 errno = ENOMEM;
4988 return -1;
4991 fi->fd = libc_vfcntl(fd, cmd, va);
4992 if (fi->fd == -1) {
4993 int saved_errno = errno;
4994 free(fi);
4995 errno = saved_errno;
4996 return -1;
4999 /* Make sure we don't have an entry for the fd */
5000 swrap_remove_stale(fi->fd);
5002 SWRAP_DLIST_ADD(si->fds, fi);
5004 rc = fi->fd;
5005 break;
5006 default:
5007 rc = libc_vfcntl(fd, cmd, va);
5008 break;
5011 return rc;
5014 int fcntl(int fd, int cmd, ...)
5016 va_list va;
5017 int rc;
5019 va_start(va, cmd);
5021 rc = swrap_vfcntl(fd, cmd, va);
5023 va_end(va);
5025 return rc;
5028 /****************************
5029 * EVENTFD
5030 ***************************/
5032 #ifdef HAVE_EVENTFD
5033 static int swrap_eventfd(int count, int flags)
5035 int fd;
5037 fd = libc_eventfd(count, flags);
5038 if (fd != -1) {
5039 swrap_remove_stale(fd);
5042 return fd;
5045 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5046 int eventfd(unsigned int count, int flags)
5047 #else
5048 int eventfd(int count, int flags)
5049 #endif
5051 return swrap_eventfd(count, flags);
5053 #endif
5055 /****************************
5056 * DESTRUCTOR
5057 ***************************/
5060 * This function is called when the library is unloaded and makes sure that
5061 * sockets get closed and the unix file for the socket are unlinked.
5063 void swrap_destructor(void)
5065 struct socket_info *s = sockets;
5067 while (s != NULL) {
5068 struct socket_info_fd *f = s->fds;
5069 if (f != NULL) {
5070 swrap_close(f->fd);
5072 s = sockets;