1 /*
2 * BSD 3-Clause License
3 *
4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2018, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
7 * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8 * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 /*
40 Socket wrapper library. Passes all socket communication over
41 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
42 is set.
43 */
44
45 #include "config.h"
46
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <sys/stat.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
54 #endif
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
57 #endif
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
60 #endif
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
63 #endif
64 #include <sys/uio.h>
65 #include <errno.h>
66 #include <sys/un.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #include <arpa/inet.h>
70 #include <fcntl.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <stdio.h>
74 #include <stdint.h>
75 #include <stdarg.h>
76 #include <stdbool.h>
77 #include <unistd.h>
78 #ifdef HAVE_GNU_LIB_NAMES_H
79 #include <gnu/lib-names.h>
80 #endif
81 #ifdef HAVE_RPC_RPC_H
82 #include <rpc/rpc.h>
83 #endif
84 #include <pthread.h>
85
86 enum swrap_dbglvl_e {
87 SWRAP_LOG_ERROR = 0,
88 SWRAP_LOG_WARN,
89 SWRAP_LOG_DEBUG,
90 SWRAP_LOG_TRACE
91 };
92
93 /* GCC have printf type attribute check. */
94 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
95 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
96 #else
97 #define PRINTF_ATTRIBUTE(a,b)
98 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
99
100 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
101 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
102 #else
103 #define CONSTRUCTOR_ATTRIBUTE
104 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
105
106 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
107 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
108 #else
109 #define DESTRUCTOR_ATTRIBUTE
110 #endif
111
112 #ifndef FALL_THROUGH
113 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
114 # define FALL_THROUGH __attribute__ ((fallthrough))
115 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 # define FALL_THROUGH ((void)0)
117 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
118 #endif /* FALL_THROUGH */
119
120 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
122 #else
123 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
124 #endif
125
126 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
127 # define SWRAP_THREAD __thread
128 #else
129 # define SWRAP_THREAD
130 #endif
131
132 #ifndef MIN
133 #define MIN(a,b) ((a)<(b)?(a):(b))
134 #endif
135
136 #ifndef ZERO_STRUCT
137 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
138 #endif
139
140 #ifndef ZERO_STRUCTP
141 #define ZERO_STRUCTP(x) do { \
142 if ((x) != NULL) \
143 memset((char *)(x), 0, sizeof(*(x))); \
144 } while(0)
145 #endif
146
147 #ifndef SAFE_FREE
148 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
149 #endif
150
151 #ifndef discard_const
152 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
153 #endif
154
155 #ifndef discard_const_p
156 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
157 #endif
158
159 #define UNUSED(x) (void)(x)
160
161 #ifdef IPV6_PKTINFO
162 # ifndef IPV6_RECVPKTINFO
163 # define IPV6_RECVPKTINFO IPV6_PKTINFO
164 # endif /* IPV6_RECVPKTINFO */
165 #endif /* IPV6_PKTINFO */
166
167 /*
168 * On BSD IP_PKTINFO has a different name because during
169 * the time when they implemented it, there was no RFC.
170 * The name for IPv6 is the same as on Linux.
171 */
172 #ifndef IP_PKTINFO
173 # ifdef IP_RECVDSTADDR
174 # define IP_PKTINFO IP_RECVDSTADDR
175 # endif
176 #endif
177
178 /* Add new global locks here please */
179 # define SWRAP_LOCK_ALL \
180 swrap_mutex_lock(&libc_symbol_binding_mutex); \
181
182 # define SWRAP_UNLOCK_ALL \
183 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
184
185 #define SOCKET_INFO_CONTAINER(si) \
186 (struct socket_info_container *)(si)
187
188 #define SWRAP_LOCK_SI(si) do { \
189 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
190 swrap_mutex_lock(&sic->meta.mutex); \
191 } while(0)
192
193 #define SWRAP_UNLOCK_SI(si) do { \
194 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
195 swrap_mutex_unlock(&sic->meta.mutex); \
196 } while(0)
197
198 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
199 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
200 #else
201 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
202 #endif
203
204 /* we need to use a very terse format here as IRIX 6.4 silently
205 truncates names to 16 chars, so if we use a longer name then we
206 can't tell which port a packet came from with recvfrom()
207
208 with this format we have 8 chars left for the directory name
209 */
210 #define SOCKET_FORMAT "%c%02X%04X"
211 #define SOCKET_TYPE_CHAR_TCP 'T'
212 #define SOCKET_TYPE_CHAR_UDP 'U'
213 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
214 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
215
216 /*
217 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
218 * format PCAP capture files (as the caller will simply continue from here).
219 */
220 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
221 #define SOCKET_WRAPPER_MTU_MIN 512
222 #define SOCKET_WRAPPER_MTU_MAX 32768
223
224 #define SOCKET_MAX_SOCKETS 1024
225
226 /*
227 * Maximum number of socket_info structures that can
228 * be used. Can be overriden by the environment variable
229 * SOCKET_WRAPPER_MAX_SOCKETS.
230 */
231 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
232
233 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
234
235 /* This limit is to avoid broadcast sendto() needing to stat too many
236 * files. It may be raised (with a performance cost) to up to 254
237 * without changing the format above */
238 #define MAX_WRAPPED_INTERFACES 64
239
240 struct swrap_address {
241 socklen_t sa_socklen;
242 union {
243 struct sockaddr s;
244 struct sockaddr_in in;
245 #ifdef HAVE_IPV6
246 struct sockaddr_in6 in6;
247 #endif
248 struct sockaddr_un un;
249 struct sockaddr_storage ss;
250 } sa;
251 };
252
253 int first_free;
254
255 struct socket_info
256 {
257 int family;
258 int type;
259 int protocol;
260 int bound;
261 int bcast;
262 int is_server;
263 int connected;
264 int defer_connect;
265 int pktinfo;
266 int tcp_nodelay;
267
268 /* The unix path so we can unlink it on close() */
269 struct sockaddr_un un_addr;
270
271 struct swrap_address bindname;
272 struct swrap_address myname;
273 struct swrap_address peername;
274
275 struct {
276 unsigned long pck_snd;
277 unsigned long pck_rcv;
278 } io;
279 };
280
281 struct socket_info_meta
282 {
283 unsigned int refcount;
284 int next_free;
285 pthread_mutex_t mutex;
286 };
287
288 struct socket_info_container
289 {
290 struct socket_info info;
291 struct socket_info_meta meta;
292 };
293
294 static struct socket_info_container *sockets;
295
296 static size_t socket_info_max = 0;
297
298 /*
299 * Allocate the socket array always on the limit value. We want it to be
300 * at least bigger than the default so if we reach the limit we can
301 * still deal with duplicate fds pointing to the same socket_info.
302 */
303 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
304
305 /* Hash table to map fds to corresponding socket_info index */
306 static int *socket_fds_idx;
307
308 /* Mutex to synchronize access to global libc.symbols */
309 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
310
311 /* Mutex for syncronizing port selection during swrap_auto_bind() */
312 static pthread_mutex_t autobind_start_mutex;
313
314 /* Mutex to guard the initialization of array of socket_info structures */
315 static pthread_mutex_t sockets_mutex;
316
317 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
318 static pthread_mutex_t socket_reset_mutex;
319
320 /* Mutex to synchronize access to first free index in socket_info array */
321 static pthread_mutex_t first_free_mutex;
322
323 /* Mutex to synchronize access to packet capture dump file */
324 static pthread_mutex_t pcap_dump_mutex;
325
326 /* Mutex for synchronizing mtu value fetch*/
327 static pthread_mutex_t mtu_update_mutex;
328
329 /* Function prototypes */
330
331 bool socket_wrapper_enabled(void);
332
333 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
334 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
335
336 #ifndef HAVE_GETPROGNAME
getprogname(void)337 static const char *getprogname(void)
338 {
339 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
340 return program_invocation_short_name;
341 #elif defined(HAVE_GETEXECNAME)
342 return getexecname();
343 #else
344 return NULL;
345 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
346 }
347 #endif /* HAVE_GETPROGNAME */
348
349 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
350 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
351
swrap_log(enum swrap_dbglvl_e dbglvl,const char * func,const char * format,...)352 static void swrap_log(enum swrap_dbglvl_e dbglvl,
353 const char *func,
354 const char *format, ...)
355 {
356 char buffer[1024];
357 va_list va;
358 const char *d;
359 unsigned int lvl = 0;
360 const char *prefix = "SWRAP";
361 const char *progname = getprogname();
362
363 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
364 if (d != NULL) {
365 lvl = atoi(d);
366 }
367
368 if (lvl < dbglvl) {
369 return;
370 }
371
372 va_start(va, format);
373 vsnprintf(buffer, sizeof(buffer), format, va);
374 va_end(va);
375
376 switch (dbglvl) {
377 case SWRAP_LOG_ERROR:
378 prefix = "SWRAP_ERROR";
379 break;
380 case SWRAP_LOG_WARN:
381 prefix = "SWRAP_WARN";
382 break;
383 case SWRAP_LOG_DEBUG:
384 prefix = "SWRAP_DEBUG";
385 break;
386 case SWRAP_LOG_TRACE:
387 prefix = "SWRAP_TRACE";
388 break;
389 }
390
391 if (progname == NULL) {
392 progname = "<unknown>";
393 }
394
395 fprintf(stderr,
396 "%s[%s (%u)] - %s: %s\n",
397 prefix,
398 progname,
399 (unsigned int)getpid(),
400 func,
401 buffer);
402 }
403
404 /*********************************************************
405 * SWRAP LOADING LIBC FUNCTIONS
406 *********************************************************/
407
408 #include <dlfcn.h>
409
410 #ifdef HAVE_ACCEPT4
411 typedef int (*__libc_accept4)(int sockfd,
412 struct sockaddr *addr,
413 socklen_t *addrlen,
414 int flags);
415 #else
416 typedef int (*__libc_accept)(int sockfd,
417 struct sockaddr *addr,
418 socklen_t *addrlen);
419 #endif
420 typedef int (*__libc_bind)(int sockfd,
421 const struct sockaddr *addr,
422 socklen_t addrlen);
423 typedef int (*__libc_close)(int fd);
424 typedef int (*__libc_connect)(int sockfd,
425 const struct sockaddr *addr,
426 socklen_t addrlen);
427 typedef int (*__libc_dup)(int fd);
428 typedef int (*__libc_dup2)(int oldfd, int newfd);
429 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
430 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
431 #ifdef HAVE_FOPEN64
432 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
433 #endif
434 #ifdef HAVE_EVENTFD
435 typedef int (*__libc_eventfd)(int count, int flags);
436 #endif
437 typedef int (*__libc_getpeername)(int sockfd,
438 struct sockaddr *addr,
439 socklen_t *addrlen);
440 typedef int (*__libc_getsockname)(int sockfd,
441 struct sockaddr *addr,
442 socklen_t *addrlen);
443 typedef int (*__libc_getsockopt)(int sockfd,
444 int level,
445 int optname,
446 void *optval,
447 socklen_t *optlen);
448 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
449 typedef int (*__libc_listen)(int sockfd, int backlog);
450 typedef int (*__libc_open)(const char *pathname, int flags, ...);
451 #ifdef HAVE_OPEN64
452 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
453 #endif /* HAVE_OPEN64 */
454 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
455 typedef int (*__libc_pipe)(int pipefd[2]);
456 typedef int (*__libc_read)(int fd, void *buf, size_t count);
457 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
458 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
459 typedef int (*__libc_recvfrom)(int sockfd,
460 void *buf,
461 size_t len,
462 int flags,
463 struct sockaddr *src_addr,
464 socklen_t *addrlen);
465 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
466 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
467 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
468 typedef int (*__libc_sendto)(int sockfd,
469 const void *buf,
470 size_t len,
471 int flags,
472 const struct sockaddr *dst_addr,
473 socklen_t addrlen);
474 typedef int (*__libc_setsockopt)(int sockfd,
475 int level,
476 int optname,
477 const void *optval,
478 socklen_t optlen);
479 #ifdef HAVE_SIGNALFD
480 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
481 #endif
482 typedef int (*__libc_socket)(int domain, int type, int protocol);
483 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
484 #ifdef HAVE_TIMERFD_CREATE
485 typedef int (*__libc_timerfd_create)(int clockid, int flags);
486 #endif
487 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
488 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
489
490 #define SWRAP_SYMBOL_ENTRY(i) \
491 union { \
492 __libc_##i f; \
493 void *obj; \
494 } _libc_##i
495
496 struct swrap_libc_symbols {
497 #ifdef HAVE_ACCEPT4
498 SWRAP_SYMBOL_ENTRY(accept4);
499 #else
500 SWRAP_SYMBOL_ENTRY(accept);
501 #endif
502 SWRAP_SYMBOL_ENTRY(bind);
503 SWRAP_SYMBOL_ENTRY(close);
504 SWRAP_SYMBOL_ENTRY(connect);
505 SWRAP_SYMBOL_ENTRY(dup);
506 SWRAP_SYMBOL_ENTRY(dup2);
507 SWRAP_SYMBOL_ENTRY(fcntl);
508 SWRAP_SYMBOL_ENTRY(fopen);
509 #ifdef HAVE_FOPEN64
510 SWRAP_SYMBOL_ENTRY(fopen64);
511 #endif
512 #ifdef HAVE_EVENTFD
513 SWRAP_SYMBOL_ENTRY(eventfd);
514 #endif
515 SWRAP_SYMBOL_ENTRY(getpeername);
516 SWRAP_SYMBOL_ENTRY(getsockname);
517 SWRAP_SYMBOL_ENTRY(getsockopt);
518 SWRAP_SYMBOL_ENTRY(ioctl);
519 SWRAP_SYMBOL_ENTRY(listen);
520 SWRAP_SYMBOL_ENTRY(open);
521 #ifdef HAVE_OPEN64
522 SWRAP_SYMBOL_ENTRY(open64);
523 #endif
524 SWRAP_SYMBOL_ENTRY(openat);
525 SWRAP_SYMBOL_ENTRY(pipe);
526 SWRAP_SYMBOL_ENTRY(read);
527 SWRAP_SYMBOL_ENTRY(readv);
528 SWRAP_SYMBOL_ENTRY(recv);
529 SWRAP_SYMBOL_ENTRY(recvfrom);
530 SWRAP_SYMBOL_ENTRY(recvmsg);
531 SWRAP_SYMBOL_ENTRY(send);
532 SWRAP_SYMBOL_ENTRY(sendmsg);
533 SWRAP_SYMBOL_ENTRY(sendto);
534 SWRAP_SYMBOL_ENTRY(setsockopt);
535 #ifdef HAVE_SIGNALFD
536 SWRAP_SYMBOL_ENTRY(signalfd);
537 #endif
538 SWRAP_SYMBOL_ENTRY(socket);
539 SWRAP_SYMBOL_ENTRY(socketpair);
540 #ifdef HAVE_TIMERFD_CREATE
541 SWRAP_SYMBOL_ENTRY(timerfd_create);
542 #endif
543 SWRAP_SYMBOL_ENTRY(write);
544 SWRAP_SYMBOL_ENTRY(writev);
545 };
546
547 struct swrap {
548 struct {
549 void *handle;
550 void *socket_handle;
551 struct swrap_libc_symbols symbols;
552 } libc;
553 };
554
555 static struct swrap swrap;
556
557 /* prototypes */
558 static char *socket_wrapper_dir(void);
559
560 #define LIBC_NAME "libc.so"
561
562 enum swrap_lib {
563 SWRAP_LIBC,
564 SWRAP_LIBNSL,
565 SWRAP_LIBSOCKET,
566 };
567
swrap_str_lib(enum swrap_lib lib)568 static const char *swrap_str_lib(enum swrap_lib lib)
569 {
570 switch (lib) {
571 case SWRAP_LIBC:
572 return "libc";
573 case SWRAP_LIBNSL:
574 return "libnsl";
575 case SWRAP_LIBSOCKET:
576 return "libsocket";
577 }
578
579 /* Compiler would warn us about unhandled enum value if we get here */
580 return "unknown";
581 }
582
swrap_load_lib_handle(enum swrap_lib lib)583 static void *swrap_load_lib_handle(enum swrap_lib lib)
584 {
585 int flags = RTLD_LAZY;
586 void *handle = NULL;
587 int i;
588
589 #ifdef RTLD_DEEPBIND
590 const char *env_preload = getenv("LD_PRELOAD");
591 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
592 bool enable_deepbind = true;
593
594 /* Don't do a deepbind if we run with libasan */
595 if (env_preload != NULL && strlen(env_preload) < 1024) {
596 const char *p = strstr(env_preload, "libasan.so");
597 if (p != NULL) {
598 enable_deepbind = false;
599 }
600 }
601
602 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
603 enable_deepbind = false;
604 }
605
606 if (enable_deepbind) {
607 flags |= RTLD_DEEPBIND;
608 }
609 #endif
610
611 switch (lib) {
612 case SWRAP_LIBNSL:
613 case SWRAP_LIBSOCKET:
614 #ifdef HAVE_LIBSOCKET
615 handle = swrap.libc.socket_handle;
616 if (handle == NULL) {
617 for (i = 10; i >= 0; i--) {
618 char soname[256] = {0};
619
620 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
621 handle = dlopen(soname, flags);
622 if (handle != NULL) {
623 break;
624 }
625 }
626
627 swrap.libc.socket_handle = handle;
628 }
629 break;
630 #endif
631 case SWRAP_LIBC:
632 handle = swrap.libc.handle;
633 #ifdef LIBC_SO
634 if (handle == NULL) {
635 handle = dlopen(LIBC_SO, flags);
636
637 swrap.libc.handle = handle;
638 }
639 #endif
640 if (handle == NULL) {
641 for (i = 10; i >= 0; i--) {
642 char soname[256] = {0};
643
644 snprintf(soname, sizeof(soname), "libc.so.%d", i);
645 handle = dlopen(soname, flags);
646 if (handle != NULL) {
647 break;
648 }
649 }
650
651 swrap.libc.handle = handle;
652 }
653 break;
654 }
655
656 if (handle == NULL) {
657 #ifdef RTLD_NEXT
658 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
659 #else
660 SWRAP_LOG(SWRAP_LOG_ERROR,
661 "Failed to dlopen library: %s\n",
662 dlerror());
663 exit(-1);
664 #endif
665 }
666
667 return handle;
668 }
669
_swrap_bind_symbol(enum swrap_lib lib,const char * fn_name)670 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
671 {
672 void *handle;
673 void *func;
674
675 handle = swrap_load_lib_handle(lib);
676
677 func = dlsym(handle, fn_name);
678 if (func == NULL) {
679 SWRAP_LOG(SWRAP_LOG_ERROR,
680 "Failed to find %s: %s\n",
681 fn_name,
682 dlerror());
683 exit(-1);
684 }
685
686 SWRAP_LOG(SWRAP_LOG_TRACE,
687 "Loaded %s from %s",
688 fn_name,
689 swrap_str_lib(lib));
690
691 return func;
692 }
693
swrap_mutex_lock(pthread_mutex_t * mutex)694 static void swrap_mutex_lock(pthread_mutex_t *mutex)
695 {
696 int ret;
697
698 ret = pthread_mutex_lock(mutex);
699 if (ret != 0) {
700 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
701 strerror(ret));
702 }
703 }
704
swrap_mutex_unlock(pthread_mutex_t * mutex)705 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
706 {
707 int ret;
708
709 ret = pthread_mutex_unlock(mutex);
710 if (ret != 0) {
711 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
712 strerror(ret));
713 }
714 }
715
716 /*
717 * These macros have a thread race condition on purpose!
718 *
719 * This is an optimization to avoid locking each time we check if the symbol is
720 * bound.
721 */
722 #define swrap_bind_symbol_libc(sym_name) \
723 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
724 swrap_mutex_lock(&libc_symbol_binding_mutex); \
725 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
726 swrap.libc.symbols._libc_##sym_name.obj = \
727 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
728 } \
729 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
730 }
731
732 #define swrap_bind_symbol_libsocket(sym_name) \
733 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
734 swrap_mutex_lock(&libc_symbol_binding_mutex); \
735 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
736 swrap.libc.symbols._libc_##sym_name.obj = \
737 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
738 } \
739 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
740 }
741
742 #define swrap_bind_symbol_libnsl(sym_name) \
743 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
744 swrap_mutex_lock(&libc_symbol_binding_mutex); \
745 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
746 swrap.libc.symbols._libc_##sym_name.obj = \
747 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
748 } \
749 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
750 }
751
752 /****************************************************************************
753 * IMPORTANT
754 ****************************************************************************
755 *
756 * Functions especially from libc need to be loaded individually, you can't
757 * load all at once or gdb will segfault at startup. The same applies to
758 * valgrind and has probably something todo with with the linker. So we need
759 * load each function at the point it is called the first time.
760 *
761 ****************************************************************************/
762
763 #ifdef HAVE_ACCEPT4
libc_accept4(int sockfd,struct sockaddr * addr,socklen_t * addrlen,int flags)764 static int libc_accept4(int sockfd,
765 struct sockaddr *addr,
766 socklen_t *addrlen,
767 int flags)
768 {
769 swrap_bind_symbol_libsocket(accept4);
770
771 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
772 }
773
774 #else /* HAVE_ACCEPT4 */
775
libc_accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen)776 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
777 {
778 swrap_bind_symbol_libsocket(accept);
779
780 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
781 }
782 #endif /* HAVE_ACCEPT4 */
783
libc_bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen)784 static int libc_bind(int sockfd,
785 const struct sockaddr *addr,
786 socklen_t addrlen)
787 {
788 swrap_bind_symbol_libsocket(bind);
789
790 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
791 }
792
libc_close(int fd)793 static int libc_close(int fd)
794 {
795 swrap_bind_symbol_libc(close);
796
797 return swrap.libc.symbols._libc_close.f(fd);
798 }
799
libc_connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen)800 static int libc_connect(int sockfd,
801 const struct sockaddr *addr,
802 socklen_t addrlen)
803 {
804 swrap_bind_symbol_libsocket(connect);
805
806 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
807 }
808
libc_dup(int fd)809 static int libc_dup(int fd)
810 {
811 swrap_bind_symbol_libc(dup);
812
813 return swrap.libc.symbols._libc_dup.f(fd);
814 }
815
libc_dup2(int oldfd,int newfd)816 static int libc_dup2(int oldfd, int newfd)
817 {
818 swrap_bind_symbol_libc(dup2);
819
820 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
821 }
822
823 #ifdef HAVE_EVENTFD
libc_eventfd(int count,int flags)824 static int libc_eventfd(int count, int flags)
825 {
826 swrap_bind_symbol_libc(eventfd);
827
828 return swrap.libc.symbols._libc_eventfd.f(count, flags);
829 }
830 #endif
831
832 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
libc_vfcntl(int fd,int cmd,va_list ap)833 static int libc_vfcntl(int fd, int cmd, va_list ap)
834 {
835 void *arg;
836 int rc;
837
838 swrap_bind_symbol_libc(fcntl);
839
840 arg = va_arg(ap, void *);
841
842 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
843
844 return rc;
845 }
846
libc_getpeername(int sockfd,struct sockaddr * addr,socklen_t * addrlen)847 static int libc_getpeername(int sockfd,
848 struct sockaddr *addr,
849 socklen_t *addrlen)
850 {
851 swrap_bind_symbol_libsocket(getpeername);
852
853 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
854 }
855
libc_getsockname(int sockfd,struct sockaddr * addr,socklen_t * addrlen)856 static int libc_getsockname(int sockfd,
857 struct sockaddr *addr,
858 socklen_t *addrlen)
859 {
860 swrap_bind_symbol_libsocket(getsockname);
861
862 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
863 }
864
libc_getsockopt(int sockfd,int level,int optname,void * optval,socklen_t * optlen)865 static int libc_getsockopt(int sockfd,
866 int level,
867 int optname,
868 void *optval,
869 socklen_t *optlen)
870 {
871 swrap_bind_symbol_libsocket(getsockopt);
872
873 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
874 level,
875 optname,
876 optval,
877 optlen);
878 }
879
880 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
libc_vioctl(int d,unsigned long int request,va_list ap)881 static int libc_vioctl(int d, unsigned long int request, va_list ap)
882 {
883 void *arg;
884 int rc;
885
886 swrap_bind_symbol_libc(ioctl);
887
888 arg = va_arg(ap, void *);
889
890 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
891
892 return rc;
893 }
894
libc_listen(int sockfd,int backlog)895 static int libc_listen(int sockfd, int backlog)
896 {
897 swrap_bind_symbol_libsocket(listen);
898
899 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
900 }
901
libc_fopen(const char * name,const char * mode)902 static FILE *libc_fopen(const char *name, const char *mode)
903 {
904 swrap_bind_symbol_libc(fopen);
905
906 return swrap.libc.symbols._libc_fopen.f(name, mode);
907 }
908
909 #ifdef HAVE_FOPEN64
libc_fopen64(const char * name,const char * mode)910 static FILE *libc_fopen64(const char *name, const char *mode)
911 {
912 swrap_bind_symbol_libc(fopen64);
913
914 return swrap.libc.symbols._libc_fopen64.f(name, mode);
915 }
916 #endif /* HAVE_FOPEN64 */
917
libc_vopen(const char * pathname,int flags,va_list ap)918 static int libc_vopen(const char *pathname, int flags, va_list ap)
919 {
920 int mode = 0;
921 int fd;
922
923 swrap_bind_symbol_libc(open);
924
925 if (flags & O_CREAT) {
926 mode = va_arg(ap, int);
927 }
928 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
929
930 return fd;
931 }
932
libc_open(const char * pathname,int flags,...)933 static int libc_open(const char *pathname, int flags, ...)
934 {
935 va_list ap;
936 int fd;
937
938 va_start(ap, flags);
939 fd = libc_vopen(pathname, flags, ap);
940 va_end(ap);
941
942 return fd;
943 }
944
945 #ifdef HAVE_OPEN64
libc_vopen64(const char * pathname,int flags,va_list ap)946 static int libc_vopen64(const char *pathname, int flags, va_list ap)
947 {
948 int mode = 0;
949 int fd;
950
951 swrap_bind_symbol_libc(open64);
952
953 if (flags & O_CREAT) {
954 mode = va_arg(ap, int);
955 }
956 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
957
958 return fd;
959 }
960 #endif /* HAVE_OPEN64 */
961
libc_vopenat(int dirfd,const char * path,int flags,va_list ap)962 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
963 {
964 int mode = 0;
965 int fd;
966
967 swrap_bind_symbol_libc(openat);
968
969 if (flags & O_CREAT) {
970 mode = va_arg(ap, int);
971 }
972 fd = swrap.libc.symbols._libc_openat.f(dirfd,
973 path,
974 flags,
975 (mode_t)mode);
976
977 return fd;
978 }
979
980 #if 0
981 static int libc_openat(int dirfd, const char *path, int flags, ...)
982 {
983 va_list ap;
984 int fd;
985
986 va_start(ap, flags);
987 fd = libc_vopenat(dirfd, path, flags, ap);
988 va_end(ap);
989
990 return fd;
991 }
992 #endif
993
libc_pipe(int pipefd[2])994 static int libc_pipe(int pipefd[2])
995 {
996 swrap_bind_symbol_libsocket(pipe);
997
998 return swrap.libc.symbols._libc_pipe.f(pipefd);
999 }
1000
libc_read(int fd,void * buf,size_t count)1001 static int libc_read(int fd, void *buf, size_t count)
1002 {
1003 swrap_bind_symbol_libc(read);
1004
1005 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1006 }
1007
libc_readv(int fd,const struct iovec * iov,int iovcnt)1008 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1009 {
1010 swrap_bind_symbol_libsocket(readv);
1011
1012 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1013 }
1014
libc_recv(int sockfd,void * buf,size_t len,int flags)1015 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1016 {
1017 swrap_bind_symbol_libsocket(recv);
1018
1019 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1020 }
1021
libc_recvfrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)1022 static int libc_recvfrom(int sockfd,
1023 void *buf,
1024 size_t len,
1025 int flags,
1026 struct sockaddr *src_addr,
1027 socklen_t *addrlen)
1028 {
1029 swrap_bind_symbol_libsocket(recvfrom);
1030
1031 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1032 buf,
1033 len,
1034 flags,
1035 src_addr,
1036 addrlen);
1037 }
1038
libc_recvmsg(int sockfd,struct msghdr * msg,int flags)1039 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1040 {
1041 swrap_bind_symbol_libsocket(recvmsg);
1042
1043 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1044 }
1045
libc_send(int sockfd,const void * buf,size_t len,int flags)1046 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1047 {
1048 swrap_bind_symbol_libsocket(send);
1049
1050 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1051 }
1052
libc_sendmsg(int sockfd,const struct msghdr * msg,int flags)1053 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1054 {
1055 swrap_bind_symbol_libsocket(sendmsg);
1056
1057 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1058 }
1059
libc_sendto(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * dst_addr,socklen_t addrlen)1060 static int libc_sendto(int sockfd,
1061 const void *buf,
1062 size_t len,
1063 int flags,
1064 const struct sockaddr *dst_addr,
1065 socklen_t addrlen)
1066 {
1067 swrap_bind_symbol_libsocket(sendto);
1068
1069 return swrap.libc.symbols._libc_sendto.f(sockfd,
1070 buf,
1071 len,
1072 flags,
1073 dst_addr,
1074 addrlen);
1075 }
1076
libc_setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen)1077 static int libc_setsockopt(int sockfd,
1078 int level,
1079 int optname,
1080 const void *optval,
1081 socklen_t optlen)
1082 {
1083 swrap_bind_symbol_libsocket(setsockopt);
1084
1085 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1086 level,
1087 optname,
1088 optval,
1089 optlen);
1090 }
1091
1092 #ifdef HAVE_SIGNALFD
libc_signalfd(int fd,const sigset_t * mask,int flags)1093 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1094 {
1095 swrap_bind_symbol_libsocket(signalfd);
1096
1097 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1098 }
1099 #endif
1100
libc_socket(int domain,int type,int protocol)1101 static int libc_socket(int domain, int type, int protocol)
1102 {
1103 swrap_bind_symbol_libsocket(socket);
1104
1105 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1106 }
1107
libc_socketpair(int domain,int type,int protocol,int sv[2])1108 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1109 {
1110 swrap_bind_symbol_libsocket(socketpair);
1111
1112 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1113 }
1114
1115 #ifdef HAVE_TIMERFD_CREATE
libc_timerfd_create(int clockid,int flags)1116 static int libc_timerfd_create(int clockid, int flags)
1117 {
1118 swrap_bind_symbol_libc(timerfd_create);
1119
1120 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1121 }
1122 #endif
1123
libc_write(int fd,const void * buf,size_t count)1124 static ssize_t libc_write(int fd, const void *buf, size_t count)
1125 {
1126 swrap_bind_symbol_libc(write);
1127
1128 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1129 }
1130
libc_writev(int fd,const struct iovec * iov,int iovcnt)1131 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1132 {
1133 swrap_bind_symbol_libsocket(writev);
1134
1135 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1136 }
1137
1138 /* DO NOT call this function during library initialization! */
swrap_bind_symbol_all(void)1139 static void swrap_bind_symbol_all(void)
1140 {
1141 #ifdef HAVE_ACCEPT4
1142 swrap_bind_symbol_libsocket(accept4);
1143 #else
1144 swrap_bind_symbol_libsocket(accept);
1145 #endif
1146 swrap_bind_symbol_libsocket(bind);
1147 swrap_bind_symbol_libc(close);
1148 swrap_bind_symbol_libsocket(connect);
1149 swrap_bind_symbol_libc(dup);
1150 swrap_bind_symbol_libc(dup2);
1151 swrap_bind_symbol_libc(fcntl);
1152 swrap_bind_symbol_libc(fopen);
1153 #ifdef HAVE_FOPEN64
1154 swrap_bind_symbol_libc(fopen64);
1155 #endif
1156 #ifdef HAVE_EVENTFD
1157 swrap_bind_symbol_libc(eventfd);
1158 #endif
1159 swrap_bind_symbol_libsocket(getpeername);
1160 swrap_bind_symbol_libsocket(getsockname);
1161 swrap_bind_symbol_libsocket(getsockopt);
1162 swrap_bind_symbol_libc(ioctl);
1163 swrap_bind_symbol_libsocket(listen);
1164 swrap_bind_symbol_libc(open);
1165 #ifdef HAVE_OPEN64
1166 swrap_bind_symbol_libc(open64);
1167 #endif
1168 swrap_bind_symbol_libc(openat);
1169 swrap_bind_symbol_libsocket(pipe);
1170 swrap_bind_symbol_libc(read);
1171 swrap_bind_symbol_libsocket(readv);
1172 swrap_bind_symbol_libsocket(recv);
1173 swrap_bind_symbol_libsocket(recvfrom);
1174 swrap_bind_symbol_libsocket(recvmsg);
1175 swrap_bind_symbol_libsocket(send);
1176 swrap_bind_symbol_libsocket(sendmsg);
1177 swrap_bind_symbol_libsocket(sendto);
1178 swrap_bind_symbol_libsocket(setsockopt);
1179 #ifdef HAVE_SIGNALFD
1180 swrap_bind_symbol_libsocket(signalfd);
1181 #endif
1182 swrap_bind_symbol_libsocket(socket);
1183 swrap_bind_symbol_libsocket(socketpair);
1184 #ifdef HAVE_TIMERFD_CREATE
1185 swrap_bind_symbol_libc(timerfd_create);
1186 #endif
1187 swrap_bind_symbol_libc(write);
1188 swrap_bind_symbol_libsocket(writev);
1189 }
1190
1191 /*********************************************************
1192 * SWRAP HELPER FUNCTIONS
1193 *********************************************************/
1194
1195 #ifdef HAVE_IPV6
1196 /*
1197 * FD00::5357:5FXX
1198 */
swrap_ipv6(void)1199 static const struct in6_addr *swrap_ipv6(void)
1200 {
1201 static struct in6_addr v;
1202 static int initialized;
1203 int ret;
1204
1205 if (initialized) {
1206 return &v;
1207 }
1208 initialized = 1;
1209
1210 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1211 if (ret <= 0) {
1212 abort();
1213 }
1214
1215 return &v;
1216 }
1217 #endif
1218
set_port(int family,int prt,struct swrap_address * addr)1219 static void set_port(int family, int prt, struct swrap_address *addr)
1220 {
1221 switch (family) {
1222 case AF_INET:
1223 addr->sa.in.sin_port = htons(prt);
1224 break;
1225 #ifdef HAVE_IPV6
1226 case AF_INET6:
1227 addr->sa.in6.sin6_port = htons(prt);
1228 break;
1229 #endif
1230 }
1231 }
1232
socket_length(int family)1233 static size_t socket_length(int family)
1234 {
1235 switch (family) {
1236 case AF_INET:
1237 return sizeof(struct sockaddr_in);
1238 #ifdef HAVE_IPV6
1239 case AF_INET6:
1240 return sizeof(struct sockaddr_in6);
1241 #endif
1242 }
1243 return 0;
1244 }
1245
swrap_get_socket_info(int si_index)1246 static struct socket_info *swrap_get_socket_info(int si_index)
1247 {
1248 return (struct socket_info *)(&(sockets[si_index].info));
1249 }
1250
swrap_get_refcount(struct socket_info * si)1251 static int swrap_get_refcount(struct socket_info *si)
1252 {
1253 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1254 return sic->meta.refcount;
1255 }
1256
swrap_inc_refcount(struct socket_info * si)1257 static void swrap_inc_refcount(struct socket_info *si)
1258 {
1259 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1260
1261 sic->meta.refcount += 1;
1262 }
1263
swrap_dec_refcount(struct socket_info * si)1264 static void swrap_dec_refcount(struct socket_info *si)
1265 {
1266 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1267
1268 sic->meta.refcount -= 1;
1269 }
1270
swrap_get_next_free(struct socket_info * si)1271 static int swrap_get_next_free(struct socket_info *si)
1272 {
1273 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1274
1275 return sic->meta.next_free;
1276 }
1277
swrap_set_next_free(struct socket_info * si,int next_free)1278 static void swrap_set_next_free(struct socket_info *si, int next_free)
1279 {
1280 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1281
1282 sic->meta.next_free = next_free;
1283 }
1284
socket_wrapper_dir(void)1285 static char *socket_wrapper_dir(void)
1286 {
1287 char *swrap_dir = NULL;
1288 char *s = getenv("SOCKET_WRAPPER_DIR");
1289
1290 if (s == NULL) {
1291 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set\n");
1292 return NULL;
1293 }
1294
1295 swrap_dir = realpath(s, NULL);
1296 if (swrap_dir == NULL) {
1297 SWRAP_LOG(SWRAP_LOG_ERROR,
1298 "Unable to resolve socket_wrapper dir path: %s",
1299 strerror(errno));
1300 return NULL;
1301 }
1302
1303 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1304 return swrap_dir;
1305 }
1306
socket_wrapper_mtu(void)1307 static unsigned int socket_wrapper_mtu(void)
1308 {
1309 static unsigned int max_mtu = 0;
1310 unsigned int tmp;
1311 const char *s;
1312 char *endp;
1313
1314 swrap_mutex_lock(&mtu_update_mutex);
1315
1316 if (max_mtu != 0) {
1317 goto done;
1318 }
1319
1320 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1321
1322 s = getenv("SOCKET_WRAPPER_MTU");
1323 if (s == NULL) {
1324 goto done;
1325 }
1326
1327 tmp = strtol(s, &endp, 10);
1328 if (s == endp) {
1329 goto done;
1330 }
1331
1332 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1333 goto done;
1334 }
1335 max_mtu = tmp;
1336
1337 done:
1338 swrap_mutex_unlock(&mtu_update_mutex);
1339 return max_mtu;
1340 }
1341
socket_wrapper_init_mutex(pthread_mutex_t * m)1342 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1343 {
1344 pthread_mutexattr_t ma;
1345 int ret;
1346
1347 ret = pthread_mutexattr_init(&ma);
1348 if (ret != 0) {
1349 return ret;
1350 }
1351
1352 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1353 if (ret != 0) {
1354 goto done;
1355 }
1356
1357 ret = pthread_mutex_init(m, &ma);
1358
1359 done:
1360 pthread_mutexattr_destroy(&ma);
1361
1362 return ret;
1363 }
1364
socket_wrapper_max_sockets(void)1365 static size_t socket_wrapper_max_sockets(void)
1366 {
1367 const char *s;
1368 size_t tmp;
1369 char *endp;
1370
1371 if (socket_info_max != 0) {
1372 return socket_info_max;
1373 }
1374
1375 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1376
1377 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1378 if (s == NULL || s[0] == '\0') {
1379 goto done;
1380 }
1381
1382 tmp = strtoul(s, &endp, 10);
1383 if (s == endp) {
1384 goto done;
1385 }
1386 if (tmp == 0) {
1387 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1388 SWRAP_LOG(SWRAP_LOG_ERROR,
1389 "Invalid number of sockets specified, "
1390 "using default (%zu)",
1391 tmp);
1392 }
1393
1394 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1395 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1396 SWRAP_LOG(SWRAP_LOG_ERROR,
1397 "Invalid number of sockets specified, "
1398 "using maximum (%zu).",
1399 tmp);
1400 }
1401
1402 socket_info_max = tmp;
1403
1404 done:
1405 return socket_info_max;
1406 }
1407
socket_wrapper_init_fds_idx(void)1408 static void socket_wrapper_init_fds_idx(void)
1409 {
1410 int *tmp = NULL;
1411 size_t i;
1412
1413 if (socket_fds_idx != NULL) {
1414 return;
1415 }
1416
1417 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1418 if (tmp == NULL) {
1419 SWRAP_LOG(SWRAP_LOG_ERROR,
1420 "Failed to allocate socket fds index array: %s",
1421 strerror(errno));
1422 exit(-1);
1423 }
1424
1425 for (i = 0; i < socket_fds_max; i++) {
1426 tmp[i] = -1;
1427 }
1428
1429 socket_fds_idx = tmp;
1430 }
1431
socket_wrapper_init_sockets(void)1432 static void socket_wrapper_init_sockets(void)
1433 {
1434 size_t max_sockets;
1435 size_t i;
1436 int ret;
1437
1438 swrap_mutex_lock(&sockets_mutex);
1439
1440 if (sockets != NULL) {
1441 swrap_mutex_unlock(&sockets_mutex);
1442 return;
1443 }
1444
1445 socket_wrapper_init_fds_idx();
1446
1447 /* Needs to be called inside the sockets_mutex lock here. */
1448 max_sockets = socket_wrapper_max_sockets();
1449
1450 sockets = (struct socket_info_container *)calloc(max_sockets,
1451 sizeof(struct socket_info_container));
1452
1453 if (sockets == NULL) {
1454 SWRAP_LOG(SWRAP_LOG_ERROR,
1455 "Failed to allocate sockets array: %s",
1456 strerror(errno));
1457 swrap_mutex_unlock(&sockets_mutex);
1458 exit(-1);
1459 }
1460
1461 swrap_mutex_lock(&first_free_mutex);
1462
1463 first_free = 0;
1464
1465 for (i = 0; i < max_sockets; i++) {
1466 swrap_set_next_free(&sockets[i].info, i+1);
1467 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1468 if (ret != 0) {
1469 SWRAP_LOG(SWRAP_LOG_ERROR,
1470 "Failed to initialize pthread mutex");
1471 goto done;
1472 }
1473 }
1474
1475 /* mark the end of the free list */
1476 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1477
1478 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1479 if (ret != 0) {
1480 SWRAP_LOG(SWRAP_LOG_ERROR,
1481 "Failed to initialize pthread mutex");
1482 goto done;
1483 }
1484
1485 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1486 if (ret != 0) {
1487 SWRAP_LOG(SWRAP_LOG_ERROR,
1488 "Failed to initialize pthread mutex");
1489 goto done;
1490 }
1491
1492 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1493 if (ret != 0) {
1494 SWRAP_LOG(SWRAP_LOG_ERROR,
1495 "Failed to initialize pthread mutex");
1496 goto done;
1497 }
1498
1499 done:
1500 swrap_mutex_unlock(&first_free_mutex);
1501 swrap_mutex_unlock(&sockets_mutex);
1502 if (ret != 0) {
1503 exit(-1);
1504 }
1505 }
1506
socket_wrapper_enabled(void)1507 bool socket_wrapper_enabled(void)
1508 {
1509 char *s = socket_wrapper_dir();
1510
1511 if (s == NULL) {
1512 return false;
1513 }
1514
1515 SAFE_FREE(s);
1516
1517 socket_wrapper_init_sockets();
1518
1519 return true;
1520 }
1521
socket_wrapper_default_iface(void)1522 static unsigned int socket_wrapper_default_iface(void)
1523 {
1524 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1525 if (s) {
1526 unsigned int iface;
1527 if (sscanf(s, "%u", &iface) == 1) {
1528 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1529 return iface;
1530 }
1531 }
1532 }
1533
1534 return 1;/* 127.0.0.1 */
1535 }
1536
set_socket_info_index(int fd,int idx)1537 static void set_socket_info_index(int fd, int idx)
1538 {
1539 socket_fds_idx[fd] = idx;
1540 /* This builtin issues a full memory barrier. */
1541 __sync_synchronize();
1542 }
1543
reset_socket_info_index(int fd)1544 static void reset_socket_info_index(int fd)
1545 {
1546 set_socket_info_index(fd, -1);
1547 }
1548
find_socket_info_index(int fd)1549 static int find_socket_info_index(int fd)
1550 {
1551 if (fd < 0) {
1552 return -1;
1553 }
1554
1555 if (socket_fds_idx == NULL) {
1556 return -1;
1557 }
1558
1559 if ((size_t)fd >= socket_fds_max) {
1560 /*
1561 * Do not add a log here as some applications do stupid things
1562 * like:
1563 *
1564 * for (fd = 0; fd <= getdtablesize(); fd++) {
1565 * close(fd)
1566 * };
1567 *
1568 * This would produce millions of lines of debug messages.
1569 */
1570 #if 0
1571 SWRAP_LOG(SWRAP_LOG_ERROR,
1572 "Looking for a socket info for the fd %d is over the "
1573 "max socket index limit of %zu.",
1574 fd,
1575 socket_fds_max);
1576 #endif
1577 return -1;
1578 }
1579
1580 /* This builtin issues a full memory barrier. */
1581 __sync_synchronize();
1582 return socket_fds_idx[fd];
1583 }
1584
swrap_add_socket_info(struct socket_info * si_input)1585 static int swrap_add_socket_info(struct socket_info *si_input)
1586 {
1587 struct socket_info *si = NULL;
1588 int si_index = -1;
1589
1590 if (si_input == NULL) {
1591 errno = EINVAL;
1592 return -1;
1593 }
1594
1595 swrap_mutex_lock(&first_free_mutex);
1596 if (first_free == -1) {
1597 errno = ENFILE;
1598 goto out;
1599 }
1600
1601 si_index = first_free;
1602 si = swrap_get_socket_info(si_index);
1603
1604 SWRAP_LOCK_SI(si);
1605
1606 first_free = swrap_get_next_free(si);
1607 *si = *si_input;
1608 swrap_inc_refcount(si);
1609
1610 SWRAP_UNLOCK_SI(si);
1611
1612 out:
1613 swrap_mutex_unlock(&first_free_mutex);
1614
1615 return si_index;
1616 }
1617
swrap_create_socket(struct socket_info * si,int fd)1618 static int swrap_create_socket(struct socket_info *si, int fd)
1619 {
1620 int idx;
1621
1622 if ((size_t)fd >= socket_fds_max) {
1623 SWRAP_LOG(SWRAP_LOG_ERROR,
1624 "The max socket index limit of %zu has been reached, "
1625 "trying to add %d",
1626 socket_fds_max,
1627 fd);
1628 return -1;
1629 }
1630
1631 idx = swrap_add_socket_info(si);
1632 if (idx == -1) {
1633 return -1;
1634 }
1635
1636 set_socket_info_index(fd, idx);
1637
1638 return idx;
1639 }
1640
convert_un_in(const struct sockaddr_un * un,struct sockaddr * in,socklen_t * len)1641 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1642 {
1643 unsigned int iface;
1644 unsigned int prt;
1645 const char *p;
1646 char type;
1647
1648 p = strrchr(un->sun_path, '/');
1649 if (p) p++; else p = un->sun_path;
1650
1651 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1652 errno = EINVAL;
1653 return -1;
1654 }
1655
1656 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1657 type, iface, prt);
1658
1659 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1660 errno = EINVAL;
1661 return -1;
1662 }
1663
1664 if (prt > 0xFFFF) {
1665 errno = EINVAL;
1666 return -1;
1667 }
1668
1669 switch(type) {
1670 case SOCKET_TYPE_CHAR_TCP:
1671 case SOCKET_TYPE_CHAR_UDP: {
1672 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1673
1674 if ((*len) < sizeof(*in2)) {
1675 errno = EINVAL;
1676 return -1;
1677 }
1678
1679 memset(in2, 0, sizeof(*in2));
1680 in2->sin_family = AF_INET;
1681 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1682 in2->sin_port = htons(prt);
1683
1684 *len = sizeof(*in2);
1685 break;
1686 }
1687 #ifdef HAVE_IPV6
1688 case SOCKET_TYPE_CHAR_TCP_V6:
1689 case SOCKET_TYPE_CHAR_UDP_V6: {
1690 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1691
1692 if ((*len) < sizeof(*in2)) {
1693 errno = EINVAL;
1694 return -1;
1695 }
1696
1697 memset(in2, 0, sizeof(*in2));
1698 in2->sin6_family = AF_INET6;
1699 in2->sin6_addr = *swrap_ipv6();
1700 in2->sin6_addr.s6_addr[15] = iface;
1701 in2->sin6_port = htons(prt);
1702
1703 *len = sizeof(*in2);
1704 break;
1705 }
1706 #endif
1707 default:
1708 errno = EINVAL;
1709 return -1;
1710 }
1711
1712 return 0;
1713 }
1714
convert_in_un_remote(struct socket_info * si,const struct sockaddr * inaddr,struct sockaddr_un * un,int * bcast)1715 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1716 int *bcast)
1717 {
1718 char type = '\0';
1719 unsigned int prt;
1720 unsigned int iface;
1721 int is_bcast = 0;
1722 char *swrap_dir = NULL;
1723
1724 if (bcast) *bcast = 0;
1725
1726 switch (inaddr->sa_family) {
1727 case AF_INET: {
1728 const struct sockaddr_in *in =
1729 (const struct sockaddr_in *)(const void *)inaddr;
1730 unsigned int addr = ntohl(in->sin_addr.s_addr);
1731 char u_type = '\0';
1732 char b_type = '\0';
1733 char a_type = '\0';
1734
1735 switch (si->type) {
1736 case SOCK_STREAM:
1737 u_type = SOCKET_TYPE_CHAR_TCP;
1738 break;
1739 case SOCK_DGRAM:
1740 u_type = SOCKET_TYPE_CHAR_UDP;
1741 a_type = SOCKET_TYPE_CHAR_UDP;
1742 b_type = SOCKET_TYPE_CHAR_UDP;
1743 break;
1744 default:
1745 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1746 errno = ESOCKTNOSUPPORT;
1747 return -1;
1748 }
1749
1750 prt = ntohs(in->sin_port);
1751 if (a_type && addr == 0xFFFFFFFF) {
1752 /* 255.255.255.255 only udp */
1753 is_bcast = 2;
1754 type = a_type;
1755 iface = socket_wrapper_default_iface();
1756 } else if (b_type && addr == 0x7FFFFFFF) {
1757 /* 127.255.255.255 only udp */
1758 is_bcast = 1;
1759 type = b_type;
1760 iface = socket_wrapper_default_iface();
1761 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1762 /* 127.0.0.X */
1763 is_bcast = 0;
1764 type = u_type;
1765 iface = (addr & 0x000000FF);
1766 } else {
1767 errno = ENETUNREACH;
1768 return -1;
1769 }
1770 if (bcast) *bcast = is_bcast;
1771 break;
1772 }
1773 #ifdef HAVE_IPV6
1774 case AF_INET6: {
1775 const struct sockaddr_in6 *in =
1776 (const struct sockaddr_in6 *)(const void *)inaddr;
1777 struct in6_addr cmp1, cmp2;
1778
1779 switch (si->type) {
1780 case SOCK_STREAM:
1781 type = SOCKET_TYPE_CHAR_TCP_V6;
1782 break;
1783 case SOCK_DGRAM:
1784 type = SOCKET_TYPE_CHAR_UDP_V6;
1785 break;
1786 default:
1787 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1788 errno = ESOCKTNOSUPPORT;
1789 return -1;
1790 }
1791
1792 /* XXX no multicast/broadcast */
1793
1794 prt = ntohs(in->sin6_port);
1795
1796 cmp1 = *swrap_ipv6();
1797 cmp2 = in->sin6_addr;
1798 cmp2.s6_addr[15] = 0;
1799 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1800 iface = in->sin6_addr.s6_addr[15];
1801 } else {
1802 errno = ENETUNREACH;
1803 return -1;
1804 }
1805
1806 break;
1807 }
1808 #endif
1809 default:
1810 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1811 errno = ENETUNREACH;
1812 return -1;
1813 }
1814
1815 if (prt == 0) {
1816 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1817 errno = EINVAL;
1818 return -1;
1819 }
1820
1821 swrap_dir = socket_wrapper_dir();
1822 if (swrap_dir == NULL) {
1823 errno = EINVAL;
1824 return -1;
1825 }
1826
1827 if (is_bcast) {
1828 snprintf(un->sun_path, sizeof(un->sun_path),
1829 "%s/EINVAL", swrap_dir);
1830 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1831 SAFE_FREE(swrap_dir);
1832 /* the caller need to do more processing */
1833 return 0;
1834 }
1835
1836 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1837 swrap_dir, type, iface, prt);
1838 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1839
1840 SAFE_FREE(swrap_dir);
1841
1842 return 0;
1843 }
1844
convert_in_un_alloc(struct socket_info * si,const struct sockaddr * inaddr,struct sockaddr_un * un,int * bcast)1845 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1846 int *bcast)
1847 {
1848 char type = '\0';
1849 unsigned int prt;
1850 unsigned int iface;
1851 struct stat st;
1852 int is_bcast = 0;
1853 char *swrap_dir = NULL;
1854
1855 if (bcast) *bcast = 0;
1856
1857 switch (si->family) {
1858 case AF_INET: {
1859 const struct sockaddr_in *in =
1860 (const struct sockaddr_in *)(const void *)inaddr;
1861 unsigned int addr = ntohl(in->sin_addr.s_addr);
1862 char u_type = '\0';
1863 char d_type = '\0';
1864 char b_type = '\0';
1865 char a_type = '\0';
1866
1867 prt = ntohs(in->sin_port);
1868
1869 switch (si->type) {
1870 case SOCK_STREAM:
1871 u_type = SOCKET_TYPE_CHAR_TCP;
1872 d_type = SOCKET_TYPE_CHAR_TCP;
1873 break;
1874 case SOCK_DGRAM:
1875 u_type = SOCKET_TYPE_CHAR_UDP;
1876 d_type = SOCKET_TYPE_CHAR_UDP;
1877 a_type = SOCKET_TYPE_CHAR_UDP;
1878 b_type = SOCKET_TYPE_CHAR_UDP;
1879 break;
1880 default:
1881 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1882 errno = ESOCKTNOSUPPORT;
1883 return -1;
1884 }
1885
1886 if (addr == 0) {
1887 /* 0.0.0.0 */
1888 is_bcast = 0;
1889 type = d_type;
1890 iface = socket_wrapper_default_iface();
1891 } else if (a_type && addr == 0xFFFFFFFF) {
1892 /* 255.255.255.255 only udp */
1893 is_bcast = 2;
1894 type = a_type;
1895 iface = socket_wrapper_default_iface();
1896 } else if (b_type && addr == 0x7FFFFFFF) {
1897 /* 127.255.255.255 only udp */
1898 is_bcast = 1;
1899 type = b_type;
1900 iface = socket_wrapper_default_iface();
1901 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1902 /* 127.0.0.X */
1903 is_bcast = 0;
1904 type = u_type;
1905 iface = (addr & 0x000000FF);
1906 } else {
1907 errno = EADDRNOTAVAIL;
1908 return -1;
1909 }
1910
1911 /* Store the bind address for connect() */
1912 if (si->bindname.sa_socklen == 0) {
1913 struct sockaddr_in bind_in;
1914 socklen_t blen = sizeof(struct sockaddr_in);
1915
1916 ZERO_STRUCT(bind_in);
1917 bind_in.sin_family = in->sin_family;
1918 bind_in.sin_port = in->sin_port;
1919 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1920
1921 si->bindname.sa_socklen = blen;
1922 memcpy(&si->bindname.sa.in, &bind_in, blen);
1923 }
1924
1925 break;
1926 }
1927 #ifdef HAVE_IPV6
1928 case AF_INET6: {
1929 const struct sockaddr_in6 *in =
1930 (const struct sockaddr_in6 *)(const void *)inaddr;
1931 struct in6_addr cmp1, cmp2;
1932
1933 switch (si->type) {
1934 case SOCK_STREAM:
1935 type = SOCKET_TYPE_CHAR_TCP_V6;
1936 break;
1937 case SOCK_DGRAM:
1938 type = SOCKET_TYPE_CHAR_UDP_V6;
1939 break;
1940 default:
1941 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1942 errno = ESOCKTNOSUPPORT;
1943 return -1;
1944 }
1945
1946 /* XXX no multicast/broadcast */
1947
1948 prt = ntohs(in->sin6_port);
1949
1950 cmp1 = *swrap_ipv6();
1951 cmp2 = in->sin6_addr;
1952 cmp2.s6_addr[15] = 0;
1953 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1954 iface = socket_wrapper_default_iface();
1955 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1956 iface = in->sin6_addr.s6_addr[15];
1957 } else {
1958 errno = EADDRNOTAVAIL;
1959 return -1;
1960 }
1961
1962 /* Store the bind address for connect() */
1963 if (si->bindname.sa_socklen == 0) {
1964 struct sockaddr_in6 bind_in;
1965 socklen_t blen = sizeof(struct sockaddr_in6);
1966
1967 ZERO_STRUCT(bind_in);
1968 bind_in.sin6_family = in->sin6_family;
1969 bind_in.sin6_port = in->sin6_port;
1970
1971 bind_in.sin6_addr = *swrap_ipv6();
1972 bind_in.sin6_addr.s6_addr[15] = iface;
1973
1974 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1975 si->bindname.sa_socklen = blen;
1976 }
1977
1978 break;
1979 }
1980 #endif
1981 default:
1982 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1983 errno = EADDRNOTAVAIL;
1984 return -1;
1985 }
1986
1987
1988 if (bcast) *bcast = is_bcast;
1989
1990 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1991 errno = EINVAL;
1992 return -1;
1993 }
1994
1995 swrap_dir = socket_wrapper_dir();
1996 if (swrap_dir == NULL) {
1997 errno = EINVAL;
1998 return -1;
1999 }
2000
2001 if (prt == 0) {
2002 /* handle auto-allocation of ephemeral ports */
2003 for (prt = 5001; prt < 10000; prt++) {
2004 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2005 swrap_dir, type, iface, prt);
2006 if (stat(un->sun_path, &st) == 0) continue;
2007
2008 set_port(si->family, prt, &si->myname);
2009 set_port(si->family, prt, &si->bindname);
2010
2011 break;
2012 }
2013
2014 if (prt == 10000) {
2015 errno = ENFILE;
2016 SAFE_FREE(swrap_dir);
2017 return -1;
2018 }
2019 }
2020
2021 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2022 swrap_dir, type, iface, prt);
2023 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2024
2025 SAFE_FREE(swrap_dir);
2026
2027 return 0;
2028 }
2029
find_socket_info(int fd)2030 static struct socket_info *find_socket_info(int fd)
2031 {
2032 int idx = find_socket_info_index(fd);
2033
2034 if (idx == -1) {
2035 return NULL;
2036 }
2037
2038 return swrap_get_socket_info(idx);
2039 }
2040
2041 #if 0 /* FIXME */
2042 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2043 {
2044 struct socket_info_fd *f;
2045 const struct socket_info *last_s = NULL;
2046
2047 /* first catch invalid input */
2048 switch (sa->sa_family) {
2049 case AF_INET:
2050 if (len < sizeof(struct sockaddr_in)) {
2051 return false;
2052 }
2053 break;
2054 #ifdef HAVE_IPV6
2055 case AF_INET6:
2056 if (len < sizeof(struct sockaddr_in6)) {
2057 return false;
2058 }
2059 break;
2060 #endif
2061 default:
2062 return false;
2063 break;
2064 }
2065
2066 for (f = socket_fds; f; f = f->next) {
2067 struct socket_info *s = swrap_get_socket_info(f->si_index);
2068
2069 if (s == last_s) {
2070 continue;
2071 }
2072 last_s = s;
2073
2074 if (s->myname == NULL) {
2075 continue;
2076 }
2077 if (s->myname->sa_family != sa->sa_family) {
2078 continue;
2079 }
2080 switch (s->myname->sa_family) {
2081 case AF_INET: {
2082 struct sockaddr_in *sin1, *sin2;
2083
2084 sin1 = (struct sockaddr_in *)s->myname;
2085 sin2 = (struct sockaddr_in *)sa;
2086
2087 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2088 continue;
2089 }
2090 if (sin1->sin_port != sin2->sin_port) {
2091 continue;
2092 }
2093 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2094 continue;
2095 }
2096
2097 /* found */
2098 return true;
2099 break;
2100 }
2101 #ifdef HAVE_IPV6
2102 case AF_INET6: {
2103 struct sockaddr_in6 *sin1, *sin2;
2104
2105 sin1 = (struct sockaddr_in6 *)s->myname;
2106 sin2 = (struct sockaddr_in6 *)sa;
2107
2108 if (sin1->sin6_port != sin2->sin6_port) {
2109 continue;
2110 }
2111 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2112 &sin2->sin6_addr))
2113 {
2114 continue;
2115 }
2116
2117 /* found */
2118 return true;
2119 break;
2120 }
2121 #endif
2122 default:
2123 continue;
2124 break;
2125
2126 }
2127 }
2128
2129 return false;
2130 }
2131 #endif
2132
swrap_remove_stale(int fd)2133 static void swrap_remove_stale(int fd)
2134 {
2135 struct socket_info *si;
2136 int si_index;
2137
2138 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2139
2140 swrap_mutex_lock(&socket_reset_mutex);
2141
2142 si_index = find_socket_info_index(fd);
2143 if (si_index == -1) {
2144 swrap_mutex_unlock(&socket_reset_mutex);
2145 return;
2146 }
2147
2148 reset_socket_info_index(fd);
2149
2150 si = swrap_get_socket_info(si_index);
2151
2152 swrap_mutex_lock(&first_free_mutex);
2153 SWRAP_LOCK_SI(si);
2154
2155 swrap_dec_refcount(si);
2156
2157 if (swrap_get_refcount(si) > 0) {
2158 goto out;
2159 }
2160
2161 if (si->un_addr.sun_path[0] != '\0') {
2162 unlink(si->un_addr.sun_path);
2163 }
2164
2165 swrap_set_next_free(si, first_free);
2166 first_free = si_index;
2167
2168 out:
2169 SWRAP_UNLOCK_SI(si);
2170 swrap_mutex_unlock(&first_free_mutex);
2171 swrap_mutex_unlock(&socket_reset_mutex);
2172 }
2173
sockaddr_convert_to_un(struct socket_info * si,const struct sockaddr * in_addr,socklen_t in_len,struct sockaddr_un * out_addr,int alloc_sock,int * bcast)2174 static int sockaddr_convert_to_un(struct socket_info *si,
2175 const struct sockaddr *in_addr,
2176 socklen_t in_len,
2177 struct sockaddr_un *out_addr,
2178 int alloc_sock,
2179 int *bcast)
2180 {
2181 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2182
2183 (void) in_len; /* unused */
2184
2185 if (out_addr == NULL) {
2186 return 0;
2187 }
2188
2189 out->sa_family = AF_UNIX;
2190 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2191 out->sa_len = sizeof(*out_addr);
2192 #endif
2193
2194 switch (in_addr->sa_family) {
2195 case AF_UNSPEC: {
2196 const struct sockaddr_in *sin;
2197 if (si->family != AF_INET) {
2198 break;
2199 }
2200 if (in_len < sizeof(struct sockaddr_in)) {
2201 break;
2202 }
2203 sin = (const struct sockaddr_in *)(const void *)in_addr;
2204 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2205 break;
2206 }
2207
2208 /*
2209 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2210 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2211 */
2212
2213 FALL_THROUGH;
2214 }
2215 case AF_INET:
2216 #ifdef HAVE_IPV6
2217 case AF_INET6:
2218 #endif
2219 switch (si->type) {
2220 case SOCK_STREAM:
2221 case SOCK_DGRAM:
2222 break;
2223 default:
2224 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2225 errno = ESOCKTNOSUPPORT;
2226 return -1;
2227 }
2228 if (alloc_sock) {
2229 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2230 } else {
2231 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2232 }
2233 default:
2234 break;
2235 }
2236
2237 errno = EAFNOSUPPORT;
2238 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2239 return -1;
2240 }
2241
sockaddr_convert_from_un(const struct socket_info * si,const struct sockaddr_un * in_addr,socklen_t un_addrlen,int family,struct sockaddr * out_addr,socklen_t * out_addrlen)2242 static int sockaddr_convert_from_un(const struct socket_info *si,
2243 const struct sockaddr_un *in_addr,
2244 socklen_t un_addrlen,
2245 int family,
2246 struct sockaddr *out_addr,
2247 socklen_t *out_addrlen)
2248 {
2249 int ret;
2250
2251 if (out_addr == NULL || out_addrlen == NULL)
2252 return 0;
2253
2254 if (un_addrlen == 0) {
2255 *out_addrlen = 0;
2256 return 0;
2257 }
2258
2259 switch (family) {
2260 case AF_INET:
2261 #ifdef HAVE_IPV6
2262 case AF_INET6:
2263 #endif
2264 switch (si->type) {
2265 case SOCK_STREAM:
2266 case SOCK_DGRAM:
2267 break;
2268 default:
2269 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2270 errno = ESOCKTNOSUPPORT;
2271 return -1;
2272 }
2273 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2274 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2275 out_addr->sa_len = *out_addrlen;
2276 #endif
2277 return ret;
2278 default:
2279 break;
2280 }
2281
2282 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2283 errno = EAFNOSUPPORT;
2284 return -1;
2285 }
2286
2287 enum swrap_packet_type {
2288 SWRAP_CONNECT_SEND,
2289 SWRAP_CONNECT_UNREACH,
2290 SWRAP_CONNECT_RECV,
2291 SWRAP_CONNECT_ACK,
2292 SWRAP_ACCEPT_SEND,
2293 SWRAP_ACCEPT_RECV,
2294 SWRAP_ACCEPT_ACK,
2295 SWRAP_RECVFROM,
2296 SWRAP_SENDTO,
2297 SWRAP_SENDTO_UNREACH,
2298 SWRAP_PENDING_RST,
2299 SWRAP_RECV,
2300 SWRAP_RECV_RST,
2301 SWRAP_SEND,
2302 SWRAP_SEND_RST,
2303 SWRAP_CLOSE_SEND,
2304 SWRAP_CLOSE_RECV,
2305 SWRAP_CLOSE_ACK,
2306 };
2307
2308 struct swrap_file_hdr {
2309 uint32_t magic;
2310 uint16_t version_major;
2311 uint16_t version_minor;
2312 int32_t timezone;
2313 uint32_t sigfigs;
2314 uint32_t frame_max_len;
2315 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2316 uint32_t link_type;
2317 };
2318 #define SWRAP_FILE_HDR_SIZE 24
2319
2320 struct swrap_packet_frame {
2321 uint32_t seconds;
2322 uint32_t micro_seconds;
2323 uint32_t recorded_length;
2324 uint32_t full_length;
2325 };
2326 #define SWRAP_PACKET_FRAME_SIZE 16
2327
2328 union swrap_packet_ip {
2329 struct {
2330 uint8_t ver_hdrlen;
2331 uint8_t tos;
2332 uint16_t packet_length;
2333 uint16_t identification;
2334 uint8_t flags;
2335 uint8_t fragment;
2336 uint8_t ttl;
2337 uint8_t protocol;
2338 uint16_t hdr_checksum;
2339 uint32_t src_addr;
2340 uint32_t dest_addr;
2341 } v4;
2342 #define SWRAP_PACKET_IP_V4_SIZE 20
2343 struct {
2344 uint8_t ver_prio;
2345 uint8_t flow_label_high;
2346 uint16_t flow_label_low;
2347 uint16_t payload_length;
2348 uint8_t next_header;
2349 uint8_t hop_limit;
2350 uint8_t src_addr[16];
2351 uint8_t dest_addr[16];
2352 } v6;
2353 #define SWRAP_PACKET_IP_V6_SIZE 40
2354 };
2355 #define SWRAP_PACKET_IP_SIZE 40
2356
2357 union swrap_packet_payload {
2358 struct {
2359 uint16_t source_port;
2360 uint16_t dest_port;
2361 uint32_t seq_num;
2362 uint32_t ack_num;
2363 uint8_t hdr_length;
2364 uint8_t control;
2365 uint16_t window;
2366 uint16_t checksum;
2367 uint16_t urg;
2368 } tcp;
2369 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2370 struct {
2371 uint16_t source_port;
2372 uint16_t dest_port;
2373 uint16_t length;
2374 uint16_t checksum;
2375 } udp;
2376 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2377 struct {
2378 uint8_t type;
2379 uint8_t code;
2380 uint16_t checksum;
2381 uint32_t unused;
2382 } icmp4;
2383 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2384 struct {
2385 uint8_t type;
2386 uint8_t code;
2387 uint16_t checksum;
2388 uint32_t unused;
2389 } icmp6;
2390 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2391 };
2392 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2393
2394 #define SWRAP_PACKET_MIN_ALLOC \
2395 (SWRAP_PACKET_FRAME_SIZE + \
2396 SWRAP_PACKET_IP_SIZE + \
2397 SWRAP_PACKET_PAYLOAD_SIZE)
2398
swrap_pcap_init_file(void)2399 static const char *swrap_pcap_init_file(void)
2400 {
2401 static int initialized = 0;
2402 static const char *s = NULL;
2403 static const struct swrap_file_hdr h;
2404 static const struct swrap_packet_frame f;
2405 static const union swrap_packet_ip i;
2406 static const union swrap_packet_payload p;
2407
2408 if (initialized == 1) {
2409 return s;
2410 }
2411 initialized = 1;
2412
2413 /*
2414 * TODO: don't use the structs use plain buffer offsets
2415 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2416 *
2417 * for now make sure we disable PCAP support
2418 * if the struct has alignment!
2419 */
2420 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2421 return NULL;
2422 }
2423 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2424 return NULL;
2425 }
2426 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2427 return NULL;
2428 }
2429 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2430 return NULL;
2431 }
2432 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2433 return NULL;
2434 }
2435 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2436 return NULL;
2437 }
2438 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2439 return NULL;
2440 }
2441 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2442 return NULL;
2443 }
2444 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2445 return NULL;
2446 }
2447 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2448 return NULL;
2449 }
2450
2451 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2452 if (s == NULL) {
2453 return NULL;
2454 }
2455 if (strncmp(s, "./", 2) == 0) {
2456 s += 2;
2457 }
2458 return s;
2459 }
2460
swrap_pcap_packet_init(struct timeval * tval,const struct sockaddr * src,const struct sockaddr * dest,int socket_type,const uint8_t * payload,size_t payload_len,unsigned long tcp_seqno,unsigned long tcp_ack,unsigned char tcp_ctl,int unreachable,size_t * _packet_len)2461 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2462 const struct sockaddr *src,
2463 const struct sockaddr *dest,
2464 int socket_type,
2465 const uint8_t *payload,
2466 size_t payload_len,
2467 unsigned long tcp_seqno,
2468 unsigned long tcp_ack,
2469 unsigned char tcp_ctl,
2470 int unreachable,
2471 size_t *_packet_len)
2472 {
2473 uint8_t *base = NULL;
2474 uint8_t *buf = NULL;
2475 union {
2476 uint8_t *ptr;
2477 struct swrap_packet_frame *frame;
2478 } f;
2479 union {
2480 uint8_t *ptr;
2481 union swrap_packet_ip *ip;
2482 } i;
2483 union swrap_packet_payload *pay;
2484 size_t packet_len;
2485 size_t alloc_len;
2486 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2487 size_t wire_hdr_len = 0;
2488 size_t wire_len = 0;
2489 size_t ip_hdr_len = 0;
2490 size_t icmp_hdr_len = 0;
2491 size_t icmp_truncate_len = 0;
2492 uint8_t protocol = 0, icmp_protocol = 0;
2493 const struct sockaddr_in *src_in = NULL;
2494 const struct sockaddr_in *dest_in = NULL;
2495 #ifdef HAVE_IPV6
2496 const struct sockaddr_in6 *src_in6 = NULL;
2497 const struct sockaddr_in6 *dest_in6 = NULL;
2498 #endif
2499 uint16_t src_port;
2500 uint16_t dest_port;
2501
2502 switch (src->sa_family) {
2503 case AF_INET:
2504 src_in = (const struct sockaddr_in *)(const void *)src;
2505 dest_in = (const struct sockaddr_in *)(const void *)dest;
2506 src_port = src_in->sin_port;
2507 dest_port = dest_in->sin_port;
2508 ip_hdr_len = sizeof(i.ip->v4);
2509 break;
2510 #ifdef HAVE_IPV6
2511 case AF_INET6:
2512 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2513 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2514 src_port = src_in6->sin6_port;
2515 dest_port = dest_in6->sin6_port;
2516 ip_hdr_len = sizeof(i.ip->v6);
2517 break;
2518 #endif
2519 default:
2520 return NULL;
2521 }
2522
2523 switch (socket_type) {
2524 case SOCK_STREAM:
2525 protocol = 0x06; /* TCP */
2526 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2527 wire_len = wire_hdr_len + payload_len;
2528 break;
2529
2530 case SOCK_DGRAM:
2531 protocol = 0x11; /* UDP */
2532 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2533 wire_len = wire_hdr_len + payload_len;
2534 break;
2535
2536 default:
2537 return NULL;
2538 }
2539
2540 if (unreachable) {
2541 icmp_protocol = protocol;
2542 switch (src->sa_family) {
2543 case AF_INET:
2544 protocol = 0x01; /* ICMPv4 */
2545 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2546 break;
2547 #ifdef HAVE_IPV6
2548 case AF_INET6:
2549 protocol = 0x3A; /* ICMPv6 */
2550 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2551 break;
2552 #endif
2553 }
2554 if (wire_len > 64 ) {
2555 icmp_truncate_len = wire_len - 64;
2556 }
2557 wire_len += icmp_hdr_len;
2558 }
2559
2560 packet_len = nonwire_len + wire_len;
2561 alloc_len = packet_len;
2562 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2563 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2564 }
2565
2566 base = (uint8_t *)calloc(1, alloc_len);
2567 if (base == NULL) {
2568 return NULL;
2569 }
2570
2571 buf = base;
2572 f.ptr = buf;
2573
2574 f.frame->seconds = tval->tv_sec;
2575 f.frame->micro_seconds = tval->tv_usec;
2576 f.frame->recorded_length = wire_len - icmp_truncate_len;
2577 f.frame->full_length = wire_len - icmp_truncate_len;
2578
2579 buf += SWRAP_PACKET_FRAME_SIZE;
2580
2581 i.ptr = buf;
2582 switch (src->sa_family) {
2583 case AF_INET:
2584 if (src_in == NULL || dest_in == NULL) {
2585 SAFE_FREE(base);
2586 return NULL;
2587 }
2588
2589 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2590 i.ip->v4.tos = 0x00;
2591 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2592 i.ip->v4.identification = htons(0xFFFF);
2593 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2594 i.ip->v4.fragment = htons(0x0000);
2595 i.ip->v4.ttl = 0xFF;
2596 i.ip->v4.protocol = protocol;
2597 i.ip->v4.hdr_checksum = htons(0x0000);
2598 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2599 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2600 buf += SWRAP_PACKET_IP_V4_SIZE;
2601 break;
2602 #ifdef HAVE_IPV6
2603 case AF_INET6:
2604 if (src_in6 == NULL || dest_in6 == NULL) {
2605 SAFE_FREE(base);
2606 return NULL;
2607 }
2608
2609 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2610 i.ip->v6.flow_label_high = 0x00;
2611 i.ip->v6.flow_label_low = 0x0000;
2612 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2613 i.ip->v6.next_header = protocol;
2614 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2615 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2616 buf += SWRAP_PACKET_IP_V6_SIZE;
2617 break;
2618 #endif
2619 }
2620
2621 if (unreachable) {
2622 pay = (union swrap_packet_payload *)(void *)buf;
2623 switch (src->sa_family) {
2624 case AF_INET:
2625 pay->icmp4.type = 0x03; /* destination unreachable */
2626 pay->icmp4.code = 0x01; /* host unreachable */
2627 pay->icmp4.checksum = htons(0x0000);
2628 pay->icmp4.unused = htonl(0x00000000);
2629
2630 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2631
2632 /* set the ip header in the ICMP payload */
2633 i.ptr = buf;
2634 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2635 i.ip->v4.tos = 0x00;
2636 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2637 i.ip->v4.identification = htons(0xFFFF);
2638 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2639 i.ip->v4.fragment = htons(0x0000);
2640 i.ip->v4.ttl = 0xFF;
2641 i.ip->v4.protocol = icmp_protocol;
2642 i.ip->v4.hdr_checksum = htons(0x0000);
2643 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2644 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2645
2646 buf += SWRAP_PACKET_IP_V4_SIZE;
2647
2648 src_port = dest_in->sin_port;
2649 dest_port = src_in->sin_port;
2650 break;
2651 #ifdef HAVE_IPV6
2652 case AF_INET6:
2653 pay->icmp6.type = 0x01; /* destination unreachable */
2654 pay->icmp6.code = 0x03; /* address unreachable */
2655 pay->icmp6.checksum = htons(0x0000);
2656 pay->icmp6.unused = htonl(0x00000000);
2657 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2658
2659 /* set the ip header in the ICMP payload */
2660 i.ptr = buf;
2661 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2662 i.ip->v6.flow_label_high = 0x00;
2663 i.ip->v6.flow_label_low = 0x0000;
2664 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2665 i.ip->v6.next_header = protocol;
2666 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2667 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2668
2669 buf += SWRAP_PACKET_IP_V6_SIZE;
2670
2671 src_port = dest_in6->sin6_port;
2672 dest_port = src_in6->sin6_port;
2673 break;
2674 #endif
2675 }
2676 }
2677
2678 pay = (union swrap_packet_payload *)(void *)buf;
2679
2680 switch (socket_type) {
2681 case SOCK_STREAM:
2682 pay->tcp.source_port = src_port;
2683 pay->tcp.dest_port = dest_port;
2684 pay->tcp.seq_num = htonl(tcp_seqno);
2685 pay->tcp.ack_num = htonl(tcp_ack);
2686 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2687 pay->tcp.control = tcp_ctl;
2688 pay->tcp.window = htons(0x7FFF);
2689 pay->tcp.checksum = htons(0x0000);
2690 pay->tcp.urg = htons(0x0000);
2691 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2692
2693 break;
2694
2695 case SOCK_DGRAM:
2696 pay->udp.source_port = src_port;
2697 pay->udp.dest_port = dest_port;
2698 pay->udp.length = htons(8 + payload_len);
2699 pay->udp.checksum = htons(0x0000);
2700 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2701
2702 break;
2703 }
2704
2705 if (payload && payload_len > 0) {
2706 memcpy(buf, payload, payload_len);
2707 }
2708
2709 *_packet_len = packet_len - icmp_truncate_len;
2710 return base;
2711 }
2712
swrap_pcap_get_fd(const char * fname)2713 static int swrap_pcap_get_fd(const char *fname)
2714 {
2715 static int fd = -1;
2716
2717 if (fd != -1) {
2718 return fd;
2719 }
2720
2721 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2722 if (fd != -1) {
2723 struct swrap_file_hdr file_hdr;
2724 file_hdr.magic = 0xA1B2C3D4;
2725 file_hdr.version_major = 0x0002;
2726 file_hdr.version_minor = 0x0004;
2727 file_hdr.timezone = 0x00000000;
2728 file_hdr.sigfigs = 0x00000000;
2729 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2730 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2731
2732 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2733 close(fd);
2734 fd = -1;
2735 }
2736 return fd;
2737 }
2738
2739 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2740
2741 return fd;
2742 }
2743
swrap_pcap_marshall_packet(struct socket_info * si,const struct sockaddr * addr,enum swrap_packet_type type,const void * buf,size_t len,size_t * packet_len)2744 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2745 const struct sockaddr *addr,
2746 enum swrap_packet_type type,
2747 const void *buf, size_t len,
2748 size_t *packet_len)
2749 {
2750 const struct sockaddr *src_addr;
2751 const struct sockaddr *dest_addr;
2752 unsigned long tcp_seqno = 0;
2753 unsigned long tcp_ack = 0;
2754 unsigned char tcp_ctl = 0;
2755 int unreachable = 0;
2756
2757 struct timeval tv;
2758
2759 switch (si->family) {
2760 case AF_INET:
2761 break;
2762 #ifdef HAVE_IPV6
2763 case AF_INET6:
2764 break;
2765 #endif
2766 default:
2767 return NULL;
2768 }
2769
2770 switch (type) {
2771 case SWRAP_CONNECT_SEND:
2772 if (si->type != SOCK_STREAM) {
2773 return NULL;
2774 }
2775
2776 src_addr = &si->myname.sa.s;
2777 dest_addr = addr;
2778
2779 tcp_seqno = si->io.pck_snd;
2780 tcp_ack = si->io.pck_rcv;
2781 tcp_ctl = 0x02; /* SYN */
2782
2783 si->io.pck_snd += 1;
2784
2785 break;
2786
2787 case SWRAP_CONNECT_RECV:
2788 if (si->type != SOCK_STREAM) {
2789 return NULL;
2790 }
2791
2792 dest_addr = &si->myname.sa.s;
2793 src_addr = addr;
2794
2795 tcp_seqno = si->io.pck_rcv;
2796 tcp_ack = si->io.pck_snd;
2797 tcp_ctl = 0x12; /** SYN,ACK */
2798
2799 si->io.pck_rcv += 1;
2800
2801 break;
2802
2803 case SWRAP_CONNECT_UNREACH:
2804 if (si->type != SOCK_STREAM) {
2805 return NULL;
2806 }
2807
2808 dest_addr = &si->myname.sa.s;
2809 src_addr = addr;
2810
2811 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2812 tcp_seqno = si->io.pck_snd - 1;
2813 tcp_ack = si->io.pck_rcv;
2814 tcp_ctl = 0x02; /* SYN */
2815 unreachable = 1;
2816
2817 break;
2818
2819 case SWRAP_CONNECT_ACK:
2820 if (si->type != SOCK_STREAM) {
2821 return NULL;
2822 }
2823
2824 src_addr = &si->myname.sa.s;
2825 dest_addr = addr;
2826
2827 tcp_seqno = si->io.pck_snd;
2828 tcp_ack = si->io.pck_rcv;
2829 tcp_ctl = 0x10; /* ACK */
2830
2831 break;
2832
2833 case SWRAP_ACCEPT_SEND:
2834 if (si->type != SOCK_STREAM) {
2835 return NULL;
2836 }
2837
2838 dest_addr = &si->myname.sa.s;
2839 src_addr = addr;
2840
2841 tcp_seqno = si->io.pck_rcv;
2842 tcp_ack = si->io.pck_snd;
2843 tcp_ctl = 0x02; /* SYN */
2844
2845 si->io.pck_rcv += 1;
2846
2847 break;
2848
2849 case SWRAP_ACCEPT_RECV:
2850 if (si->type != SOCK_STREAM) {
2851 return NULL;
2852 }
2853
2854 src_addr = &si->myname.sa.s;
2855 dest_addr = addr;
2856
2857 tcp_seqno = si->io.pck_snd;
2858 tcp_ack = si->io.pck_rcv;
2859 tcp_ctl = 0x12; /* SYN,ACK */
2860
2861 si->io.pck_snd += 1;
2862
2863 break;
2864
2865 case SWRAP_ACCEPT_ACK:
2866 if (si->type != SOCK_STREAM) {
2867 return NULL;
2868 }
2869
2870 dest_addr = &si->myname.sa.s;
2871 src_addr = addr;
2872
2873 tcp_seqno = si->io.pck_rcv;
2874 tcp_ack = si->io.pck_snd;
2875 tcp_ctl = 0x10; /* ACK */
2876
2877 break;
2878
2879 case SWRAP_SEND:
2880 src_addr = &si->myname.sa.s;
2881 dest_addr = &si->peername.sa.s;
2882
2883 tcp_seqno = si->io.pck_snd;
2884 tcp_ack = si->io.pck_rcv;
2885 tcp_ctl = 0x18; /* PSH,ACK */
2886
2887 si->io.pck_snd += len;
2888
2889 break;
2890
2891 case SWRAP_SEND_RST:
2892 dest_addr = &si->myname.sa.s;
2893 src_addr = &si->peername.sa.s;
2894
2895 if (si->type == SOCK_DGRAM) {
2896 return swrap_pcap_marshall_packet(si,
2897 &si->peername.sa.s,
2898 SWRAP_SENDTO_UNREACH,
2899 buf,
2900 len,
2901 packet_len);
2902 }
2903
2904 tcp_seqno = si->io.pck_rcv;
2905 tcp_ack = si->io.pck_snd;
2906 tcp_ctl = 0x14; /** RST,ACK */
2907
2908 break;
2909
2910 case SWRAP_PENDING_RST:
2911 dest_addr = &si->myname.sa.s;
2912 src_addr = &si->peername.sa.s;
2913
2914 if (si->type == SOCK_DGRAM) {
2915 return NULL;
2916 }
2917
2918 tcp_seqno = si->io.pck_rcv;
2919 tcp_ack = si->io.pck_snd;
2920 tcp_ctl = 0x14; /* RST,ACK */
2921
2922 break;
2923
2924 case SWRAP_RECV:
2925 dest_addr = &si->myname.sa.s;
2926 src_addr = &si->peername.sa.s;
2927
2928 tcp_seqno = si->io.pck_rcv;
2929 tcp_ack = si->io.pck_snd;
2930 tcp_ctl = 0x18; /* PSH,ACK */
2931
2932 si->io.pck_rcv += len;
2933
2934 break;
2935
2936 case SWRAP_RECV_RST:
2937 dest_addr = &si->myname.sa.s;
2938 src_addr = &si->peername.sa.s;
2939
2940 if (si->type == SOCK_DGRAM) {
2941 return NULL;
2942 }
2943
2944 tcp_seqno = si->io.pck_rcv;
2945 tcp_ack = si->io.pck_snd;
2946 tcp_ctl = 0x14; /* RST,ACK */
2947
2948 break;
2949
2950 case SWRAP_SENDTO:
2951 src_addr = &si->myname.sa.s;
2952 dest_addr = addr;
2953
2954 si->io.pck_snd += len;
2955
2956 break;
2957
2958 case SWRAP_SENDTO_UNREACH:
2959 dest_addr = &si->myname.sa.s;
2960 src_addr = addr;
2961
2962 unreachable = 1;
2963
2964 break;
2965
2966 case SWRAP_RECVFROM:
2967 dest_addr = &si->myname.sa.s;
2968 src_addr = addr;
2969
2970 si->io.pck_rcv += len;
2971
2972 break;
2973
2974 case SWRAP_CLOSE_SEND:
2975 if (si->type != SOCK_STREAM) {
2976 return NULL;
2977 }
2978
2979 src_addr = &si->myname.sa.s;
2980 dest_addr = &si->peername.sa.s;
2981
2982 tcp_seqno = si->io.pck_snd;
2983 tcp_ack = si->io.pck_rcv;
2984 tcp_ctl = 0x11; /* FIN, ACK */
2985
2986 si->io.pck_snd += 1;
2987
2988 break;
2989
2990 case SWRAP_CLOSE_RECV:
2991 if (si->type != SOCK_STREAM) {
2992 return NULL;
2993 }
2994
2995 dest_addr = &si->myname.sa.s;
2996 src_addr = &si->peername.sa.s;
2997
2998 tcp_seqno = si->io.pck_rcv;
2999 tcp_ack = si->io.pck_snd;
3000 tcp_ctl = 0x11; /* FIN,ACK */
3001
3002 si->io.pck_rcv += 1;
3003
3004 break;
3005
3006 case SWRAP_CLOSE_ACK:
3007 if (si->type != SOCK_STREAM) {
3008 return NULL;
3009 }
3010
3011 src_addr = &si->myname.sa.s;
3012 dest_addr = &si->peername.sa.s;
3013
3014 tcp_seqno = si->io.pck_snd;
3015 tcp_ack = si->io.pck_rcv;
3016 tcp_ctl = 0x10; /* ACK */
3017
3018 break;
3019 default:
3020 return NULL;
3021 }
3022
3023 swrapGetTimeOfDay(&tv);
3024
3025 return swrap_pcap_packet_init(&tv,
3026 src_addr,
3027 dest_addr,
3028 si->type,
3029 (const uint8_t *)buf,
3030 len,
3031 tcp_seqno,
3032 tcp_ack,
3033 tcp_ctl,
3034 unreachable,
3035 packet_len);
3036 }
3037
swrap_pcap_dump_packet(struct socket_info * si,const struct sockaddr * addr,enum swrap_packet_type type,const void * buf,size_t len)3038 static void swrap_pcap_dump_packet(struct socket_info *si,
3039 const struct sockaddr *addr,
3040 enum swrap_packet_type type,
3041 const void *buf, size_t len)
3042 {
3043 const char *file_name;
3044 uint8_t *packet;
3045 size_t packet_len = 0;
3046 int fd;
3047
3048 swrap_mutex_lock(&pcap_dump_mutex);
3049
3050 file_name = swrap_pcap_init_file();
3051 if (!file_name) {
3052 goto done;
3053 }
3054
3055 packet = swrap_pcap_marshall_packet(si,
3056 addr,
3057 type,
3058 buf,
3059 len,
3060 &packet_len);
3061 if (packet == NULL) {
3062 goto done;
3063 }
3064
3065 fd = swrap_pcap_get_fd(file_name);
3066 if (fd != -1) {
3067 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3068 free(packet);
3069 goto done;
3070 }
3071 }
3072
3073 free(packet);
3074
3075 done:
3076 swrap_mutex_unlock(&pcap_dump_mutex);
3077 }
3078
3079 /****************************************************************************
3080 * SIGNALFD
3081 ***************************************************************************/
3082
3083 #ifdef HAVE_SIGNALFD
swrap_signalfd(int fd,const sigset_t * mask,int flags)3084 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3085 {
3086 int rc;
3087
3088 rc = libc_signalfd(fd, mask, flags);
3089 if (rc != -1) {
3090 swrap_remove_stale(fd);
3091 }
3092
3093 return rc;
3094 }
3095
signalfd(int fd,const sigset_t * mask,int flags)3096 int signalfd(int fd, const sigset_t *mask, int flags)
3097 {
3098 return swrap_signalfd(fd, mask, flags);
3099 }
3100 #endif
3101
3102 /****************************************************************************
3103 * SOCKET
3104 ***************************************************************************/
3105
swrap_socket(int family,int type,int protocol)3106 static int swrap_socket(int family, int type, int protocol)
3107 {
3108 struct socket_info *si = NULL;
3109 struct socket_info _si = { 0 };
3110 int fd;
3111 int ret;
3112 int real_type = type;
3113
3114 /*
3115 * Remove possible addition flags passed to socket() so
3116 * do not fail checking the type.
3117 * See https://lwn.net/Articles/281965/
3118 */
3119 #ifdef SOCK_CLOEXEC
3120 real_type &= ~SOCK_CLOEXEC;
3121 #endif
3122 #ifdef SOCK_NONBLOCK
3123 real_type &= ~SOCK_NONBLOCK;
3124 #endif
3125
3126 if (!socket_wrapper_enabled()) {
3127 return libc_socket(family, type, protocol);
3128 }
3129
3130 switch (family) {
3131 case AF_INET:
3132 #ifdef HAVE_IPV6
3133 case AF_INET6:
3134 #endif
3135 break;
3136 #ifdef AF_NETLINK
3137 case AF_NETLINK:
3138 #endif /* AF_NETLINK */
3139 #ifdef AF_PACKET
3140 case AF_PACKET:
3141 #endif /* AF_PACKET */
3142 case AF_UNIX:
3143 return libc_socket(family, type, protocol);
3144 default:
3145 errno = EAFNOSUPPORT;
3146 return -1;
3147 }
3148
3149 switch (real_type) {
3150 case SOCK_STREAM:
3151 break;
3152 case SOCK_DGRAM:
3153 break;
3154 default:
3155 errno = EPROTONOSUPPORT;
3156 return -1;
3157 }
3158
3159 switch (protocol) {
3160 case 0:
3161 break;
3162 case 6:
3163 if (real_type == SOCK_STREAM) {
3164 break;
3165 }
3166 FALL_THROUGH;
3167 case 17:
3168 if (real_type == SOCK_DGRAM) {
3169 break;
3170 }
3171 FALL_THROUGH;
3172 default:
3173 errno = EPROTONOSUPPORT;
3174 return -1;
3175 }
3176
3177 /*
3178 * We must call libc_socket with type, from the caller, not the version
3179 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3180 */
3181 fd = libc_socket(AF_UNIX, type, 0);
3182
3183 if (fd == -1) {
3184 return -1;
3185 }
3186
3187 /* Check if we have a stale fd and remove it */
3188 swrap_remove_stale(fd);
3189
3190 si = &_si;
3191 si->family = family;
3192
3193 /* however, the rest of the socket_wrapper code expects just
3194 * the type, not the flags */
3195 si->type = real_type;
3196 si->protocol = protocol;
3197
3198 /*
3199 * Setup myname so getsockname() can succeed to find out the socket
3200 * type.
3201 */
3202 switch(si->family) {
3203 case AF_INET: {
3204 struct sockaddr_in sin = {
3205 .sin_family = AF_INET,
3206 };
3207
3208 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3209 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3210 break;
3211 }
3212 #ifdef HAVE_IPV6
3213 case AF_INET6: {
3214 struct sockaddr_in6 sin6 = {
3215 .sin6_family = AF_INET6,
3216 };
3217
3218 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3219 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3220 break;
3221 }
3222 #endif
3223 default:
3224 errno = EINVAL;
3225 return -1;
3226 }
3227
3228 ret = swrap_create_socket(si, fd);
3229 if (ret == -1) {
3230 return -1;
3231 }
3232
3233 SWRAP_LOG(SWRAP_LOG_TRACE,
3234 "Created %s socket for protocol %s, fd=%d",
3235 family == AF_INET ? "IPv4" : "IPv6",
3236 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3237 fd);
3238
3239 return fd;
3240 }
3241
socket(int family,int type,int protocol)3242 int socket(int family, int type, int protocol)
3243 {
3244 return swrap_socket(family, type, protocol);
3245 }
3246
3247 /****************************************************************************
3248 * SOCKETPAIR
3249 ***************************************************************************/
3250
swrap_socketpair(int family,int type,int protocol,int sv[2])3251 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3252 {
3253 int rc;
3254
3255 rc = libc_socketpair(family, type, protocol, sv);
3256 if (rc != -1) {
3257 swrap_remove_stale(sv[0]);
3258 swrap_remove_stale(sv[1]);
3259 }
3260
3261 return rc;
3262 }
3263
socketpair(int family,int type,int protocol,int sv[2])3264 int socketpair(int family, int type, int protocol, int sv[2])
3265 {
3266 return swrap_socketpair(family, type, protocol, sv);
3267 }
3268
3269 /****************************************************************************
3270 * SOCKETPAIR
3271 ***************************************************************************/
3272
3273 #ifdef HAVE_TIMERFD_CREATE
swrap_timerfd_create(int clockid,int flags)3274 static int swrap_timerfd_create(int clockid, int flags)
3275 {
3276 int fd;
3277
3278 fd = libc_timerfd_create(clockid, flags);
3279 if (fd != -1) {
3280 swrap_remove_stale(fd);
3281 }
3282
3283 return fd;
3284 }
3285
timerfd_create(int clockid,int flags)3286 int timerfd_create(int clockid, int flags)
3287 {
3288 return swrap_timerfd_create(clockid, flags);
3289 }
3290 #endif
3291
3292 /****************************************************************************
3293 * PIPE
3294 ***************************************************************************/
3295
swrap_pipe(int pipefd[2])3296 static int swrap_pipe(int pipefd[2])
3297 {
3298 int rc;
3299
3300 rc = libc_pipe(pipefd);
3301 if (rc != -1) {
3302 swrap_remove_stale(pipefd[0]);
3303 swrap_remove_stale(pipefd[1]);
3304 }
3305
3306 return rc;
3307 }
3308
pipe(int pipefd[2])3309 int pipe(int pipefd[2])
3310 {
3311 return swrap_pipe(pipefd);
3312 }
3313
3314 /****************************************************************************
3315 * ACCEPT
3316 ***************************************************************************/
3317
swrap_accept(int s,struct sockaddr * addr,socklen_t * addrlen,int flags)3318 static int swrap_accept(int s,
3319 struct sockaddr *addr,
3320 socklen_t *addrlen,
3321 int flags)
3322 {
3323 struct socket_info *parent_si, *child_si;
3324 struct socket_info new_si = { 0 };
3325 int fd;
3326 int idx;
3327 struct swrap_address un_addr = {
3328 .sa_socklen = sizeof(struct sockaddr_un),
3329 };
3330 struct swrap_address un_my_addr = {
3331 .sa_socklen = sizeof(struct sockaddr_un),
3332 };
3333 struct swrap_address in_addr = {
3334 .sa_socklen = sizeof(struct sockaddr_storage),
3335 };
3336 struct swrap_address in_my_addr = {
3337 .sa_socklen = sizeof(struct sockaddr_storage),
3338 };
3339 int ret;
3340
3341 parent_si = find_socket_info(s);
3342 if (!parent_si) {
3343 #ifdef HAVE_ACCEPT4
3344 return libc_accept4(s, addr, addrlen, flags);
3345 #else
3346 UNUSED(flags);
3347 return libc_accept(s, addr, addrlen);
3348 #endif
3349 }
3350
3351
3352 /*
3353 * prevent parent_si from being altered / closed
3354 * while we read it
3355 */
3356 SWRAP_LOCK_SI(parent_si);
3357
3358 /*
3359 * assume out sockaddr have the same size as the in parent
3360 * socket family
3361 */
3362 in_addr.sa_socklen = socket_length(parent_si->family);
3363 if (in_addr.sa_socklen <= 0) {
3364 SWRAP_UNLOCK_SI(parent_si);
3365 errno = EINVAL;
3366 return -1;
3367 }
3368
3369 SWRAP_UNLOCK_SI(parent_si);
3370
3371 #ifdef HAVE_ACCEPT4
3372 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3373 #else
3374 UNUSED(flags);
3375 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3376 #endif
3377 if (ret == -1) {
3378 if (errno == ENOTSOCK) {
3379 /* Remove stale fds */
3380 swrap_remove_stale(s);
3381 }
3382 return ret;
3383 }
3384
3385 fd = ret;
3386
3387 SWRAP_LOCK_SI(parent_si);
3388
3389 ret = sockaddr_convert_from_un(parent_si,
3390 &un_addr.sa.un,
3391 un_addr.sa_socklen,
3392 parent_si->family,
3393 &in_addr.sa.s,
3394 &in_addr.sa_socklen);
3395 if (ret == -1) {
3396 SWRAP_UNLOCK_SI(parent_si);
3397 close(fd);
3398 return ret;
3399 }
3400
3401 child_si = &new_si;
3402
3403 child_si->family = parent_si->family;
3404 child_si->type = parent_si->type;
3405 child_si->protocol = parent_si->protocol;
3406 child_si->bound = 1;
3407 child_si->is_server = 1;
3408 child_si->connected = 1;
3409
3410 SWRAP_UNLOCK_SI(parent_si);
3411
3412 child_si->peername = (struct swrap_address) {
3413 .sa_socklen = in_addr.sa_socklen,
3414 };
3415 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3416
3417 if (addr != NULL && addrlen != NULL) {
3418 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3419 if (copy_len > 0) {
3420 memcpy(addr, &in_addr.sa.ss, copy_len);
3421 }
3422 *addrlen = in_addr.sa_socklen;
3423 }
3424
3425 ret = libc_getsockname(fd,
3426 &un_my_addr.sa.s,
3427 &un_my_addr.sa_socklen);
3428 if (ret == -1) {
3429 close(fd);
3430 return ret;
3431 }
3432
3433 ret = sockaddr_convert_from_un(child_si,
3434 &un_my_addr.sa.un,
3435 un_my_addr.sa_socklen,
3436 child_si->family,
3437 &in_my_addr.sa.s,
3438 &in_my_addr.sa_socklen);
3439 if (ret == -1) {
3440 close(fd);
3441 return ret;
3442 }
3443
3444 SWRAP_LOG(SWRAP_LOG_TRACE,
3445 "accept() path=%s, fd=%d",
3446 un_my_addr.sa.un.sun_path, s);
3447
3448 child_si->myname = (struct swrap_address) {
3449 .sa_socklen = in_my_addr.sa_socklen,
3450 };
3451 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3452
3453 idx = swrap_create_socket(&new_si, fd);
3454 if (idx == -1) {
3455 close (fd);
3456 return -1;
3457 }
3458
3459 if (addr != NULL) {
3460 struct socket_info *si = swrap_get_socket_info(idx);
3461
3462 SWRAP_LOCK_SI(si);
3463 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3464 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3465 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3466 SWRAP_UNLOCK_SI(si);
3467 }
3468
3469 return fd;
3470 }
3471
3472 #ifdef HAVE_ACCEPT4
accept4(int s,struct sockaddr * addr,socklen_t * addrlen,int flags)3473 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3474 {
3475 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3476 }
3477 #endif
3478
3479 #ifdef HAVE_ACCEPT_PSOCKLEN_T
accept(int s,struct sockaddr * addr,Psocklen_t addrlen)3480 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3481 #else
3482 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3483 #endif
3484 {
3485 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3486 }
3487
3488 static int autobind_start_init;
3489 static int autobind_start;
3490
3491 /* using sendto() or connect() on an unbound socket would give the
3492 recipient no way to reply, as unlike UDP and TCP, a unix domain
3493 socket can't auto-assign ephemeral port numbers, so we need to
3494 assign it here.
3495 Note: this might change the family from ipv6 to ipv4
3496 */
swrap_auto_bind(int fd,struct socket_info * si,int family)3497 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3498 {
3499 struct swrap_address un_addr = {
3500 .sa_socklen = sizeof(struct sockaddr_un),
3501 };
3502 int i;
3503 char type;
3504 int ret;
3505 int port;
3506 struct stat st;
3507 char *swrap_dir = NULL;
3508
3509 swrap_mutex_lock(&autobind_start_mutex);
3510
3511 if (autobind_start_init != 1) {
3512 autobind_start_init = 1;
3513 autobind_start = getpid();
3514 autobind_start %= 50000;
3515 autobind_start += 10000;
3516 }
3517
3518 un_addr.sa.un.sun_family = AF_UNIX;
3519
3520 switch (family) {
3521 case AF_INET: {
3522 struct sockaddr_in in;
3523
3524 switch (si->type) {
3525 case SOCK_STREAM:
3526 type = SOCKET_TYPE_CHAR_TCP;
3527 break;
3528 case SOCK_DGRAM:
3529 type = SOCKET_TYPE_CHAR_UDP;
3530 break;
3531 default:
3532 errno = ESOCKTNOSUPPORT;
3533 ret = -1;
3534 goto done;
3535 }
3536
3537 memset(&in, 0, sizeof(in));
3538 in.sin_family = AF_INET;
3539 in.sin_addr.s_addr = htonl(127<<24 |
3540 socket_wrapper_default_iface());
3541
3542 si->myname = (struct swrap_address) {
3543 .sa_socklen = sizeof(in),
3544 };
3545 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3546 break;
3547 }
3548 #ifdef HAVE_IPV6
3549 case AF_INET6: {
3550 struct sockaddr_in6 in6;
3551
3552 if (si->family != family) {
3553 errno = ENETUNREACH;
3554 ret = -1;
3555 goto done;
3556 }
3557
3558 switch (si->type) {
3559 case SOCK_STREAM:
3560 type = SOCKET_TYPE_CHAR_TCP_V6;
3561 break;
3562 case SOCK_DGRAM:
3563 type = SOCKET_TYPE_CHAR_UDP_V6;
3564 break;
3565 default:
3566 errno = ESOCKTNOSUPPORT;
3567 ret = -1;
3568 goto done;
3569 }
3570
3571 memset(&in6, 0, sizeof(in6));
3572 in6.sin6_family = AF_INET6;
3573 in6.sin6_addr = *swrap_ipv6();
3574 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3575
3576 si->myname = (struct swrap_address) {
3577 .sa_socklen = sizeof(in6),
3578 };
3579 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3580 break;
3581 }
3582 #endif
3583 default:
3584 errno = ESOCKTNOSUPPORT;
3585 ret = -1;
3586 goto done;
3587 }
3588
3589 if (autobind_start > 60000) {
3590 autobind_start = 10000;
3591 }
3592
3593 swrap_dir = socket_wrapper_dir();
3594 if (swrap_dir == NULL) {
3595 errno = EINVAL;
3596 ret = -1;
3597 goto done;
3598 }
3599
3600 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3601 port = autobind_start + i;
3602 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3603 "%s/"SOCKET_FORMAT, swrap_dir, type,
3604 socket_wrapper_default_iface(), port);
3605 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3606
3607 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3608 if (ret == -1) {
3609 goto done;
3610 }
3611
3612 si->un_addr = un_addr.sa.un;
3613
3614 si->bound = 1;
3615 autobind_start = port + 1;
3616 break;
3617 }
3618 if (i == SOCKET_MAX_SOCKETS) {
3619 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3620 "interface "SOCKET_FORMAT,
3621 SOCKET_MAX_SOCKETS,
3622 type,
3623 socket_wrapper_default_iface(),
3624 0);
3625 errno = ENFILE;
3626 ret = -1;
3627 goto done;
3628 }
3629
3630 si->family = family;
3631 set_port(si->family, port, &si->myname);
3632
3633 ret = 0;
3634
3635 done:
3636 SAFE_FREE(swrap_dir);
3637 swrap_mutex_unlock(&autobind_start_mutex);
3638 return ret;
3639 }
3640
3641 /****************************************************************************
3642 * CONNECT
3643 ***************************************************************************/
3644
swrap_connect(int s,const struct sockaddr * serv_addr,socklen_t addrlen)3645 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3646 socklen_t addrlen)
3647 {
3648 int ret;
3649 struct swrap_address un_addr = {
3650 .sa_socklen = sizeof(struct sockaddr_un),
3651 };
3652 struct socket_info *si = find_socket_info(s);
3653 int bcast = 0;
3654
3655 if (!si) {
3656 return libc_connect(s, serv_addr, addrlen);
3657 }
3658
3659 SWRAP_LOCK_SI(si);
3660
3661 if (si->bound == 0) {
3662 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3663 if (ret == -1) {
3664 goto done;
3665 }
3666 }
3667
3668 if (si->family != serv_addr->sa_family) {
3669 errno = EINVAL;
3670 ret = -1;
3671 goto done;
3672 }
3673
3674 ret = sockaddr_convert_to_un(si, serv_addr,
3675 addrlen, &un_addr.sa.un, 0, &bcast);
3676 if (ret == -1) {
3677 goto done;
3678 }
3679
3680 if (bcast) {
3681 errno = ENETUNREACH;
3682 ret = -1;
3683 goto done;
3684 }
3685
3686 if (si->type == SOCK_DGRAM) {
3687 si->defer_connect = 1;
3688 ret = 0;
3689 } else {
3690 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3691
3692 ret = libc_connect(s,
3693 &un_addr.sa.s,
3694 un_addr.sa_socklen);
3695 }
3696
3697 SWRAP_LOG(SWRAP_LOG_TRACE,
3698 "connect() path=%s, fd=%d",
3699 un_addr.sa.un.sun_path, s);
3700
3701
3702 /* to give better errors */
3703 if (ret == -1 && errno == ENOENT) {
3704 errno = EHOSTUNREACH;
3705 }
3706
3707 if (ret == 0) {
3708 si->peername = (struct swrap_address) {
3709 .sa_socklen = addrlen,
3710 };
3711
3712 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3713 si->connected = 1;
3714
3715 /*
3716 * When we connect() on a socket than we have to bind the
3717 * outgoing connection on the interface we use for the
3718 * transport. We already bound it on the right interface
3719 * but here we have to update the name so getsockname()
3720 * returns correct information.
3721 */
3722 if (si->bindname.sa_socklen > 0) {
3723 si->myname = (struct swrap_address) {
3724 .sa_socklen = si->bindname.sa_socklen,
3725 };
3726
3727 memcpy(&si->myname.sa.ss,
3728 &si->bindname.sa.ss,
3729 si->bindname.sa_socklen);
3730
3731 /* Cleanup bindname */
3732 si->bindname = (struct swrap_address) {
3733 .sa_socklen = 0,
3734 };
3735 }
3736
3737 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3738 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3739 } else {
3740 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3741 }
3742
3743 done:
3744 SWRAP_UNLOCK_SI(si);
3745 return ret;
3746 }
3747
connect(int s,const struct sockaddr * serv_addr,socklen_t addrlen)3748 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3749 {
3750 return swrap_connect(s, serv_addr, addrlen);
3751 }
3752
3753 /****************************************************************************
3754 * BIND
3755 ***************************************************************************/
3756
swrap_bind(int s,const struct sockaddr * myaddr,socklen_t addrlen)3757 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3758 {
3759 int ret;
3760 struct swrap_address un_addr = {
3761 .sa_socklen = sizeof(struct sockaddr_un),
3762 };
3763 struct socket_info *si = find_socket_info(s);
3764 int bind_error = 0;
3765 #if 0 /* FIXME */
3766 bool in_use;
3767 #endif
3768
3769 if (!si) {
3770 return libc_bind(s, myaddr, addrlen);
3771 }
3772
3773 SWRAP_LOCK_SI(si);
3774
3775 switch (si->family) {
3776 case AF_INET: {
3777 const struct sockaddr_in *sin;
3778 if (addrlen < sizeof(struct sockaddr_in)) {
3779 bind_error = EINVAL;
3780 break;
3781 }
3782
3783 sin = (const struct sockaddr_in *)(const void *)myaddr;
3784
3785 if (sin->sin_family != AF_INET) {
3786 bind_error = EAFNOSUPPORT;
3787 }
3788
3789 /* special case for AF_UNSPEC */
3790 if (sin->sin_family == AF_UNSPEC &&
3791 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3792 {
3793 bind_error = 0;
3794 }
3795
3796 break;
3797 }
3798 #ifdef HAVE_IPV6
3799 case AF_INET6: {
3800 const struct sockaddr_in6 *sin6;
3801 if (addrlen < sizeof(struct sockaddr_in6)) {
3802 bind_error = EINVAL;
3803 break;
3804 }
3805
3806 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3807
3808 if (sin6->sin6_family != AF_INET6) {
3809 bind_error = EAFNOSUPPORT;
3810 }
3811
3812 break;
3813 }
3814 #endif
3815 default:
3816 bind_error = EINVAL;
3817 break;
3818 }
3819
3820 if (bind_error != 0) {
3821 errno = bind_error;
3822 ret = -1;
3823 goto out;
3824 }
3825
3826 #if 0 /* FIXME */
3827 in_use = check_addr_port_in_use(myaddr, addrlen);
3828 if (in_use) {
3829 errno = EADDRINUSE;
3830 ret = -1;
3831 goto out;
3832 }
3833 #endif
3834
3835 si->myname.sa_socklen = addrlen;
3836 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3837
3838 ret = sockaddr_convert_to_un(si,
3839 myaddr,
3840 addrlen,
3841 &un_addr.sa.un,
3842 1,
3843 &si->bcast);
3844 if (ret == -1) {
3845 goto out;
3846 }
3847
3848 unlink(un_addr.sa.un.sun_path);
3849
3850 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3851
3852 SWRAP_LOG(SWRAP_LOG_TRACE,
3853 "bind() path=%s, fd=%d",
3854 un_addr.sa.un.sun_path, s);
3855
3856 if (ret == 0) {
3857 si->bound = 1;
3858 }
3859
3860 out:
3861 SWRAP_UNLOCK_SI(si);
3862
3863 return ret;
3864 }
3865
bind(int s,const struct sockaddr * myaddr,socklen_t addrlen)3866 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3867 {
3868 return swrap_bind(s, myaddr, addrlen);
3869 }
3870
3871 /****************************************************************************
3872 * BINDRESVPORT
3873 ***************************************************************************/
3874
3875 #ifdef HAVE_BINDRESVPORT
3876 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3877
swrap_bindresvport_sa(int sd,struct sockaddr * sa)3878 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3879 {
3880 struct swrap_address myaddr = {
3881 .sa_socklen = sizeof(struct sockaddr_storage),
3882 };
3883 socklen_t salen;
3884 static uint16_t port;
3885 uint16_t i;
3886 int rc = -1;
3887 int af;
3888
3889 #define SWRAP_STARTPORT 600
3890 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3891 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3892
3893 if (port == 0) {
3894 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3895 }
3896
3897 if (sa == NULL) {
3898 salen = myaddr.sa_socklen;
3899 sa = &myaddr.sa.s;
3900
3901 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3902 if (rc < 0) {
3903 return -1;
3904 }
3905
3906 af = sa->sa_family;
3907 memset(&myaddr.sa.ss, 0, salen);
3908 } else {
3909 af = sa->sa_family;
3910 }
3911
3912 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3913 switch(af) {
3914 case AF_INET: {
3915 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3916
3917 salen = sizeof(struct sockaddr_in);
3918 sinp->sin_port = htons(port);
3919 break;
3920 }
3921 case AF_INET6: {
3922 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3923
3924 salen = sizeof(struct sockaddr_in6);
3925 sin6p->sin6_port = htons(port);
3926 break;
3927 }
3928 default:
3929 errno = EAFNOSUPPORT;
3930 return -1;
3931 }
3932 sa->sa_family = af;
3933
3934 if (port > SWRAP_ENDPORT) {
3935 port = SWRAP_STARTPORT;
3936 }
3937
3938 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3939 if (rc == 0 || errno != EADDRINUSE) {
3940 break;
3941 }
3942 }
3943
3944 return rc;
3945 }
3946
bindresvport(int sockfd,struct sockaddr_in * sinp)3947 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3948 {
3949 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3950 }
3951 #endif
3952
3953 /****************************************************************************
3954 * LISTEN
3955 ***************************************************************************/
3956
swrap_listen(int s,int backlog)3957 static int swrap_listen(int s, int backlog)
3958 {
3959 int ret;
3960 struct socket_info *si = find_socket_info(s);
3961
3962 if (!si) {
3963 return libc_listen(s, backlog);
3964 }
3965
3966 SWRAP_LOCK_SI(si);
3967
3968 if (si->bound == 0) {
3969 ret = swrap_auto_bind(s, si, si->family);
3970 if (ret == -1) {
3971 errno = EADDRINUSE;
3972 goto out;
3973 }
3974 }
3975
3976 ret = libc_listen(s, backlog);
3977
3978 out:
3979 SWRAP_UNLOCK_SI(si);
3980
3981 return ret;
3982 }
3983
listen(int s,int backlog)3984 int listen(int s, int backlog)
3985 {
3986 return swrap_listen(s, backlog);
3987 }
3988
3989 /****************************************************************************
3990 * FOPEN
3991 ***************************************************************************/
3992
swrap_fopen(const char * name,const char * mode)3993 static FILE *swrap_fopen(const char *name, const char *mode)
3994 {
3995 FILE *fp;
3996
3997 fp = libc_fopen(name, mode);
3998 if (fp != NULL) {
3999 int fd = fileno(fp);
4000
4001 swrap_remove_stale(fd);
4002 }
4003
4004 return fp;
4005 }
4006
fopen(const char * name,const char * mode)4007 FILE *fopen(const char *name, const char *mode)
4008 {
4009 return swrap_fopen(name, mode);
4010 }
4011
4012 /****************************************************************************
4013 * FOPEN64
4014 ***************************************************************************/
4015
4016 #ifdef HAVE_FOPEN64
swrap_fopen64(const char * name,const char * mode)4017 static FILE *swrap_fopen64(const char *name, const char *mode)
4018 {
4019 FILE *fp;
4020
4021 fp = libc_fopen64(name, mode);
4022 if (fp != NULL) {
4023 int fd = fileno(fp);
4024
4025 swrap_remove_stale(fd);
4026 }
4027
4028 return fp;
4029 }
4030
fopen64(const char * name,const char * mode)4031 FILE *fopen64(const char *name, const char *mode)
4032 {
4033 return swrap_fopen64(name, mode);
4034 }
4035 #endif /* HAVE_FOPEN64 */
4036
4037 /****************************************************************************
4038 * OPEN
4039 ***************************************************************************/
4040
swrap_vopen(const char * pathname,int flags,va_list ap)4041 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4042 {
4043 int ret;
4044
4045 ret = libc_vopen(pathname, flags, ap);
4046 if (ret != -1) {
4047 /*
4048 * There are methods for closing descriptors (libc-internal code
4049 * paths, direct syscalls) which close descriptors in ways that
4050 * we can't intercept, so try to recover when we notice that
4051 * that's happened
4052 */
4053 swrap_remove_stale(ret);
4054 }
4055 return ret;
4056 }
4057
open(const char * pathname,int flags,...)4058 int open(const char *pathname, int flags, ...)
4059 {
4060 va_list ap;
4061 int fd;
4062
4063 va_start(ap, flags);
4064 fd = swrap_vopen(pathname, flags, ap);
4065 va_end(ap);
4066
4067 return fd;
4068 }
4069
4070 /****************************************************************************
4071 * OPEN64
4072 ***************************************************************************/
4073
4074 #ifdef HAVE_OPEN64
swrap_vopen64(const char * pathname,int flags,va_list ap)4075 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4076 {
4077 int ret;
4078
4079 ret = libc_vopen64(pathname, flags, ap);
4080 if (ret != -1) {
4081 /*
4082 * There are methods for closing descriptors (libc-internal code
4083 * paths, direct syscalls) which close descriptors in ways that
4084 * we can't intercept, so try to recover when we notice that
4085 * that's happened
4086 */
4087 swrap_remove_stale(ret);
4088 }
4089 return ret;
4090 }
4091
open64(const char * pathname,int flags,...)4092 int open64(const char *pathname, int flags, ...)
4093 {
4094 va_list ap;
4095 int fd;
4096
4097 va_start(ap, flags);
4098 fd = swrap_vopen64(pathname, flags, ap);
4099 va_end(ap);
4100
4101 return fd;
4102 }
4103 #endif /* HAVE_OPEN64 */
4104
4105 /****************************************************************************
4106 * OPENAT
4107 ***************************************************************************/
4108
swrap_vopenat(int dirfd,const char * path,int flags,va_list ap)4109 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4110 {
4111 int ret;
4112
4113 ret = libc_vopenat(dirfd, path, flags, ap);
4114 if (ret != -1) {
4115 /*
4116 * There are methods for closing descriptors (libc-internal code
4117 * paths, direct syscalls) which close descriptors in ways that
4118 * we can't intercept, so try to recover when we notice that
4119 * that's happened
4120 */
4121 swrap_remove_stale(ret);
4122 }
4123
4124 return ret;
4125 }
4126
openat(int dirfd,const char * path,int flags,...)4127 int openat(int dirfd, const char *path, int flags, ...)
4128 {
4129 va_list ap;
4130 int fd;
4131
4132 va_start(ap, flags);
4133 fd = swrap_vopenat(dirfd, path, flags, ap);
4134 va_end(ap);
4135
4136 return fd;
4137 }
4138
4139 /****************************************************************************
4140 * GETPEERNAME
4141 ***************************************************************************/
4142
swrap_getpeername(int s,struct sockaddr * name,socklen_t * addrlen)4143 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4144 {
4145 struct socket_info *si = find_socket_info(s);
4146 socklen_t len;
4147 int ret = -1;
4148
4149 if (!si) {
4150 return libc_getpeername(s, name, addrlen);
4151 }
4152
4153 SWRAP_LOCK_SI(si);
4154
4155 if (si->peername.sa_socklen == 0)
4156 {
4157 errno = ENOTCONN;
4158 goto out;
4159 }
4160
4161 len = MIN(*addrlen, si->peername.sa_socklen);
4162 if (len == 0) {
4163 ret = 0;
4164 goto out;
4165 }
4166
4167 memcpy(name, &si->peername.sa.ss, len);
4168 *addrlen = si->peername.sa_socklen;
4169
4170 ret = 0;
4171 out:
4172 SWRAP_UNLOCK_SI(si);
4173
4174 return ret;
4175 }
4176
4177 #ifdef HAVE_ACCEPT_PSOCKLEN_T
getpeername(int s,struct sockaddr * name,Psocklen_t addrlen)4178 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4179 #else
4180 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4181 #endif
4182 {
4183 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4184 }
4185
4186 /****************************************************************************
4187 * GETSOCKNAME
4188 ***************************************************************************/
4189
swrap_getsockname(int s,struct sockaddr * name,socklen_t * addrlen)4190 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4191 {
4192 struct socket_info *si = find_socket_info(s);
4193 socklen_t len;
4194 int ret = -1;
4195
4196 if (!si) {
4197 return libc_getsockname(s, name, addrlen);
4198 }
4199
4200 SWRAP_LOCK_SI(si);
4201
4202 len = MIN(*addrlen, si->myname.sa_socklen);
4203 if (len == 0) {
4204 ret = 0;
4205 goto out;
4206 }
4207
4208 memcpy(name, &si->myname.sa.ss, len);
4209 *addrlen = si->myname.sa_socklen;
4210
4211 ret = 0;
4212 out:
4213 SWRAP_UNLOCK_SI(si);
4214
4215 return ret;
4216 }
4217
4218 #ifdef HAVE_ACCEPT_PSOCKLEN_T
getsockname(int s,struct sockaddr * name,Psocklen_t addrlen)4219 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4220 #else
4221 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4222 #endif
4223 {
4224 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4225 }
4226
4227 /****************************************************************************
4228 * GETSOCKOPT
4229 ***************************************************************************/
4230
4231 #ifndef SO_PROTOCOL
4232 # ifdef SO_PROTOTYPE /* The Solaris name */
4233 # define SO_PROTOCOL SO_PROTOTYPE
4234 # endif /* SO_PROTOTYPE */
4235 #endif /* SO_PROTOCOL */
4236
swrap_getsockopt(int s,int level,int optname,void * optval,socklen_t * optlen)4237 static int swrap_getsockopt(int s, int level, int optname,
4238 void *optval, socklen_t *optlen)
4239 {
4240 struct socket_info *si = find_socket_info(s);
4241 int ret;
4242
4243 if (!si) {
4244 return libc_getsockopt(s,
4245 level,
4246 optname,
4247 optval,
4248 optlen);
4249 }
4250
4251 SWRAP_LOCK_SI(si);
4252
4253 if (level == SOL_SOCKET) {
4254 switch (optname) {
4255 #ifdef SO_DOMAIN
4256 case SO_DOMAIN:
4257 if (optval == NULL || optlen == NULL ||
4258 *optlen < (socklen_t)sizeof(int)) {
4259 errno = EINVAL;
4260 ret = -1;
4261 goto done;
4262 }
4263
4264 *optlen = sizeof(int);
4265 *(int *)optval = si->family;
4266 ret = 0;
4267 goto done;
4268 #endif /* SO_DOMAIN */
4269
4270 #ifdef SO_PROTOCOL
4271 case SO_PROTOCOL:
4272 if (optval == NULL || optlen == NULL ||
4273 *optlen < (socklen_t)sizeof(int)) {
4274 errno = EINVAL;
4275 ret = -1;
4276 goto done;
4277 }
4278
4279 *optlen = sizeof(int);
4280 *(int *)optval = si->protocol;
4281 ret = 0;
4282 goto done;
4283 #endif /* SO_PROTOCOL */
4284 case SO_TYPE:
4285 if (optval == NULL || optlen == NULL ||
4286 *optlen < (socklen_t)sizeof(int)) {
4287 errno = EINVAL;
4288 ret = -1;
4289 goto done;
4290 }
4291
4292 *optlen = sizeof(int);
4293 *(int *)optval = si->type;
4294 ret = 0;
4295 goto done;
4296 default:
4297 ret = libc_getsockopt(s,
4298 level,
4299 optname,
4300 optval,
4301 optlen);
4302 goto done;
4303 }
4304 } else if (level == IPPROTO_TCP) {
4305 switch (optname) {
4306 #ifdef TCP_NODELAY
4307 case TCP_NODELAY:
4308 /*
4309 * This enables sending packets directly out over TCP.
4310 * As a unix socket is doing that any way, report it as
4311 * enabled.
4312 */
4313 if (optval == NULL || optlen == NULL ||
4314 *optlen < (socklen_t)sizeof(int)) {
4315 errno = EINVAL;
4316 ret = -1;
4317 goto done;
4318 }
4319
4320 *optlen = sizeof(int);
4321 *(int *)optval = si->tcp_nodelay;
4322
4323 ret = 0;
4324 goto done;
4325 #endif /* TCP_NODELAY */
4326 default:
4327 break;
4328 }
4329 }
4330
4331 errno = ENOPROTOOPT;
4332 ret = -1;
4333
4334 done:
4335 SWRAP_UNLOCK_SI(si);
4336 return ret;
4337 }
4338
4339 #ifdef HAVE_ACCEPT_PSOCKLEN_T
getsockopt(int s,int level,int optname,void * optval,Psocklen_t optlen)4340 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4341 #else
4342 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4343 #endif
4344 {
4345 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4346 }
4347
4348 /****************************************************************************
4349 * SETSOCKOPT
4350 ***************************************************************************/
4351
swrap_setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)4352 static int swrap_setsockopt(int s, int level, int optname,
4353 const void *optval, socklen_t optlen)
4354 {
4355 struct socket_info *si = find_socket_info(s);
4356 int ret;
4357
4358 if (!si) {
4359 return libc_setsockopt(s,
4360 level,
4361 optname,
4362 optval,
4363 optlen);
4364 }
4365
4366 if (level == SOL_SOCKET) {
4367 return libc_setsockopt(s,
4368 level,
4369 optname,
4370 optval,
4371 optlen);
4372 }
4373
4374 SWRAP_LOCK_SI(si);
4375
4376 if (level == IPPROTO_TCP) {
4377 switch (optname) {
4378 #ifdef TCP_NODELAY
4379 case TCP_NODELAY: {
4380 int i;
4381
4382 /*
4383 * This enables sending packets directly out over TCP.
4384 * A unix socket is doing that any way.
4385 */
4386 if (optval == NULL || optlen == 0 ||
4387 optlen < (socklen_t)sizeof(int)) {
4388 errno = EINVAL;
4389 ret = -1;
4390 goto done;
4391 }
4392
4393 i = *discard_const_p(int, optval);
4394 if (i != 0 && i != 1) {
4395 errno = EINVAL;
4396 ret = -1;
4397 goto done;
4398 }
4399 si->tcp_nodelay = i;
4400
4401 ret = 0;
4402 goto done;
4403 }
4404 #endif /* TCP_NODELAY */
4405 default:
4406 break;
4407 }
4408 }
4409
4410 switch (si->family) {
4411 case AF_INET:
4412 if (level == IPPROTO_IP) {
4413 #ifdef IP_PKTINFO
4414 if (optname == IP_PKTINFO) {
4415 si->pktinfo = AF_INET;
4416 }
4417 #endif /* IP_PKTINFO */
4418 }
4419 ret = 0;
4420 goto done;
4421 #ifdef HAVE_IPV6
4422 case AF_INET6:
4423 if (level == IPPROTO_IPV6) {
4424 #ifdef IPV6_RECVPKTINFO
4425 if (optname == IPV6_RECVPKTINFO) {
4426 si->pktinfo = AF_INET6;
4427 }
4428 #endif /* IPV6_PKTINFO */
4429 }
4430 ret = 0;
4431 goto done;
4432 #endif
4433 default:
4434 errno = ENOPROTOOPT;
4435 ret = -1;
4436 goto done;
4437 }
4438
4439 done:
4440 SWRAP_UNLOCK_SI(si);
4441 return ret;
4442 }
4443
setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)4444 int setsockopt(int s, int level, int optname,
4445 const void *optval, socklen_t optlen)
4446 {
4447 return swrap_setsockopt(s, level, optname, optval, optlen);
4448 }
4449
4450 /****************************************************************************
4451 * IOCTL
4452 ***************************************************************************/
4453
swrap_vioctl(int s,unsigned long int r,va_list va)4454 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4455 {
4456 struct socket_info *si = find_socket_info(s);
4457 va_list ap;
4458 int value;
4459 int rc;
4460
4461 if (!si) {
4462 return libc_vioctl(s, r, va);
4463 }
4464
4465 SWRAP_LOCK_SI(si);
4466
4467 va_copy(ap, va);
4468
4469 rc = libc_vioctl(s, r, va);
4470
4471 switch (r) {
4472 case FIONREAD:
4473 value = *((int *)va_arg(ap, int *));
4474
4475 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4476 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4477 } else if (value == 0) { /* END OF FILE */
4478 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4479 }
4480 break;
4481 }
4482
4483 va_end(ap);
4484
4485 SWRAP_UNLOCK_SI(si);
4486 return rc;
4487 }
4488
4489 #ifdef HAVE_IOCTL_INT
ioctl(int s,int r,...)4490 int ioctl(int s, int r, ...)
4491 #else
4492 int ioctl(int s, unsigned long int r, ...)
4493 #endif
4494 {
4495 va_list va;
4496 int rc;
4497
4498 va_start(va, r);
4499
4500 rc = swrap_vioctl(s, (unsigned long int) r, va);
4501
4502 va_end(va);
4503
4504 return rc;
4505 }
4506
4507 /*****************
4508 * CMSG
4509 *****************/
4510
4511 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4512
4513 #ifndef CMSG_ALIGN
4514 # ifdef _ALIGN /* BSD */
4515 #define CMSG_ALIGN _ALIGN
4516 # else
4517 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4518 # endif /* _ALIGN */
4519 #endif /* CMSG_ALIGN */
4520
4521 /**
4522 * @brief Add a cmsghdr to a msghdr.
4523 *
4524 * This is an function to add any type of cmsghdr. It will operate on the
4525 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4526 * the buffer position after the added cmsg element. Hence, this function is
4527 * intended to be used with an intermediate msghdr and not on the original
4528 * one handed in by the client.
4529 *
4530 * @param[in] msg The msghdr to which to add the cmsg.
4531 *
4532 * @param[in] level The cmsg level to set.
4533 *
4534 * @param[in] type The cmsg type to set.
4535 *
4536 * @param[in] data The cmsg data to set.
4537 *
4538 * @param[in] len the length of the data to set.
4539 */
swrap_msghdr_add_cmsghdr(struct msghdr * msg,int level,int type,const void * data,size_t len)4540 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4541 int level,
4542 int type,
4543 const void *data,
4544 size_t len)
4545 {
4546 size_t cmlen = CMSG_LEN(len);
4547 size_t cmspace = CMSG_SPACE(len);
4548 uint8_t cmbuf[cmspace];
4549 void *cast_ptr = (void *)cmbuf;
4550 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4551 uint8_t *p;
4552
4553 memset(cmbuf, 0, cmspace);
4554
4555 if (msg->msg_controllen < cmlen) {
4556 cmlen = msg->msg_controllen;
4557 msg->msg_flags |= MSG_CTRUNC;
4558 }
4559
4560 if (msg->msg_controllen < cmspace) {
4561 cmspace = msg->msg_controllen;
4562 }
4563
4564 /*
4565 * We copy the full input data into an intermediate cmsghdr first
4566 * in order to more easily cope with truncation.
4567 */
4568 cm->cmsg_len = cmlen;
4569 cm->cmsg_level = level;
4570 cm->cmsg_type = type;
4571 memcpy(CMSG_DATA(cm), data, len);
4572
4573 /*
4574 * We now copy the possibly truncated buffer.
4575 * We copy cmlen bytes, but consume cmspace bytes,
4576 * leaving the possible padding uninitialiazed.
4577 */
4578 p = (uint8_t *)msg->msg_control;
4579 memcpy(p, cm, cmlen);
4580 p += cmspace;
4581 msg->msg_control = p;
4582 msg->msg_controllen -= cmspace;
4583
4584 return;
4585 }
4586
swrap_msghdr_add_pktinfo(struct socket_info * si,struct msghdr * msg)4587 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4588 struct msghdr *msg)
4589 {
4590 /* Add packet info */
4591 switch (si->pktinfo) {
4592 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4593 case AF_INET: {
4594 struct sockaddr_in *sin;
4595 #if defined(HAVE_STRUCT_IN_PKTINFO)
4596 struct in_pktinfo pkt;
4597 #elif defined(IP_RECVDSTADDR)
4598 struct in_addr pkt;
4599 #endif
4600
4601 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4602 sin = &si->bindname.sa.in;
4603 } else {
4604 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4605 return 0;
4606 }
4607 sin = &si->myname.sa.in;
4608 }
4609
4610 ZERO_STRUCT(pkt);
4611
4612 #if defined(HAVE_STRUCT_IN_PKTINFO)
4613 pkt.ipi_ifindex = socket_wrapper_default_iface();
4614 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4615 #elif defined(IP_RECVDSTADDR)
4616 pkt = sin->sin_addr;
4617 #endif
4618
4619 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4620 &pkt, sizeof(pkt));
4621
4622 break;
4623 }
4624 #endif /* IP_PKTINFO */
4625 #if defined(HAVE_IPV6)
4626 case AF_INET6: {
4627 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4628 struct sockaddr_in6 *sin6;
4629 struct in6_pktinfo pkt6;
4630
4631 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4632 sin6 = &si->bindname.sa.in6;
4633 } else {
4634 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4635 return 0;
4636 }
4637 sin6 = &si->myname.sa.in6;
4638 }
4639
4640 ZERO_STRUCT(pkt6);
4641
4642 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4643 pkt6.ipi6_addr = sin6->sin6_addr;
4644
4645 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4646 &pkt6, sizeof(pkt6));
4647 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4648
4649 break;
4650 }
4651 #endif /* IPV6_PKTINFO */
4652 default:
4653 return -1;
4654 }
4655
4656 return 0;
4657 }
4658
swrap_msghdr_add_socket_info(struct socket_info * si,struct msghdr * omsg)4659 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4660 struct msghdr *omsg)
4661 {
4662 int rc = 0;
4663
4664 if (si->pktinfo > 0) {
4665 rc = swrap_msghdr_add_pktinfo(si, omsg);
4666 }
4667
4668 return rc;
4669 }
4670
4671 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4672 uint8_t **cm_data,
4673 size_t *cm_data_space);
4674 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4675 uint8_t **cm_data,
4676 size_t *cm_data_space);
4677
swrap_sendmsg_filter_cmsghdr(struct msghdr * msg,uint8_t ** cm_data,size_t * cm_data_space)4678 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4679 uint8_t **cm_data,
4680 size_t *cm_data_space) {
4681 struct cmsghdr *cmsg;
4682 int rc = -1;
4683
4684 /* Nothing to do */
4685 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4686 return 0;
4687 }
4688
4689 for (cmsg = CMSG_FIRSTHDR(msg);
4690 cmsg != NULL;
4691 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4692 switch (cmsg->cmsg_level) {
4693 case IPPROTO_IP:
4694 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4695 cm_data,
4696 cm_data_space);
4697 break;
4698 default:
4699 rc = swrap_sendmsg_copy_cmsg(cmsg,
4700 cm_data,
4701 cm_data_space);
4702 break;
4703 }
4704 }
4705
4706 return rc;
4707 }
4708
swrap_sendmsg_copy_cmsg(struct cmsghdr * cmsg,uint8_t ** cm_data,size_t * cm_data_space)4709 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4710 uint8_t **cm_data,
4711 size_t *cm_data_space)
4712 {
4713 size_t cmspace;
4714 uint8_t *p;
4715
4716 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4717
4718 p = realloc((*cm_data), cmspace);
4719 if (p == NULL) {
4720 return -1;
4721 }
4722 (*cm_data) = p;
4723
4724 p = (*cm_data) + (*cm_data_space);
4725 *cm_data_space = cmspace;
4726
4727 memcpy(p, cmsg, cmsg->cmsg_len);
4728
4729 return 0;
4730 }
4731
4732 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4733 uint8_t **cm_data,
4734 size_t *cm_data_space);
4735
4736
swrap_sendmsg_filter_cmsg_socket(struct cmsghdr * cmsg,uint8_t ** cm_data,size_t * cm_data_space)4737 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4738 uint8_t **cm_data,
4739 size_t *cm_data_space)
4740 {
4741 int rc = -1;
4742
4743 switch(cmsg->cmsg_type) {
4744 #ifdef IP_PKTINFO
4745 case IP_PKTINFO:
4746 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4747 cm_data,
4748 cm_data_space);
4749 break;
4750 #endif
4751 #ifdef IPV6_PKTINFO
4752 case IPV6_PKTINFO:
4753 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4754 cm_data,
4755 cm_data_space);
4756 break;
4757 #endif
4758 default:
4759 break;
4760 }
4761
4762 return rc;
4763 }
4764
swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr * cmsg,uint8_t ** cm_data,size_t * cm_data_space)4765 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4766 uint8_t **cm_data,
4767 size_t *cm_data_space)
4768 {
4769 (void)cmsg; /* unused */
4770 (void)cm_data; /* unused */
4771 (void)cm_data_space; /* unused */
4772
4773 /*
4774 * Passing a IP pktinfo to a unix socket might be rejected by the
4775 * Kernel, at least on FreeBSD. So skip this cmsg.
4776 */
4777 return 0;
4778 }
4779 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4780
swrap_sendmsg_before(int fd,struct socket_info * si,struct msghdr * msg,struct iovec * tmp_iov,struct sockaddr_un * tmp_un,const struct sockaddr_un ** to_un,const struct sockaddr ** to,int * bcast)4781 static ssize_t swrap_sendmsg_before(int fd,
4782 struct socket_info *si,
4783 struct msghdr *msg,
4784 struct iovec *tmp_iov,
4785 struct sockaddr_un *tmp_un,
4786 const struct sockaddr_un **to_un,
4787 const struct sockaddr **to,
4788 int *bcast)
4789 {
4790 size_t i, len = 0;
4791 ssize_t ret = -1;
4792
4793 if (to_un) {
4794 *to_un = NULL;
4795 }
4796 if (to) {
4797 *to = NULL;
4798 }
4799 if (bcast) {
4800 *bcast = 0;
4801 }
4802
4803 SWRAP_LOCK_SI(si);
4804
4805 switch (si->type) {
4806 case SOCK_STREAM: {
4807 unsigned long mtu;
4808
4809 if (!si->connected) {
4810 errno = ENOTCONN;
4811 goto out;
4812 }
4813
4814 if (msg->msg_iovlen == 0) {
4815 break;
4816 }
4817
4818 mtu = socket_wrapper_mtu();
4819 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4820 size_t nlen;
4821 nlen = len + msg->msg_iov[i].iov_len;
4822 if (nlen < len) {
4823 /* overflow */
4824 errno = EMSGSIZE;
4825 goto out;
4826 }
4827 if (nlen > mtu) {
4828 break;
4829 }
4830 }
4831 msg->msg_iovlen = i;
4832 if (msg->msg_iovlen == 0) {
4833 *tmp_iov = msg->msg_iov[0];
4834 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4835 (size_t)mtu);
4836 msg->msg_iov = tmp_iov;
4837 msg->msg_iovlen = 1;
4838 }
4839 break;
4840 }
4841 case SOCK_DGRAM:
4842 if (si->connected) {
4843 if (msg->msg_name != NULL) {
4844 /*
4845 * We are dealing with unix sockets and if we
4846 * are connected, we should only talk to the
4847 * connected unix path. Using the fd to send
4848 * to another server would be hard to achieve.
4849 */
4850 msg->msg_name = NULL;
4851 msg->msg_namelen = 0;
4852 }
4853 } else {
4854 const struct sockaddr *msg_name;
4855 msg_name = (const struct sockaddr *)msg->msg_name;
4856
4857 if (msg_name == NULL) {
4858 errno = ENOTCONN;
4859 goto out;
4860 }
4861
4862
4863 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4864 tmp_un, 0, bcast);
4865 if (ret == -1) {
4866 goto out;
4867 }
4868
4869 if (to_un) {
4870 *to_un = tmp_un;
4871 }
4872 if (to) {
4873 *to = msg_name;
4874 }
4875 msg->msg_name = tmp_un;
4876 msg->msg_namelen = sizeof(*tmp_un);
4877 }
4878
4879 if (si->bound == 0) {
4880 ret = swrap_auto_bind(fd, si, si->family);
4881 if (ret == -1) {
4882 SWRAP_UNLOCK_SI(si);
4883 if (errno == ENOTSOCK) {
4884 swrap_remove_stale(fd);
4885 ret = -ENOTSOCK;
4886 } else {
4887 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4888 }
4889 return ret;
4890 }
4891 }
4892
4893 if (!si->defer_connect) {
4894 break;
4895 }
4896
4897 ret = sockaddr_convert_to_un(si,
4898 &si->peername.sa.s,
4899 si->peername.sa_socklen,
4900 tmp_un,
4901 0,
4902 NULL);
4903 if (ret == -1) {
4904 goto out;
4905 }
4906
4907 ret = libc_connect(fd,
4908 (struct sockaddr *)(void *)tmp_un,
4909 sizeof(*tmp_un));
4910
4911 /* to give better errors */
4912 if (ret == -1 && errno == ENOENT) {
4913 errno = EHOSTUNREACH;
4914 }
4915
4916 if (ret == -1) {
4917 goto out;
4918 }
4919
4920 si->defer_connect = 0;
4921 break;
4922 default:
4923 errno = EHOSTUNREACH;
4924 goto out;
4925 }
4926
4927 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4928 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4929 uint8_t *cmbuf = NULL;
4930 size_t cmlen = 0;
4931
4932 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4933 if (ret < 0) {
4934 free(cmbuf);
4935 goto out;
4936 }
4937
4938 if (cmlen == 0) {
4939 msg->msg_controllen = 0;
4940 msg->msg_control = NULL;
4941 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4942 memcpy(msg->msg_control, cmbuf, cmlen);
4943 msg->msg_controllen = cmlen;
4944 }
4945 free(cmbuf);
4946 }
4947 #endif
4948
4949 ret = 0;
4950 out:
4951 SWRAP_UNLOCK_SI(si);
4952
4953 return ret;
4954 }
4955
swrap_sendmsg_after(int fd,struct socket_info * si,struct msghdr * msg,const struct sockaddr * to,ssize_t ret)4956 static void swrap_sendmsg_after(int fd,
4957 struct socket_info *si,
4958 struct msghdr *msg,
4959 const struct sockaddr *to,
4960 ssize_t ret)
4961 {
4962 int saved_errno = errno;
4963 size_t i, len = 0;
4964 uint8_t *buf;
4965 off_t ofs = 0;
4966 size_t avail = 0;
4967 size_t remain;
4968
4969 /* to give better errors */
4970 if (ret == -1) {
4971 if (saved_errno == ENOENT) {
4972 saved_errno = EHOSTUNREACH;
4973 } else if (saved_errno == ENOTSOCK) {
4974 /* If the fd is not a socket, remove it */
4975 swrap_remove_stale(fd);
4976 }
4977 }
4978
4979 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4980 avail += msg->msg_iov[i].iov_len;
4981 }
4982
4983 if (ret == -1) {
4984 remain = MIN(80, avail);
4985 } else {
4986 remain = ret;
4987 }
4988
4989 /* we capture it as one single packet */
4990 buf = (uint8_t *)malloc(remain);
4991 if (!buf) {
4992 /* we just not capture the packet */
4993 errno = saved_errno;
4994 return;
4995 }
4996
4997 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4998 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4999 memcpy(buf + ofs,
5000 msg->msg_iov[i].iov_base,
5001 this_time);
5002 ofs += this_time;
5003 remain -= this_time;
5004 }
5005 len = ofs;
5006
5007 SWRAP_LOCK_SI(si);
5008
5009 switch (si->type) {
5010 case SOCK_STREAM:
5011 if (ret == -1) {
5012 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5013 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5014 } else {
5015 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5016 }
5017 break;
5018
5019 case SOCK_DGRAM:
5020 if (si->connected) {
5021 to = &si->peername.sa.s;
5022 }
5023 if (ret == -1) {
5024 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5025 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5026 } else {
5027 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5028 }
5029 break;
5030 }
5031
5032 SWRAP_UNLOCK_SI(si);
5033
5034 free(buf);
5035 errno = saved_errno;
5036 }
5037
swrap_recvmsg_before(int fd,struct socket_info * si,struct msghdr * msg,struct iovec * tmp_iov)5038 static int swrap_recvmsg_before(int fd,
5039 struct socket_info *si,
5040 struct msghdr *msg,
5041 struct iovec *tmp_iov)
5042 {
5043 size_t i, len = 0;
5044 int ret = -1;
5045
5046 SWRAP_LOCK_SI(si);
5047
5048 (void)fd; /* unused */
5049
5050 switch (si->type) {
5051 case SOCK_STREAM: {
5052 unsigned int mtu;
5053 if (!si->connected) {
5054 errno = ENOTCONN;
5055 goto out;
5056 }
5057
5058 if (msg->msg_iovlen == 0) {
5059 break;
5060 }
5061
5062 mtu = socket_wrapper_mtu();
5063 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5064 size_t nlen;
5065 nlen = len + msg->msg_iov[i].iov_len;
5066 if (nlen > mtu) {
5067 break;
5068 }
5069 }
5070 msg->msg_iovlen = i;
5071 if (msg->msg_iovlen == 0) {
5072 *tmp_iov = msg->msg_iov[0];
5073 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5074 (size_t)mtu);
5075 msg->msg_iov = tmp_iov;
5076 msg->msg_iovlen = 1;
5077 }
5078 break;
5079 }
5080 case SOCK_DGRAM:
5081 if (msg->msg_name == NULL) {
5082 errno = EINVAL;
5083 goto out;
5084 }
5085
5086 if (msg->msg_iovlen == 0) {
5087 break;
5088 }
5089
5090 if (si->bound == 0) {
5091 ret = swrap_auto_bind(fd, si, si->family);
5092 if (ret == -1) {
5093 SWRAP_UNLOCK_SI(si);
5094 /*
5095 * When attempting to read or write to a
5096 * descriptor, if an underlying autobind fails
5097 * because it's not a socket, stop intercepting
5098 * uses of that descriptor.
5099 */
5100 if (errno == ENOTSOCK) {
5101 swrap_remove_stale(fd);
5102 ret = -ENOTSOCK;
5103 } else {
5104 SWRAP_LOG(SWRAP_LOG_ERROR,
5105 "swrap_recvmsg_before failed");
5106 }
5107 return ret;
5108 }
5109 }
5110 break;
5111 default:
5112 errno = EHOSTUNREACH;
5113 goto out;
5114 }
5115
5116 ret = 0;
5117 out:
5118 SWRAP_UNLOCK_SI(si);
5119
5120 return ret;
5121 }
5122
swrap_recvmsg_after(int fd,struct socket_info * si,struct msghdr * msg,const struct sockaddr_un * un_addr,socklen_t un_addrlen,ssize_t ret)5123 static int swrap_recvmsg_after(int fd,
5124 struct socket_info *si,
5125 struct msghdr *msg,
5126 const struct sockaddr_un *un_addr,
5127 socklen_t un_addrlen,
5128 ssize_t ret)
5129 {
5130 int saved_errno = errno;
5131 size_t i;
5132 uint8_t *buf = NULL;
5133 off_t ofs = 0;
5134 size_t avail = 0;
5135 size_t remain;
5136 int rc;
5137
5138 /* to give better errors */
5139 if (ret == -1) {
5140 if (saved_errno == ENOENT) {
5141 saved_errno = EHOSTUNREACH;
5142 } else if (saved_errno == ENOTSOCK) {
5143 /* If the fd is not a socket, remove it */
5144 swrap_remove_stale(fd);
5145 }
5146 }
5147
5148 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5149 avail += msg->msg_iov[i].iov_len;
5150 }
5151
5152 SWRAP_LOCK_SI(si);
5153
5154 /* Convert the socket address before we leave */
5155 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5156 rc = sockaddr_convert_from_un(si,
5157 un_addr,
5158 un_addrlen,
5159 si->family,
5160 msg->msg_name,
5161 &msg->msg_namelen);
5162 if (rc == -1) {
5163 goto done;
5164 }
5165 }
5166
5167 if (avail == 0) {
5168 rc = 0;
5169 goto done;
5170 }
5171
5172 if (ret == -1) {
5173 remain = MIN(80, avail);
5174 } else {
5175 remain = ret;
5176 }
5177
5178 /* we capture it as one single packet */
5179 buf = (uint8_t *)malloc(remain);
5180 if (buf == NULL) {
5181 /* we just not capture the packet */
5182 SWRAP_UNLOCK_SI(si);
5183 errno = saved_errno;
5184 return -1;
5185 }
5186
5187 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5188 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5189 memcpy(buf + ofs,
5190 msg->msg_iov[i].iov_base,
5191 this_time);
5192 ofs += this_time;
5193 remain -= this_time;
5194 }
5195
5196 switch (si->type) {
5197 case SOCK_STREAM:
5198 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5199 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5200 } else if (ret == 0) { /* END OF FILE */
5201 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5202 } else if (ret > 0) {
5203 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5204 }
5205 break;
5206
5207 case SOCK_DGRAM:
5208 if (ret == -1) {
5209 break;
5210 }
5211
5212 if (un_addr != NULL) {
5213 swrap_pcap_dump_packet(si,
5214 msg->msg_name,
5215 SWRAP_RECVFROM,
5216 buf,
5217 ret);
5218 } else {
5219 swrap_pcap_dump_packet(si,
5220 msg->msg_name,
5221 SWRAP_RECV,
5222 buf,
5223 ret);
5224 }
5225
5226 break;
5227 }
5228
5229 rc = 0;
5230 done:
5231 free(buf);
5232 errno = saved_errno;
5233
5234 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5235 if (rc == 0 &&
5236 msg->msg_controllen > 0 &&
5237 msg->msg_control != NULL) {
5238 rc = swrap_msghdr_add_socket_info(si, msg);
5239 if (rc < 0) {
5240 SWRAP_UNLOCK_SI(si);
5241 return -1;
5242 }
5243 }
5244 #endif
5245
5246 SWRAP_UNLOCK_SI(si);
5247 return rc;
5248 }
5249
5250 /****************************************************************************
5251 * RECVFROM
5252 ***************************************************************************/
5253
swrap_recvfrom(int s,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)5254 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5255 struct sockaddr *from, socklen_t *fromlen)
5256 {
5257 struct swrap_address from_addr = {
5258 .sa_socklen = sizeof(struct sockaddr_un),
5259 };
5260 ssize_t ret;
5261 struct socket_info *si = find_socket_info(s);
5262 struct swrap_address saddr = {
5263 .sa_socklen = sizeof(struct sockaddr_storage),
5264 };
5265 struct msghdr msg;
5266 struct iovec tmp;
5267 int tret;
5268
5269 if (!si) {
5270 return libc_recvfrom(s,
5271 buf,
5272 len,
5273 flags,
5274 from,
5275 fromlen);
5276 }
5277
5278 tmp.iov_base = buf;
5279 tmp.iov_len = len;
5280
5281 ZERO_STRUCT(msg);
5282 if (from != NULL && fromlen != NULL) {
5283 msg.msg_name = from; /* optional address */
5284 msg.msg_namelen = *fromlen; /* size of address */
5285 } else {
5286 msg.msg_name = &saddr.sa.s; /* optional address */
5287 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5288 }
5289 msg.msg_iov = &tmp; /* scatter/gather array */
5290 msg.msg_iovlen = 1; /* # elements in msg_iov */
5291 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5292 msg.msg_control = NULL; /* ancillary data, see below */
5293 msg.msg_controllen = 0; /* ancillary data buffer len */
5294 msg.msg_flags = 0; /* flags on received message */
5295 #endif
5296
5297 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5298 if (tret < 0) {
5299 return -1;
5300 }
5301
5302 buf = msg.msg_iov[0].iov_base;
5303 len = msg.msg_iov[0].iov_len;
5304
5305 ret = libc_recvfrom(s,
5306 buf,
5307 len,
5308 flags,
5309 &from_addr.sa.s,
5310 &from_addr.sa_socklen);
5311 if (ret == -1) {
5312 return ret;
5313 }
5314
5315 tret = swrap_recvmsg_after(s,
5316 si,
5317 &msg,
5318 &from_addr.sa.un,
5319 from_addr.sa_socklen,
5320 ret);
5321 if (tret != 0) {
5322 return tret;
5323 }
5324
5325 if (from != NULL && fromlen != NULL) {
5326 *fromlen = msg.msg_namelen;
5327 }
5328
5329 return ret;
5330 }
5331
5332 #ifdef HAVE_ACCEPT_PSOCKLEN_T
recvfrom(int s,void * buf,size_t len,int flags,struct sockaddr * from,Psocklen_t fromlen)5333 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5334 struct sockaddr *from, Psocklen_t fromlen)
5335 #else
5336 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5337 struct sockaddr *from, socklen_t *fromlen)
5338 #endif
5339 {
5340 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5341 }
5342
5343 /****************************************************************************
5344 * SENDTO
5345 ***************************************************************************/
5346
swrap_sendto(int s,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)5347 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5348 const struct sockaddr *to, socklen_t tolen)
5349 {
5350 struct msghdr msg;
5351 struct iovec tmp;
5352 struct swrap_address un_addr = {
5353 .sa_socklen = sizeof(struct sockaddr_un),
5354 };
5355 const struct sockaddr_un *to_un = NULL;
5356 ssize_t ret;
5357 int rc;
5358 struct socket_info *si = find_socket_info(s);
5359 int bcast = 0;
5360
5361 if (!si) {
5362 return libc_sendto(s, buf, len, flags, to, tolen);
5363 }
5364
5365 tmp.iov_base = discard_const_p(char, buf);
5366 tmp.iov_len = len;
5367
5368 ZERO_STRUCT(msg);
5369 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5370 msg.msg_namelen = tolen; /* size of address */
5371 msg.msg_iov = &tmp; /* scatter/gather array */
5372 msg.msg_iovlen = 1; /* # elements in msg_iov */
5373 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5374 msg.msg_control = NULL; /* ancillary data, see below */
5375 msg.msg_controllen = 0; /* ancillary data buffer len */
5376 msg.msg_flags = 0; /* flags on received message */
5377 #endif
5378
5379 rc = swrap_sendmsg_before(s,
5380 si,
5381 &msg,
5382 &tmp,
5383 &un_addr.sa.un,
5384 &to_un,
5385 &to,
5386 &bcast);
5387 if (rc < 0) {
5388 return -1;
5389 }
5390
5391 buf = msg.msg_iov[0].iov_base;
5392 len = msg.msg_iov[0].iov_len;
5393
5394 if (bcast) {
5395 struct stat st;
5396 unsigned int iface;
5397 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5398 char type;
5399 char *swrap_dir = NULL;
5400
5401 type = SOCKET_TYPE_CHAR_UDP;
5402
5403 swrap_dir = socket_wrapper_dir();
5404 if (swrap_dir == NULL) {
5405 return -1;
5406 }
5407
5408 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5409 snprintf(un_addr.sa.un.sun_path,
5410 sizeof(un_addr.sa.un.sun_path),
5411 "%s/"SOCKET_FORMAT, swrap_dir, type, iface, prt);
5412 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5413
5414 /* ignore the any errors in broadcast sends */
5415 libc_sendto(s,
5416 buf,
5417 len,
5418 flags,
5419 &un_addr.sa.s,
5420 un_addr.sa_socklen);
5421 }
5422
5423 SAFE_FREE(swrap_dir);
5424
5425 SWRAP_LOCK_SI(si);
5426
5427 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5428
5429 SWRAP_UNLOCK_SI(si);
5430
5431 return len;
5432 }
5433
5434 SWRAP_LOCK_SI(si);
5435 /*
5436 * If it is a dgram socket and we are connected, don't include the
5437 * 'to' address.
5438 */
5439 if (si->type == SOCK_DGRAM && si->connected) {
5440 ret = libc_sendto(s,
5441 buf,
5442 len,
5443 flags,
5444 NULL,
5445 0);
5446 } else {
5447 ret = libc_sendto(s,
5448 buf,
5449 len,
5450 flags,
5451 (struct sockaddr *)msg.msg_name,
5452 msg.msg_namelen);
5453 }
5454
5455 SWRAP_UNLOCK_SI(si);
5456
5457 swrap_sendmsg_after(s, si, &msg, to, ret);
5458
5459 return ret;
5460 }
5461
sendto(int s,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)5462 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5463 const struct sockaddr *to, socklen_t tolen)
5464 {
5465 return swrap_sendto(s, buf, len, flags, to, tolen);
5466 }
5467
5468 /****************************************************************************
5469 * READV
5470 ***************************************************************************/
5471
swrap_recv(int s,void * buf,size_t len,int flags)5472 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5473 {
5474 struct socket_info *si;
5475 struct msghdr msg;
5476 struct swrap_address saddr = {
5477 .sa_socklen = sizeof(struct sockaddr_storage),
5478 };
5479 struct iovec tmp;
5480 ssize_t ret;
5481 int tret;
5482
5483 si = find_socket_info(s);
5484 if (si == NULL) {
5485 return libc_recv(s, buf, len, flags);
5486 }
5487
5488 tmp.iov_base = buf;
5489 tmp.iov_len = len;
5490
5491 ZERO_STRUCT(msg);
5492 msg.msg_name = &saddr.sa.s; /* optional address */
5493 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5494 msg.msg_iov = &tmp; /* scatter/gather array */
5495 msg.msg_iovlen = 1; /* # elements in msg_iov */
5496 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5497 msg.msg_control = NULL; /* ancillary data, see below */
5498 msg.msg_controllen = 0; /* ancillary data buffer len */
5499 msg.msg_flags = 0; /* flags on received message */
5500 #endif
5501
5502 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5503 if (tret < 0) {
5504 return -1;
5505 }
5506
5507 buf = msg.msg_iov[0].iov_base;
5508 len = msg.msg_iov[0].iov_len;
5509
5510 ret = libc_recv(s, buf, len, flags);
5511
5512 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5513 if (tret != 0) {
5514 return tret;
5515 }
5516
5517 return ret;
5518 }
5519
recv(int s,void * buf,size_t len,int flags)5520 ssize_t recv(int s, void *buf, size_t len, int flags)
5521 {
5522 return swrap_recv(s, buf, len, flags);
5523 }
5524
5525 /****************************************************************************
5526 * READ
5527 ***************************************************************************/
5528
swrap_read(int s,void * buf,size_t len)5529 static ssize_t swrap_read(int s, void *buf, size_t len)
5530 {
5531 struct socket_info *si;
5532 struct msghdr msg;
5533 struct iovec tmp;
5534 struct swrap_address saddr = {
5535 .sa_socklen = sizeof(struct sockaddr_storage),
5536 };
5537 ssize_t ret;
5538 int tret;
5539
5540 si = find_socket_info(s);
5541 if (si == NULL) {
5542 return libc_read(s, buf, len);
5543 }
5544
5545 tmp.iov_base = buf;
5546 tmp.iov_len = len;
5547
5548 ZERO_STRUCT(msg);
5549 msg.msg_name = &saddr.sa.ss; /* optional address */
5550 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5551 msg.msg_iov = &tmp; /* scatter/gather array */
5552 msg.msg_iovlen = 1; /* # elements in msg_iov */
5553 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5554 msg.msg_control = NULL; /* ancillary data, see below */
5555 msg.msg_controllen = 0; /* ancillary data buffer len */
5556 msg.msg_flags = 0; /* flags on received message */
5557 #endif
5558
5559 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5560 if (tret < 0) {
5561 if (tret == -ENOTSOCK) {
5562 return libc_read(s, buf, len);
5563 }
5564 return -1;
5565 }
5566
5567 buf = msg.msg_iov[0].iov_base;
5568 len = msg.msg_iov[0].iov_len;
5569
5570 ret = libc_read(s, buf, len);
5571
5572 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5573 if (tret != 0) {
5574 return tret;
5575 }
5576
5577 return ret;
5578 }
5579
read(int s,void * buf,size_t len)5580 ssize_t read(int s, void *buf, size_t len)
5581 {
5582 return swrap_read(s, buf, len);
5583 }
5584
5585 /****************************************************************************
5586 * WRITE
5587 ***************************************************************************/
5588
swrap_write(int s,const void * buf,size_t len)5589 static ssize_t swrap_write(int s, const void *buf, size_t len)
5590 {
5591 struct msghdr msg;
5592 struct iovec tmp;
5593 struct sockaddr_un un_addr;
5594 ssize_t ret;
5595 int rc;
5596 struct socket_info *si;
5597
5598 si = find_socket_info(s);
5599 if (si == NULL) {
5600 return libc_write(s, buf, len);
5601 }
5602
5603 tmp.iov_base = discard_const_p(char, buf);
5604 tmp.iov_len = len;
5605
5606 ZERO_STRUCT(msg);
5607 msg.msg_name = NULL; /* optional address */
5608 msg.msg_namelen = 0; /* size of address */
5609 msg.msg_iov = &tmp; /* scatter/gather array */
5610 msg.msg_iovlen = 1; /* # elements in msg_iov */
5611 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5612 msg.msg_control = NULL; /* ancillary data, see below */
5613 msg.msg_controllen = 0; /* ancillary data buffer len */
5614 msg.msg_flags = 0; /* flags on received message */
5615 #endif
5616
5617 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5618 if (rc < 0) {
5619 return -1;
5620 }
5621
5622 buf = msg.msg_iov[0].iov_base;
5623 len = msg.msg_iov[0].iov_len;
5624
5625 ret = libc_write(s, buf, len);
5626
5627 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5628
5629 return ret;
5630 }
5631
write(int s,const void * buf,size_t len)5632 ssize_t write(int s, const void *buf, size_t len)
5633 {
5634 return swrap_write(s, buf, len);
5635 }
5636
5637 /****************************************************************************
5638 * SEND
5639 ***************************************************************************/
5640
swrap_send(int s,const void * buf,size_t len,int flags)5641 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5642 {
5643 struct msghdr msg;
5644 struct iovec tmp;
5645 struct sockaddr_un un_addr;
5646 ssize_t ret;
5647 int rc;
5648 struct socket_info *si = find_socket_info(s);
5649
5650 if (!si) {
5651 return libc_send(s, buf, len, flags);
5652 }
5653
5654 tmp.iov_base = discard_const_p(char, buf);
5655 tmp.iov_len = len;
5656
5657 ZERO_STRUCT(msg);
5658 msg.msg_name = NULL; /* optional address */
5659 msg.msg_namelen = 0; /* size of address */
5660 msg.msg_iov = &tmp; /* scatter/gather array */
5661 msg.msg_iovlen = 1; /* # elements in msg_iov */
5662 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5663 msg.msg_control = NULL; /* ancillary data, see below */
5664 msg.msg_controllen = 0; /* ancillary data buffer len */
5665 msg.msg_flags = 0; /* flags on received message */
5666 #endif
5667
5668 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5669 if (rc < 0) {
5670 return -1;
5671 }
5672
5673 buf = msg.msg_iov[0].iov_base;
5674 len = msg.msg_iov[0].iov_len;
5675
5676 ret = libc_send(s, buf, len, flags);
5677
5678 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5679
5680 return ret;
5681 }
5682
send(int s,const void * buf,size_t len,int flags)5683 ssize_t send(int s, const void *buf, size_t len, int flags)
5684 {
5685 return swrap_send(s, buf, len, flags);
5686 }
5687
5688 /****************************************************************************
5689 * RECVMSG
5690 ***************************************************************************/
5691
swrap_recvmsg(int s,struct msghdr * omsg,int flags)5692 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5693 {
5694 struct swrap_address from_addr = {
5695 .sa_socklen = sizeof(struct sockaddr_un),
5696 };
5697 struct swrap_address convert_addr = {
5698 .sa_socklen = sizeof(struct sockaddr_storage),
5699 };
5700 struct socket_info *si;
5701 struct msghdr msg;
5702 struct iovec tmp;
5703 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5704 size_t msg_ctrllen_filled;
5705 size_t msg_ctrllen_left;
5706 #endif
5707
5708 ssize_t ret;
5709 int rc;
5710
5711 si = find_socket_info(s);
5712 if (si == NULL) {
5713 return libc_recvmsg(s, omsg, flags);
5714 }
5715
5716 tmp.iov_base = NULL;
5717 tmp.iov_len = 0;
5718
5719 ZERO_STRUCT(msg);
5720 msg.msg_name = &from_addr.sa; /* optional address */
5721 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5722 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5723 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5724 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5725 msg_ctrllen_filled = 0;
5726 msg_ctrllen_left = omsg->msg_controllen;
5727
5728 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5729 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5730 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5731 #endif
5732
5733 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5734 if (rc < 0) {
5735 return -1;
5736 }
5737
5738 ret = libc_recvmsg(s, &msg, flags);
5739
5740 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5741 msg_ctrllen_filled += msg.msg_controllen;
5742 msg_ctrllen_left -= msg.msg_controllen;
5743
5744 if (omsg->msg_control != NULL) {
5745 uint8_t *p;
5746
5747 p = omsg->msg_control;
5748 p += msg_ctrllen_filled;
5749
5750 msg.msg_control = p;
5751 msg.msg_controllen = msg_ctrllen_left;
5752 } else {
5753 msg.msg_control = NULL;
5754 msg.msg_controllen = 0;
5755 }
5756 #endif
5757
5758 /*
5759 * We convert the unix address to a IP address so we need a buffer
5760 * which can store the address in case of SOCK_DGRAM, see below.
5761 */
5762 msg.msg_name = &convert_addr.sa;
5763 msg.msg_namelen = convert_addr.sa_socklen;
5764
5765 rc = swrap_recvmsg_after(s,
5766 si,
5767 &msg,
5768 &from_addr.sa.un,
5769 from_addr.sa_socklen,
5770 ret);
5771 if (rc != 0) {
5772 return rc;
5773 }
5774
5775 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5776 if (omsg->msg_control != NULL) {
5777 /* msg.msg_controllen = space left */
5778 msg_ctrllen_left = msg.msg_controllen;
5779 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5780 }
5781
5782 /* Update the original message length */
5783 omsg->msg_controllen = msg_ctrllen_filled;
5784 omsg->msg_flags = msg.msg_flags;
5785 #endif
5786 omsg->msg_iovlen = msg.msg_iovlen;
5787
5788 SWRAP_LOCK_SI(si);
5789
5790 /*
5791 * From the manpage:
5792 *
5793 * The msg_name field points to a caller-allocated buffer that is
5794 * used to return the source address if the socket is unconnected. The
5795 * caller should set msg_namelen to the size of this buffer before this
5796 * call; upon return from a successful call, msg_name will contain the
5797 * length of the returned address. If the application does not need
5798 * to know the source address, msg_name can be specified as NULL.
5799 */
5800 if (si->type == SOCK_STREAM) {
5801 omsg->msg_namelen = 0;
5802 } else if (omsg->msg_name != NULL &&
5803 omsg->msg_namelen != 0 &&
5804 omsg->msg_namelen >= msg.msg_namelen) {
5805 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5806 omsg->msg_namelen = msg.msg_namelen;
5807 }
5808
5809 SWRAP_UNLOCK_SI(si);
5810
5811 return ret;
5812 }
5813
recvmsg(int sockfd,struct msghdr * msg,int flags)5814 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5815 {
5816 return swrap_recvmsg(sockfd, msg, flags);
5817 }
5818
5819 /****************************************************************************
5820 * SENDMSG
5821 ***************************************************************************/
5822
swrap_sendmsg(int s,const struct msghdr * omsg,int flags)5823 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5824 {
5825 struct msghdr msg;
5826 struct iovec tmp;
5827 struct sockaddr_un un_addr;
5828 const struct sockaddr_un *to_un = NULL;
5829 const struct sockaddr *to = NULL;
5830 ssize_t ret;
5831 int rc;
5832 struct socket_info *si = find_socket_info(s);
5833 int bcast = 0;
5834
5835 if (!si) {
5836 return libc_sendmsg(s, omsg, flags);
5837 }
5838
5839 ZERO_STRUCT(un_addr);
5840
5841 tmp.iov_base = NULL;
5842 tmp.iov_len = 0;
5843
5844 ZERO_STRUCT(msg);
5845
5846 SWRAP_LOCK_SI(si);
5847
5848 if (si->connected == 0) {
5849 msg.msg_name = omsg->msg_name; /* optional address */
5850 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5851 }
5852 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5853 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5854
5855 SWRAP_UNLOCK_SI(si);
5856
5857 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5858 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5859 /* omsg is a const so use a local buffer for modifications */
5860 uint8_t cmbuf[omsg->msg_controllen];
5861
5862 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5863
5864 msg.msg_control = cmbuf; /* ancillary data, see below */
5865 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5866 }
5867 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5868 #endif
5869
5870 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5871 if (rc < 0) {
5872 return -1;
5873 }
5874
5875 if (bcast) {
5876 struct stat st;
5877 unsigned int iface;
5878 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5879 char type;
5880 size_t i, len = 0;
5881 uint8_t *buf;
5882 off_t ofs = 0;
5883 size_t avail = 0;
5884 size_t remain;
5885 char *swrap_dir = NULL;
5886
5887 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5888 avail += msg.msg_iov[i].iov_len;
5889 }
5890
5891 len = avail;
5892 remain = avail;
5893
5894 /* we capture it as one single packet */
5895 buf = (uint8_t *)malloc(remain);
5896 if (!buf) {
5897 return -1;
5898 }
5899
5900 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5901 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5902 memcpy(buf + ofs,
5903 msg.msg_iov[i].iov_base,
5904 this_time);
5905 ofs += this_time;
5906 remain -= this_time;
5907 }
5908
5909 type = SOCKET_TYPE_CHAR_UDP;
5910
5911 swrap_dir = socket_wrapper_dir();
5912 if (swrap_dir == NULL) {
5913 free(buf);
5914 return -1;
5915 }
5916
5917 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5918 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5919 swrap_dir, type, iface, prt);
5920 if (stat(un_addr.sun_path, &st) != 0) continue;
5921
5922 msg.msg_name = &un_addr; /* optional address */
5923 msg.msg_namelen = sizeof(un_addr); /* size of address */
5924
5925 /* ignore the any errors in broadcast sends */
5926 libc_sendmsg(s, &msg, flags);
5927 }
5928
5929 SAFE_FREE(swrap_dir);
5930
5931 SWRAP_LOCK_SI(si);
5932
5933 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5934 free(buf);
5935
5936 SWRAP_UNLOCK_SI(si);
5937
5938 return len;
5939 }
5940
5941 ret = libc_sendmsg(s, &msg, flags);
5942
5943 swrap_sendmsg_after(s, si, &msg, to, ret);
5944
5945 return ret;
5946 }
5947
sendmsg(int s,const struct msghdr * omsg,int flags)5948 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5949 {
5950 return swrap_sendmsg(s, omsg, flags);
5951 }
5952
5953 /****************************************************************************
5954 * READV
5955 ***************************************************************************/
5956
swrap_readv(int s,const struct iovec * vector,int count)5957 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5958 {
5959 struct socket_info *si;
5960 struct msghdr msg;
5961 struct iovec tmp;
5962 struct swrap_address saddr = {
5963 .sa_socklen = sizeof(struct sockaddr_storage)
5964 };
5965 ssize_t ret;
5966 int rc;
5967
5968 si = find_socket_info(s);
5969 if (si == NULL) {
5970 return libc_readv(s, vector, count);
5971 }
5972
5973 tmp.iov_base = NULL;
5974 tmp.iov_len = 0;
5975
5976 ZERO_STRUCT(msg);
5977 msg.msg_name = &saddr.sa.s; /* optional address */
5978 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5979 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5980 msg.msg_iovlen = count; /* # elements in msg_iov */
5981 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5982 msg.msg_control = NULL; /* ancillary data, see below */
5983 msg.msg_controllen = 0; /* ancillary data buffer len */
5984 msg.msg_flags = 0; /* flags on received message */
5985 #endif
5986
5987 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5988 if (rc < 0) {
5989 if (rc == -ENOTSOCK) {
5990 return libc_readv(s, vector, count);
5991 }
5992 return -1;
5993 }
5994
5995 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5996
5997 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5998 if (rc != 0) {
5999 return rc;
6000 }
6001
6002 return ret;
6003 }
6004
readv(int s,const struct iovec * vector,int count)6005 ssize_t readv(int s, const struct iovec *vector, int count)
6006 {
6007 return swrap_readv(s, vector, count);
6008 }
6009
6010 /****************************************************************************
6011 * WRITEV
6012 ***************************************************************************/
6013
swrap_writev(int s,const struct iovec * vector,int count)6014 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6015 {
6016 struct msghdr msg;
6017 struct iovec tmp;
6018 struct sockaddr_un un_addr;
6019 ssize_t ret;
6020 int rc;
6021 struct socket_info *si = find_socket_info(s);
6022
6023 if (!si) {
6024 return libc_writev(s, vector, count);
6025 }
6026
6027 tmp.iov_base = NULL;
6028 tmp.iov_len = 0;
6029
6030 ZERO_STRUCT(msg);
6031 msg.msg_name = NULL; /* optional address */
6032 msg.msg_namelen = 0; /* size of address */
6033 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6034 msg.msg_iovlen = count; /* # elements in msg_iov */
6035 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6036 msg.msg_control = NULL; /* ancillary data, see below */
6037 msg.msg_controllen = 0; /* ancillary data buffer len */
6038 msg.msg_flags = 0; /* flags on received message */
6039 #endif
6040
6041 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6042 if (rc < 0) {
6043 if (rc == -ENOTSOCK) {
6044 return libc_readv(s, vector, count);
6045 }
6046 return -1;
6047 }
6048
6049 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6050
6051 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6052
6053 return ret;
6054 }
6055
writev(int s,const struct iovec * vector,int count)6056 ssize_t writev(int s, const struct iovec *vector, int count)
6057 {
6058 return swrap_writev(s, vector, count);
6059 }
6060
6061 /****************************
6062 * CLOSE
6063 ***************************/
6064
swrap_close(int fd)6065 static int swrap_close(int fd)
6066 {
6067 struct socket_info *si = NULL;
6068 int si_index;
6069 int ret;
6070
6071 swrap_mutex_lock(&socket_reset_mutex);
6072
6073 si_index = find_socket_info_index(fd);
6074 if (si_index == -1) {
6075 swrap_mutex_unlock(&socket_reset_mutex);
6076 return libc_close(fd);
6077 }
6078
6079 reset_socket_info_index(fd);
6080
6081 si = swrap_get_socket_info(si_index);
6082
6083 swrap_mutex_lock(&first_free_mutex);
6084 SWRAP_LOCK_SI(si);
6085
6086 ret = libc_close(fd);
6087
6088 swrap_dec_refcount(si);
6089
6090 if (swrap_get_refcount(si) > 0) {
6091 /* there are still references left */
6092 goto out;
6093 }
6094
6095 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6096 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6097 }
6098
6099 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6100 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6101 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6102 }
6103
6104 if (si->un_addr.sun_path[0] != '\0') {
6105 unlink(si->un_addr.sun_path);
6106 }
6107
6108 swrap_set_next_free(si, first_free);
6109 first_free = si_index;
6110
6111 out:
6112 SWRAP_UNLOCK_SI(si);
6113 swrap_mutex_unlock(&first_free_mutex);
6114 swrap_mutex_unlock(&socket_reset_mutex);
6115
6116 return ret;
6117 }
6118
close(int fd)6119 int close(int fd)
6120 {
6121 return swrap_close(fd);
6122 }
6123
6124 /****************************
6125 * DUP
6126 ***************************/
6127
swrap_dup(int fd)6128 static int swrap_dup(int fd)
6129 {
6130 struct socket_info *si;
6131 int dup_fd, idx;
6132
6133 idx = find_socket_info_index(fd);
6134 if (idx == -1) {
6135 return libc_dup(fd);
6136 }
6137
6138 si = swrap_get_socket_info(idx);
6139
6140 dup_fd = libc_dup(fd);
6141 if (dup_fd == -1) {
6142 int saved_errno = errno;
6143 errno = saved_errno;
6144 return -1;
6145 }
6146
6147 SWRAP_LOCK_SI(si);
6148
6149 swrap_inc_refcount(si);
6150
6151 SWRAP_UNLOCK_SI(si);
6152
6153 /* Make sure we don't have an entry for the fd */
6154 swrap_remove_stale(dup_fd);
6155
6156 set_socket_info_index(dup_fd, idx);
6157
6158 return dup_fd;
6159 }
6160
dup(int fd)6161 int dup(int fd)
6162 {
6163 return swrap_dup(fd);
6164 }
6165
6166 /****************************
6167 * DUP2
6168 ***************************/
6169
swrap_dup2(int fd,int newfd)6170 static int swrap_dup2(int fd, int newfd)
6171 {
6172 struct socket_info *si;
6173 int dup_fd, idx;
6174
6175 idx = find_socket_info_index(fd);
6176 if (idx == -1) {
6177 return libc_dup2(fd, newfd);
6178 }
6179
6180 si = swrap_get_socket_info(idx);
6181
6182 if (fd == newfd) {
6183 /*
6184 * According to the manpage:
6185 *
6186 * "If oldfd is a valid file descriptor, and newfd has the same
6187 * value as oldfd, then dup2() does nothing, and returns newfd."
6188 */
6189 return newfd;
6190 }
6191
6192 if (find_socket_info(newfd)) {
6193 /* dup2() does an implicit close of newfd, which we
6194 * need to emulate */
6195 swrap_close(newfd);
6196 }
6197
6198 dup_fd = libc_dup2(fd, newfd);
6199 if (dup_fd == -1) {
6200 int saved_errno = errno;
6201 errno = saved_errno;
6202 return -1;
6203 }
6204
6205 SWRAP_LOCK_SI(si);
6206
6207 swrap_inc_refcount(si);
6208
6209 SWRAP_UNLOCK_SI(si);
6210
6211 /* Make sure we don't have an entry for the fd */
6212 swrap_remove_stale(dup_fd);
6213
6214 set_socket_info_index(dup_fd, idx);
6215
6216 return dup_fd;
6217 }
6218
dup2(int fd,int newfd)6219 int dup2(int fd, int newfd)
6220 {
6221 return swrap_dup2(fd, newfd);
6222 }
6223
6224 /****************************
6225 * FCNTL
6226 ***************************/
6227
swrap_vfcntl(int fd,int cmd,va_list va)6228 static int swrap_vfcntl(int fd, int cmd, va_list va)
6229 {
6230 struct socket_info *si;
6231 int rc, dup_fd, idx;
6232
6233 idx = find_socket_info_index(fd);
6234 if (idx == -1) {
6235 return libc_vfcntl(fd, cmd, va);
6236 }
6237
6238 si = swrap_get_socket_info(idx);
6239
6240 switch (cmd) {
6241 case F_DUPFD:
6242 dup_fd = libc_vfcntl(fd, cmd, va);
6243 if (dup_fd == -1) {
6244 int saved_errno = errno;
6245 errno = saved_errno;
6246 return -1;
6247 }
6248
6249 SWRAP_LOCK_SI(si);
6250
6251 swrap_inc_refcount(si);
6252
6253 SWRAP_UNLOCK_SI(si);
6254
6255 /* Make sure we don't have an entry for the fd */
6256 swrap_remove_stale(dup_fd);
6257
6258 set_socket_info_index(dup_fd, idx);
6259
6260 rc = dup_fd;
6261 break;
6262 default:
6263 rc = libc_vfcntl(fd, cmd, va);
6264 break;
6265 }
6266
6267 return rc;
6268 }
6269
fcntl(int fd,int cmd,...)6270 int fcntl(int fd, int cmd, ...)
6271 {
6272 va_list va;
6273 int rc;
6274
6275 va_start(va, cmd);
6276
6277 rc = swrap_vfcntl(fd, cmd, va);
6278
6279 va_end(va);
6280
6281 return rc;
6282 }
6283
6284 /****************************
6285 * EVENTFD
6286 ***************************/
6287
6288 #ifdef HAVE_EVENTFD
swrap_eventfd(int count,int flags)6289 static int swrap_eventfd(int count, int flags)
6290 {
6291 int fd;
6292
6293 fd = libc_eventfd(count, flags);
6294 if (fd != -1) {
6295 swrap_remove_stale(fd);
6296 }
6297
6298 return fd;
6299 }
6300
6301 #ifdef HAVE_EVENTFD_UNSIGNED_INT
eventfd(unsigned int count,int flags)6302 int eventfd(unsigned int count, int flags)
6303 #else
6304 int eventfd(int count, int flags)
6305 #endif
6306 {
6307 return swrap_eventfd(count, flags);
6308 }
6309 #endif
6310
6311 #ifdef HAVE_PLEDGE
pledge(const char * promises,const char * paths[])6312 int pledge(const char *promises, const char *paths[])
6313 {
6314 (void)promises; /* unused */
6315 (void)paths; /* unused */
6316
6317 return 0;
6318 }
6319 #endif /* HAVE_PLEDGE */
6320
swrap_thread_prepare(void)6321 static void swrap_thread_prepare(void)
6322 {
6323 /*
6324 * This function should only be called here!!
6325 *
6326 * We bind all symobls to avoid deadlocks of the fork is
6327 * interrupted by a signal handler using a symbol of this
6328 * library.
6329 */
6330 swrap_bind_symbol_all();
6331
6332 SWRAP_LOCK_ALL;
6333 }
6334
swrap_thread_parent(void)6335 static void swrap_thread_parent(void)
6336 {
6337 SWRAP_UNLOCK_ALL;
6338 }
6339
swrap_thread_child(void)6340 static void swrap_thread_child(void)
6341 {
6342 SWRAP_UNLOCK_ALL;
6343 }
6344
6345 /****************************
6346 * CONSTRUCTOR
6347 ***************************/
swrap_constructor(void)6348 void swrap_constructor(void)
6349 {
6350 int ret;
6351
6352 /*
6353 * If we hold a lock and the application forks, then the child
6354 * is not able to unlock the mutex and we are in a deadlock.
6355 * This should prevent such deadlocks.
6356 */
6357 pthread_atfork(&swrap_thread_prepare,
6358 &swrap_thread_parent,
6359 &swrap_thread_child);
6360
6361 ret = socket_wrapper_init_mutex(&sockets_mutex);
6362 if (ret != 0) {
6363 SWRAP_LOG(SWRAP_LOG_ERROR,
6364 "Failed to initialize pthread mutex");
6365 exit(-1);
6366 }
6367
6368 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6369 if (ret != 0) {
6370 SWRAP_LOG(SWRAP_LOG_ERROR,
6371 "Failed to initialize pthread mutex");
6372 exit(-1);
6373 }
6374
6375 ret = socket_wrapper_init_mutex(&first_free_mutex);
6376 if (ret != 0) {
6377 SWRAP_LOG(SWRAP_LOG_ERROR,
6378 "Failed to initialize pthread mutex");
6379 exit(-1);
6380 }
6381 }
6382
6383 /****************************
6384 * DESTRUCTOR
6385 ***************************/
6386
6387 /*
6388 * This function is called when the library is unloaded and makes sure that
6389 * sockets get closed and the unix file for the socket are unlinked.
6390 */
swrap_destructor(void)6391 void swrap_destructor(void)
6392 {
6393 size_t i;
6394
6395 if (socket_fds_idx != NULL) {
6396 for (i = 0; i < socket_fds_max; ++i) {
6397 if (socket_fds_idx[i] != -1) {
6398 swrap_close(i);
6399 }
6400 }
6401 SAFE_FREE(socket_fds_idx);
6402 }
6403
6404 SAFE_FREE(sockets);
6405
6406 if (swrap.libc.handle != NULL) {
6407 dlclose(swrap.libc.handle);
6408 }
6409 if (swrap.libc.socket_handle) {
6410 dlclose(swrap.libc.socket_handle);
6411 }
6412 }
6413