Line data Source code
1 : /*
2 : * BSD 3-Clause License
3 : *
4 : * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 : * Copyright (c) 2006-2021, Stefan Metzmacher <metze@samba.org>
6 : * Copyright (c) 2013-2021, 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 : #ifdef HAVE_SYS_SYSCALL_H
51 : #include <sys/syscall.h>
52 : #endif
53 : #ifdef HAVE_SYSCALL_H
54 : #include <syscall.h>
55 : #endif
56 : #include <sys/socket.h>
57 : #include <sys/ioctl.h>
58 : #ifdef HAVE_SYS_FILIO_H
59 : #include <sys/filio.h>
60 : #endif
61 : #ifdef HAVE_SYS_SIGNALFD_H
62 : #include <sys/signalfd.h>
63 : #endif
64 : #ifdef HAVE_SYS_EVENTFD_H
65 : #include <sys/eventfd.h>
66 : #endif
67 : #ifdef HAVE_SYS_TIMERFD_H
68 : #include <sys/timerfd.h>
69 : #endif
70 : #include <sys/uio.h>
71 : #include <errno.h>
72 : #include <sys/un.h>
73 : #include <netinet/in.h>
74 : #include <netinet/tcp.h>
75 : #ifdef HAVE_NETINET_TCP_FSM_H
76 : #include <netinet/tcp_fsm.h>
77 : #endif
78 : #include <arpa/inet.h>
79 : #include <fcntl.h>
80 : #include <stdlib.h>
81 : #include <string.h>
82 : #include <stdio.h>
83 : #include <stdint.h>
84 : #include <stdarg.h>
85 : #include <stdbool.h>
86 : #include <unistd.h>
87 : #ifdef HAVE_GNU_LIB_NAMES_H
88 : #include <gnu/lib-names.h>
89 : #endif
90 : #ifdef HAVE_RPC_RPC_H
91 : #include <rpc/rpc.h>
92 : #endif
93 : #include <pthread.h>
94 :
95 : #include "socket_wrapper.h"
96 :
97 : enum swrap_dbglvl_e {
98 : SWRAP_LOG_ERROR = 0,
99 : SWRAP_LOG_WARN,
100 : SWRAP_LOG_DEBUG,
101 : SWRAP_LOG_TRACE
102 : };
103 :
104 : /* GCC have printf type attribute check. */
105 : #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
106 : #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
107 : #else
108 : #define PRINTF_ATTRIBUTE(a,b)
109 : #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
110 :
111 : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
112 : #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
113 : #else
114 : #define CONSTRUCTOR_ATTRIBUTE
115 : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
116 :
117 : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
118 : #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
119 : #else
120 : #define DESTRUCTOR_ATTRIBUTE
121 : #endif
122 :
123 : #ifndef FALL_THROUGH
124 : # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
125 : # define FALL_THROUGH __attribute__ ((fallthrough))
126 : # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
127 : # define FALL_THROUGH ((void)0)
128 : # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
129 : #endif /* FALL_THROUGH */
130 :
131 : #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
132 : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
133 : #else
134 : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
135 : #endif
136 :
137 : #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
138 : # define SWRAP_THREAD __thread
139 : #else
140 : # define SWRAP_THREAD
141 : #endif
142 :
143 : #ifndef MIN
144 : #define MIN(a,b) ((a)<(b)?(a):(b))
145 : #endif
146 :
147 : #ifndef ZERO_STRUCT
148 : #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
149 : #endif
150 :
151 : #ifndef ZERO_STRUCTP
152 : #define ZERO_STRUCTP(x) do { \
153 : if ((x) != NULL) \
154 : memset((char *)(x), 0, sizeof(*(x))); \
155 : } while(0)
156 : #endif
157 :
158 : #ifndef SAFE_FREE
159 : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
160 : #endif
161 :
162 : #ifndef discard_const
163 : #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
164 : #endif
165 :
166 : #ifndef discard_const_p
167 : #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
168 : #endif
169 :
170 : #define UNUSED(x) (void)(x)
171 :
172 : #ifdef IPV6_PKTINFO
173 : # ifndef IPV6_RECVPKTINFO
174 : # define IPV6_RECVPKTINFO IPV6_PKTINFO
175 : # endif /* IPV6_RECVPKTINFO */
176 : #endif /* IPV6_PKTINFO */
177 :
178 : /*
179 : * On BSD IP_PKTINFO has a different name because during
180 : * the time when they implemented it, there was no RFC.
181 : * The name for IPv6 is the same as on Linux.
182 : */
183 : #ifndef IP_PKTINFO
184 : # ifdef IP_RECVDSTADDR
185 : # define IP_PKTINFO IP_RECVDSTADDR
186 : # endif
187 : #endif
188 :
189 : #define socket_wrapper_init_mutex(m) \
190 : _socket_wrapper_init_mutex(m, #m)
191 :
192 : /* Add new global locks here please */
193 : # define SWRAP_REINIT_ALL do { \
194 : int ret; \
195 : ret = socket_wrapper_init_mutex(&sockets_mutex); \
196 : if (ret != 0) exit(-1); \
197 : ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
198 : if (ret != 0) exit(-1); \
199 : ret = socket_wrapper_init_mutex(&first_free_mutex); \
200 : if (ret != 0) exit(-1); \
201 : ret = socket_wrapper_init_mutex(&sockets_si_global); \
202 : if (ret != 0) exit(-1); \
203 : ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
204 : if (ret != 0) exit(-1); \
205 : ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
206 : if (ret != 0) exit(-1); \
207 : ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
208 : if (ret != 0) exit(-1); \
209 : } while(0)
210 :
211 : # define SWRAP_LOCK_ALL do { \
212 : swrap_mutex_lock(&sockets_mutex); \
213 : swrap_mutex_lock(&socket_reset_mutex); \
214 : swrap_mutex_lock(&first_free_mutex); \
215 : swrap_mutex_lock(&sockets_si_global); \
216 : swrap_mutex_lock(&autobind_start_mutex); \
217 : swrap_mutex_lock(&pcap_dump_mutex); \
218 : swrap_mutex_lock(&mtu_update_mutex); \
219 : } while(0)
220 :
221 : # define SWRAP_UNLOCK_ALL do { \
222 : swrap_mutex_unlock(&mtu_update_mutex); \
223 : swrap_mutex_unlock(&pcap_dump_mutex); \
224 : swrap_mutex_unlock(&autobind_start_mutex); \
225 : swrap_mutex_unlock(&sockets_si_global); \
226 : swrap_mutex_unlock(&first_free_mutex); \
227 : swrap_mutex_unlock(&socket_reset_mutex); \
228 : swrap_mutex_unlock(&sockets_mutex); \
229 : } while(0)
230 :
231 : #define SOCKET_INFO_CONTAINER(si) \
232 : (struct socket_info_container *)(si)
233 :
234 : #define SWRAP_LOCK_SI(si) do { \
235 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
236 : if (sic != NULL) { \
237 : swrap_mutex_lock(&sockets_si_global); \
238 : } else { \
239 : abort(); \
240 : } \
241 : } while(0)
242 :
243 : #define SWRAP_UNLOCK_SI(si) do { \
244 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
245 : if (sic != NULL) { \
246 : swrap_mutex_unlock(&sockets_si_global); \
247 : } else { \
248 : abort(); \
249 : } \
250 : } while(0)
251 :
252 : #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
253 : #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
254 : #else
255 : #define swrapGetTimeOfDay(tval) gettimeofday(tval)
256 : #endif
257 :
258 : /* we need to use a very terse format here as IRIX 6.4 silently
259 : truncates names to 16 chars, so if we use a longer name then we
260 : can't tell which port a packet came from with recvfrom()
261 :
262 : with this format we have 8 chars left for the directory name
263 : */
264 : #define SOCKET_FORMAT "%c%02X%04X"
265 : #define SOCKET_TYPE_CHAR_TCP 'T'
266 : #define SOCKET_TYPE_CHAR_UDP 'U'
267 : #define SOCKET_TYPE_CHAR_TCP_V6 'X'
268 : #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
269 :
270 : /*
271 : * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
272 : * format PCAP capture files (as the caller will simply continue from here).
273 : */
274 : #define SOCKET_WRAPPER_MTU_DEFAULT 1500
275 : #define SOCKET_WRAPPER_MTU_MIN 512
276 : #define SOCKET_WRAPPER_MTU_MAX 32768
277 :
278 : #define SOCKET_MAX_SOCKETS 1024
279 :
280 : /*
281 : * Maximum number of socket_info structures that can
282 : * be used. Can be overriden by the environment variable
283 : * SOCKET_WRAPPER_MAX_SOCKETS.
284 : */
285 : #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
286 :
287 : #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
288 :
289 : /* This limit is to avoid broadcast sendto() needing to stat too many
290 : * files. It may be raised (with a performance cost) to up to 254
291 : * without changing the format above */
292 : #define MAX_WRAPPED_INTERFACES 64
293 :
294 : struct swrap_address {
295 : socklen_t sa_socklen;
296 : union {
297 : struct sockaddr s;
298 : struct sockaddr_in in;
299 : #ifdef HAVE_IPV6
300 : struct sockaddr_in6 in6;
301 : #endif
302 : struct sockaddr_un un;
303 : struct sockaddr_storage ss;
304 : } sa;
305 : };
306 :
307 : static int first_free;
308 :
309 : struct socket_info
310 : {
311 : /*
312 : * Remember to update swrap_unix_scm_right_magic
313 : * on any change.
314 : */
315 :
316 : int family;
317 : int type;
318 : int protocol;
319 : int bound;
320 : int bcast;
321 : int is_server;
322 : int connected;
323 : int defer_connect;
324 : int pktinfo;
325 : int tcp_nodelay;
326 : int listening;
327 : int fd_passed;
328 :
329 : /* The unix path so we can unlink it on close() */
330 : struct sockaddr_un un_addr;
331 :
332 : struct swrap_address bindname;
333 : struct swrap_address myname;
334 : struct swrap_address peername;
335 :
336 : struct {
337 : unsigned long pck_snd;
338 : unsigned long pck_rcv;
339 : } io;
340 : };
341 :
342 : struct socket_info_meta
343 : {
344 : unsigned int refcount;
345 : int next_free;
346 : /*
347 : * As long as we don't use shared memory
348 : * for the sockets array, we use
349 : * sockets_si_global as a single mutex.
350 : *
351 : * pthread_mutex_t mutex;
352 : */
353 : };
354 :
355 : struct socket_info_container
356 : {
357 : struct socket_info info;
358 : struct socket_info_meta meta;
359 : };
360 :
361 : static struct socket_info_container *sockets;
362 :
363 : static size_t socket_info_max = 0;
364 :
365 : /*
366 : * Allocate the socket array always on the limit value. We want it to be
367 : * at least bigger than the default so if we reach the limit we can
368 : * still deal with duplicate fds pointing to the same socket_info.
369 : */
370 : static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
371 :
372 : /* Hash table to map fds to corresponding socket_info index */
373 : static int *socket_fds_idx;
374 :
375 : /* Mutex for syncronizing port selection during swrap_auto_bind() */
376 : static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
377 :
378 : /* Mutex to guard the initialization of array of socket_info structures */
379 : static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
380 :
381 : /* Mutex to guard the socket reset in swrap_remove_wrapper() */
382 : static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
383 :
384 : /* Mutex to synchronize access to first free index in socket_info array */
385 : static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
386 :
387 : /*
388 : * Mutex to synchronize access to to socket_info structures
389 : * We use a single global mutex in order to avoid leaking
390 : * ~ 38M copy on write memory per fork.
391 : * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
392 : */
393 : static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
394 :
395 : /* Mutex to synchronize access to packet capture dump file */
396 : static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
397 :
398 : /* Mutex for synchronizing mtu value fetch*/
399 : static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
400 :
401 : /* Function prototypes */
402 :
403 : #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
404 : /* xlC and other oldschool compilers support (only) this */
405 : #pragma init (swrap_constructor)
406 : #endif
407 : void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
408 : #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
409 : #pragma fini (swrap_destructor)
410 : #endif
411 : void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
412 :
413 : #ifndef HAVE_GETPROGNAME
414 62339128 : static const char *getprogname(void)
415 : {
416 : #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
417 62339128 : return program_invocation_short_name;
418 : #elif defined(HAVE_GETEXECNAME)
419 : return getexecname();
420 : #else
421 : return NULL;
422 : #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
423 : }
424 : #endif /* HAVE_GETPROGNAME */
425 :
426 : static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
427 : # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
428 :
429 62339128 : static void swrap_log(enum swrap_dbglvl_e dbglvl,
430 : const char *func,
431 : const char *format, ...)
432 : {
433 : char buffer[1024];
434 : va_list va;
435 : const char *d;
436 62339128 : unsigned int lvl = 0;
437 62339128 : const char *prefix = "SWRAP";
438 62339128 : const char *progname = getprogname();
439 :
440 62339128 : d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
441 62339128 : if (d != NULL) {
442 0 : lvl = atoi(d);
443 : }
444 :
445 62339128 : if (lvl < dbglvl) {
446 62339128 : return;
447 : }
448 :
449 0 : va_start(va, format);
450 0 : vsnprintf(buffer, sizeof(buffer), format, va);
451 0 : va_end(va);
452 :
453 0 : switch (dbglvl) {
454 0 : case SWRAP_LOG_ERROR:
455 0 : prefix = "SWRAP_ERROR";
456 0 : break;
457 0 : case SWRAP_LOG_WARN:
458 0 : prefix = "SWRAP_WARN";
459 0 : break;
460 0 : case SWRAP_LOG_DEBUG:
461 0 : prefix = "SWRAP_DEBUG";
462 0 : break;
463 0 : case SWRAP_LOG_TRACE:
464 0 : prefix = "SWRAP_TRACE";
465 0 : break;
466 : }
467 :
468 0 : if (progname == NULL) {
469 0 : progname = "<unknown>";
470 : }
471 :
472 0 : fprintf(stderr,
473 : "%s[%s (%u)] - %s: %s\n",
474 : prefix,
475 : progname,
476 0 : (unsigned int)getpid(),
477 : func,
478 : buffer);
479 : }
480 :
481 : /*********************************************************
482 : * SWRAP LOADING LIBC FUNCTIONS
483 : *********************************************************/
484 :
485 : #include <dlfcn.h>
486 :
487 : #ifdef HAVE_ACCEPT4
488 : typedef int (*__libc_accept4)(int sockfd,
489 : struct sockaddr *addr,
490 : socklen_t *addrlen,
491 : int flags);
492 : #else
493 : typedef int (*__libc_accept)(int sockfd,
494 : struct sockaddr *addr,
495 : socklen_t *addrlen);
496 : #endif
497 : typedef int (*__libc_bind)(int sockfd,
498 : const struct sockaddr *addr,
499 : socklen_t addrlen);
500 : typedef int (*__libc_close)(int fd);
501 : #ifdef HAVE___CLOSE_NOCANCEL
502 : typedef int (*__libc___close_nocancel)(int fd);
503 : #endif
504 : typedef int (*__libc_connect)(int sockfd,
505 : const struct sockaddr *addr,
506 : socklen_t addrlen);
507 : typedef int (*__libc_dup)(int fd);
508 : typedef int (*__libc_dup2)(int oldfd, int newfd);
509 : typedef int (*__libc_fcntl)(int fd, int cmd, ...);
510 : typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
511 : #ifdef HAVE_FOPEN64
512 : typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
513 : #endif
514 : #ifdef HAVE_EVENTFD
515 : typedef int (*__libc_eventfd)(int count, int flags);
516 : #endif
517 : typedef int (*__libc_getpeername)(int sockfd,
518 : struct sockaddr *addr,
519 : socklen_t *addrlen);
520 : typedef int (*__libc_getsockname)(int sockfd,
521 : struct sockaddr *addr,
522 : socklen_t *addrlen);
523 : typedef int (*__libc_getsockopt)(int sockfd,
524 : int level,
525 : int optname,
526 : void *optval,
527 : socklen_t *optlen);
528 : typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
529 : typedef int (*__libc_listen)(int sockfd, int backlog);
530 : typedef int (*__libc_open)(const char *pathname, int flags, ...);
531 : #ifdef HAVE_OPEN64
532 : typedef int (*__libc_open64)(const char *pathname, int flags, ...);
533 : #endif /* HAVE_OPEN64 */
534 : typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
535 : typedef int (*__libc_pipe)(int pipefd[2]);
536 : typedef int (*__libc_read)(int fd, void *buf, size_t count);
537 : typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
538 : typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
539 : typedef int (*__libc_recvfrom)(int sockfd,
540 : void *buf,
541 : size_t len,
542 : int flags,
543 : struct sockaddr *src_addr,
544 : socklen_t *addrlen);
545 : typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
546 : #ifdef HAVE_RECVMMSG
547 : #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
548 : /* FreeBSD */
549 : typedef ssize_t (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout);
550 : #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
551 : /* Linux legacy glibc < 2.21 */
552 : typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout);
553 : #else
554 : /* Linux glibc >= 2.21 */
555 : typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);
556 : #endif
557 : #endif /* HAVE_RECVMMSG */
558 : typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
559 : typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
560 : #ifdef HAVE_SENDMMSG
561 : #if defined(HAVE_SENDMMSG_SSIZE_T)
562 : /* FreeBSD */
563 : typedef ssize_t (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags);
564 : #else
565 : /* Linux */
566 : typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);
567 : #endif
568 : #endif /* HAVE_SENDMMSG */
569 : typedef int (*__libc_sendto)(int sockfd,
570 : const void *buf,
571 : size_t len,
572 : int flags,
573 : const struct sockaddr *dst_addr,
574 : socklen_t addrlen);
575 : typedef int (*__libc_setsockopt)(int sockfd,
576 : int level,
577 : int optname,
578 : const void *optval,
579 : socklen_t optlen);
580 : #ifdef HAVE_SIGNALFD
581 : typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
582 : #endif
583 : typedef int (*__libc_socket)(int domain, int type, int protocol);
584 : typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
585 : #ifdef HAVE_TIMERFD_CREATE
586 : typedef int (*__libc_timerfd_create)(int clockid, int flags);
587 : #endif
588 : typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
589 : typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
590 : #ifdef HAVE_SYSCALL
591 : typedef long int (*__libc_syscall)(long int sysno, ...);
592 : #endif
593 :
594 : #define SWRAP_SYMBOL_ENTRY(i) \
595 : union { \
596 : __libc_##i f; \
597 : void *obj; \
598 : } _libc_##i
599 :
600 : struct swrap_libc_symbols {
601 : #ifdef HAVE_ACCEPT4
602 : SWRAP_SYMBOL_ENTRY(accept4);
603 : #else
604 : SWRAP_SYMBOL_ENTRY(accept);
605 : #endif
606 : SWRAP_SYMBOL_ENTRY(bind);
607 : SWRAP_SYMBOL_ENTRY(close);
608 : #ifdef HAVE___CLOSE_NOCANCEL
609 : SWRAP_SYMBOL_ENTRY(__close_nocancel);
610 : #endif
611 : SWRAP_SYMBOL_ENTRY(connect);
612 : SWRAP_SYMBOL_ENTRY(dup);
613 : SWRAP_SYMBOL_ENTRY(dup2);
614 : SWRAP_SYMBOL_ENTRY(fcntl);
615 : SWRAP_SYMBOL_ENTRY(fopen);
616 : #ifdef HAVE_FOPEN64
617 : SWRAP_SYMBOL_ENTRY(fopen64);
618 : #endif
619 : #ifdef HAVE_EVENTFD
620 : SWRAP_SYMBOL_ENTRY(eventfd);
621 : #endif
622 : SWRAP_SYMBOL_ENTRY(getpeername);
623 : SWRAP_SYMBOL_ENTRY(getsockname);
624 : SWRAP_SYMBOL_ENTRY(getsockopt);
625 : SWRAP_SYMBOL_ENTRY(ioctl);
626 : SWRAP_SYMBOL_ENTRY(listen);
627 : SWRAP_SYMBOL_ENTRY(open);
628 : #ifdef HAVE_OPEN64
629 : SWRAP_SYMBOL_ENTRY(open64);
630 : #endif
631 : SWRAP_SYMBOL_ENTRY(openat);
632 : SWRAP_SYMBOL_ENTRY(pipe);
633 : SWRAP_SYMBOL_ENTRY(read);
634 : SWRAP_SYMBOL_ENTRY(readv);
635 : SWRAP_SYMBOL_ENTRY(recv);
636 : SWRAP_SYMBOL_ENTRY(recvfrom);
637 : SWRAP_SYMBOL_ENTRY(recvmsg);
638 : #ifdef HAVE_RECVMMSG
639 : SWRAP_SYMBOL_ENTRY(recvmmsg);
640 : #endif
641 : SWRAP_SYMBOL_ENTRY(send);
642 : SWRAP_SYMBOL_ENTRY(sendmsg);
643 : #ifdef HAVE_SENDMMSG
644 : SWRAP_SYMBOL_ENTRY(sendmmsg);
645 : #endif
646 : SWRAP_SYMBOL_ENTRY(sendto);
647 : SWRAP_SYMBOL_ENTRY(setsockopt);
648 : #ifdef HAVE_SIGNALFD
649 : SWRAP_SYMBOL_ENTRY(signalfd);
650 : #endif
651 : SWRAP_SYMBOL_ENTRY(socket);
652 : SWRAP_SYMBOL_ENTRY(socketpair);
653 : #ifdef HAVE_TIMERFD_CREATE
654 : SWRAP_SYMBOL_ENTRY(timerfd_create);
655 : #endif
656 : SWRAP_SYMBOL_ENTRY(write);
657 : SWRAP_SYMBOL_ENTRY(writev);
658 : #ifdef HAVE_SYSCALL
659 : SWRAP_SYMBOL_ENTRY(syscall);
660 : #endif
661 : };
662 : #undef SWRAP_SYMBOL_ENTRY
663 :
664 : #define SWRAP_SYMBOL_ENTRY(i) \
665 : union { \
666 : __rtld_default_##i f; \
667 : void *obj; \
668 : } _rtld_default_##i
669 :
670 : #ifdef HAVE_SYSCALL
671 : typedef bool (*__rtld_default_uid_wrapper_syscall_valid)(long int sysno);
672 : typedef long int (*__rtld_default_uid_wrapper_syscall_va)(long int sysno, va_list va);
673 : #endif
674 :
675 : struct swrap_rtld_default_symbols {
676 : #ifdef HAVE_SYSCALL
677 : SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_valid);
678 : SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_va);
679 : #else
680 : uint8_t dummy;
681 : #endif
682 : };
683 : #undef SWRAP_SYMBOL_ENTRY
684 :
685 : struct swrap {
686 : struct {
687 : void *handle;
688 : void *socket_handle;
689 : struct swrap_libc_symbols symbols;
690 : } libc;
691 :
692 : struct {
693 : struct swrap_rtld_default_symbols symbols;
694 : } rtld_default;
695 : };
696 :
697 : static struct swrap swrap;
698 :
699 : /* prototypes */
700 : static char *socket_wrapper_dir(void);
701 :
702 : #define LIBC_NAME "libc.so"
703 :
704 : enum swrap_lib {
705 : SWRAP_LIBC,
706 : SWRAP_LIBSOCKET,
707 : };
708 :
709 2112516 : static const char *swrap_str_lib(enum swrap_lib lib)
710 : {
711 2112516 : switch (lib) {
712 821534 : case SWRAP_LIBC:
713 821534 : return "libc";
714 1290982 : case SWRAP_LIBSOCKET:
715 1290982 : return "libsocket";
716 : }
717 :
718 : /* Compiler would warn us about unhandled enum value if we get here */
719 0 : return "unknown";
720 : }
721 :
722 2112516 : static void *swrap_load_lib_handle(enum swrap_lib lib)
723 : {
724 2112516 : int flags = RTLD_LAZY;
725 2112516 : void *handle = NULL;
726 : int i;
727 :
728 : #ifdef RTLD_DEEPBIND
729 2112516 : const char *env_preload = getenv("LD_PRELOAD");
730 2112516 : const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
731 2112516 : bool enable_deepbind = true;
732 :
733 : /* Don't do a deepbind if we run with libasan */
734 2112516 : if (env_preload != NULL && strlen(env_preload) < 1024) {
735 2112516 : const char *p = strstr(env_preload, "libasan.so");
736 2112516 : if (p != NULL) {
737 0 : enable_deepbind = false;
738 : }
739 : }
740 :
741 2112516 : if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
742 0 : enable_deepbind = false;
743 : }
744 :
745 2112516 : if (enable_deepbind) {
746 2112516 : flags |= RTLD_DEEPBIND;
747 : }
748 : #endif
749 :
750 2112516 : switch (lib) {
751 2112516 : case SWRAP_LIBSOCKET:
752 : #ifdef HAVE_LIBSOCKET
753 : handle = swrap.libc.socket_handle;
754 : if (handle == NULL) {
755 : for (i = 10; i >= 0; i--) {
756 : char soname[256] = {0};
757 :
758 : snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
759 : handle = dlopen(soname, flags);
760 : if (handle != NULL) {
761 : break;
762 : }
763 : }
764 :
765 : swrap.libc.socket_handle = handle;
766 : }
767 : break;
768 : #endif
769 : case SWRAP_LIBC:
770 2112516 : handle = swrap.libc.handle;
771 : #ifdef LIBC_SO
772 2112516 : if (handle == NULL) {
773 58681 : handle = dlopen(LIBC_SO, flags);
774 :
775 58681 : swrap.libc.handle = handle;
776 : }
777 : #endif
778 2112516 : if (handle == NULL) {
779 0 : for (i = 10; i >= 0; i--) {
780 0 : char soname[256] = {0};
781 :
782 0 : snprintf(soname, sizeof(soname), "libc.so.%d", i);
783 0 : handle = dlopen(soname, flags);
784 0 : if (handle != NULL) {
785 0 : break;
786 : }
787 : }
788 :
789 0 : swrap.libc.handle = handle;
790 : }
791 2112516 : break;
792 : }
793 :
794 2112516 : if (handle == NULL) {
795 : #ifdef RTLD_NEXT
796 0 : handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
797 : #else
798 : SWRAP_LOG(SWRAP_LOG_ERROR,
799 : "Failed to dlopen library: %s",
800 : dlerror());
801 : exit(-1);
802 : #endif
803 : }
804 :
805 2112516 : return handle;
806 : }
807 :
808 2112516 : static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
809 : {
810 : void *handle;
811 : void *func;
812 :
813 2112516 : handle = swrap_load_lib_handle(lib);
814 :
815 2112516 : func = dlsym(handle, fn_name);
816 2112516 : if (func == NULL) {
817 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
818 : "Failed to find %s: %s",
819 : fn_name,
820 : dlerror());
821 0 : exit(-1);
822 : }
823 :
824 2112516 : SWRAP_LOG(SWRAP_LOG_TRACE,
825 : "Loaded %s from %s",
826 : fn_name,
827 : swrap_str_lib(lib));
828 :
829 2112516 : return func;
830 : }
831 :
832 : #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
833 158501480 : static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
834 : {
835 : int ret;
836 :
837 158501480 : ret = pthread_mutex_lock(mutex);
838 158501480 : if (ret != 0) {
839 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
840 : getpid(), getppid(), caller, line, name, strerror(ret));
841 0 : abort();
842 : }
843 158501480 : }
844 :
845 : #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
846 158475993 : static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
847 : {
848 : int ret;
849 :
850 158475993 : ret = pthread_mutex_unlock(mutex);
851 158475993 : if (ret != 0) {
852 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
853 : getpid(), getppid(), caller, line, name, strerror(ret));
854 0 : abort();
855 : }
856 158475993 : }
857 :
858 : /*
859 : * These macros have a thread race condition on purpose!
860 : *
861 : * This is an optimization to avoid locking each time we check if the symbol is
862 : * bound.
863 : */
864 : #define _swrap_bind_symbol_generic(lib, sym_name) do { \
865 : swrap.libc.symbols._libc_##sym_name.obj = \
866 : _swrap_bind_symbol(lib, #sym_name); \
867 : } while(0);
868 :
869 : #define swrap_bind_symbol_libc(sym_name) \
870 : _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
871 :
872 : #define swrap_bind_symbol_libsocket(sym_name) \
873 : _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
874 :
875 : #define swrap_bind_symbol_rtld_default_optional(sym_name) do { \
876 : swrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
877 : dlsym(RTLD_DEFAULT, #sym_name); \
878 : } while(0);
879 :
880 : static void swrap_bind_symbol_all(void);
881 :
882 : /****************************************************************************
883 : * IMPORTANT
884 : ****************************************************************************
885 : *
886 : * Functions especially from libc need to be loaded individually, you can't
887 : * load all at once or gdb will segfault at startup. The same applies to
888 : * valgrind and has probably something todo with with the linker. So we need
889 : * load each function at the point it is called the first time.
890 : *
891 : ****************************************************************************/
892 :
893 : #ifdef HAVE_ACCEPT4
894 112073 : static int libc_accept4(int sockfd,
895 : struct sockaddr *addr,
896 : socklen_t *addrlen,
897 : int flags)
898 : {
899 112073 : swrap_bind_symbol_all();
900 :
901 112073 : return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
902 : }
903 :
904 : #else /* HAVE_ACCEPT4 */
905 :
906 : static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
907 : {
908 : swrap_bind_symbol_all();
909 :
910 : return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
911 : }
912 : #endif /* HAVE_ACCEPT4 */
913 :
914 154561 : static int libc_bind(int sockfd,
915 : const struct sockaddr *addr,
916 : socklen_t addrlen)
917 : {
918 154561 : swrap_bind_symbol_all();
919 :
920 154561 : return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
921 : }
922 :
923 37718799 : static int libc_close(int fd)
924 : {
925 37718799 : swrap_bind_symbol_all();
926 :
927 37718799 : return swrap.libc.symbols._libc_close.f(fd);
928 : }
929 :
930 : #ifdef HAVE___CLOSE_NOCANCEL
931 0 : static int libc___close_nocancel(int fd)
932 : {
933 0 : swrap_bind_symbol_all();
934 :
935 0 : return swrap.libc.symbols._libc___close_nocancel.f(fd);
936 : }
937 : #endif /* HAVE___CLOSE_NOCANCEL */
938 :
939 13225945 : static int libc_connect(int sockfd,
940 : const struct sockaddr *addr,
941 : socklen_t addrlen)
942 : {
943 13225945 : swrap_bind_symbol_all();
944 :
945 13225945 : return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
946 : }
947 :
948 75434 : static int libc_dup(int fd)
949 : {
950 75434 : swrap_bind_symbol_all();
951 :
952 75434 : return swrap.libc.symbols._libc_dup.f(fd);
953 : }
954 :
955 68578 : static int libc_dup2(int oldfd, int newfd)
956 : {
957 68578 : swrap_bind_symbol_all();
958 :
959 68578 : return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
960 : }
961 :
962 : #ifdef HAVE_EVENTFD
963 21614 : static int libc_eventfd(int count, int flags)
964 : {
965 21614 : swrap_bind_symbol_all();
966 :
967 21614 : return swrap.libc.symbols._libc_eventfd.f(count, flags);
968 : }
969 : #endif
970 :
971 : DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
972 211837504 : static int libc_vfcntl(int fd, int cmd, va_list ap)
973 : {
974 : void *arg;
975 : int rc;
976 :
977 211837504 : swrap_bind_symbol_all();
978 :
979 211837504 : arg = va_arg(ap, void *);
980 :
981 211837504 : rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
982 :
983 211837504 : return rc;
984 : }
985 :
986 6577 : static int libc_getpeername(int sockfd,
987 : struct sockaddr *addr,
988 : socklen_t *addrlen)
989 : {
990 6577 : swrap_bind_symbol_all();
991 :
992 6577 : return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
993 : }
994 :
995 399223 : static int libc_getsockname(int sockfd,
996 : struct sockaddr *addr,
997 : socklen_t *addrlen)
998 : {
999 399223 : swrap_bind_symbol_all();
1000 :
1001 399223 : return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
1002 : }
1003 :
1004 374346 : static int libc_getsockopt(int sockfd,
1005 : int level,
1006 : int optname,
1007 : void *optval,
1008 : socklen_t *optlen)
1009 : {
1010 374346 : swrap_bind_symbol_all();
1011 :
1012 374346 : return swrap.libc.symbols._libc_getsockopt.f(sockfd,
1013 : level,
1014 : optname,
1015 : optval,
1016 : optlen);
1017 : }
1018 :
1019 : DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1020 1575696 : static int libc_vioctl(int d, unsigned long int request, va_list ap)
1021 : {
1022 : void *arg;
1023 : int rc;
1024 :
1025 1575696 : swrap_bind_symbol_all();
1026 :
1027 1575696 : arg = va_arg(ap, void *);
1028 :
1029 1575696 : rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
1030 :
1031 1575696 : return rc;
1032 : }
1033 :
1034 2863 : static int libc_listen(int sockfd, int backlog)
1035 : {
1036 2863 : swrap_bind_symbol_all();
1037 :
1038 2863 : return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
1039 : }
1040 :
1041 1595690 : static FILE *libc_fopen(const char *name, const char *mode)
1042 : {
1043 1595690 : swrap_bind_symbol_all();
1044 :
1045 1595690 : return swrap.libc.symbols._libc_fopen.f(name, mode);
1046 : }
1047 :
1048 : #ifdef HAVE_FOPEN64
1049 : static FILE *libc_fopen64(const char *name, const char *mode)
1050 : {
1051 : swrap_bind_symbol_all();
1052 :
1053 : return swrap.libc.symbols._libc_fopen64.f(name, mode);
1054 : }
1055 : #endif /* HAVE_FOPEN64 */
1056 :
1057 49411683 : static void swrap_inject_o_largefile(int *flags)
1058 : {
1059 : (void)*flags; /* maybe unused */
1060 : #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1061 : #ifdef O_PATH
1062 : if (((*flags) & O_PATH) == 0)
1063 : #endif
1064 : {
1065 : *flags |= O_LARGEFILE;
1066 : }
1067 : #endif
1068 49411683 : }
1069 :
1070 49279894 : static int libc_vopen(const char *pathname, int flags, va_list ap)
1071 : {
1072 49279894 : int mode = 0;
1073 : int fd;
1074 :
1075 49279894 : swrap_bind_symbol_all();
1076 :
1077 49279894 : swrap_inject_o_largefile(&flags);
1078 :
1079 49279894 : if (flags & O_CREAT) {
1080 25220355 : mode = va_arg(ap, int);
1081 : }
1082 49279894 : fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1083 :
1084 49279894 : return fd;
1085 : }
1086 :
1087 47406010 : static int libc_open(const char *pathname, int flags, ...)
1088 : {
1089 : va_list ap;
1090 : int fd;
1091 :
1092 47406010 : va_start(ap, flags);
1093 47406010 : fd = libc_vopen(pathname, flags, ap);
1094 47406010 : va_end(ap);
1095 :
1096 47406010 : return fd;
1097 : }
1098 :
1099 : #ifdef HAVE_OPEN64
1100 : static int libc_vopen64(const char *pathname, int flags, va_list ap)
1101 : {
1102 : int mode = 0;
1103 : int fd;
1104 :
1105 : swrap_bind_symbol_all();
1106 :
1107 : swrap_inject_o_largefile(&flags);
1108 :
1109 : if (flags & O_CREAT) {
1110 : mode = va_arg(ap, int);
1111 : }
1112 : fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1113 :
1114 : return fd;
1115 : }
1116 : #endif /* HAVE_OPEN64 */
1117 :
1118 131789 : static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1119 : {
1120 131789 : int mode = 0;
1121 : int fd;
1122 :
1123 131789 : swrap_bind_symbol_all();
1124 :
1125 131789 : swrap_inject_o_largefile(&flags);
1126 :
1127 131789 : if (flags & O_CREAT) {
1128 773 : mode = va_arg(ap, int);
1129 : }
1130 131789 : fd = swrap.libc.symbols._libc_openat.f(dirfd,
1131 : path,
1132 : flags,
1133 : (mode_t)mode);
1134 :
1135 131789 : return fd;
1136 : }
1137 :
1138 : #if 0
1139 : static int libc_openat(int dirfd, const char *path, int flags, ...)
1140 : {
1141 : va_list ap;
1142 : int fd;
1143 :
1144 : va_start(ap, flags);
1145 : fd = libc_vopenat(dirfd, path, flags, ap);
1146 : va_end(ap);
1147 :
1148 : return fd;
1149 : }
1150 : #endif
1151 :
1152 318218 : static int libc_pipe(int pipefd[2])
1153 : {
1154 318218 : swrap_bind_symbol_all();
1155 :
1156 318218 : return swrap.libc.symbols._libc_pipe.f(pipefd);
1157 : }
1158 :
1159 3062475 : static int libc_read(int fd, void *buf, size_t count)
1160 : {
1161 3062475 : swrap_bind_symbol_all();
1162 :
1163 3062475 : return swrap.libc.symbols._libc_read.f(fd, buf, count);
1164 : }
1165 :
1166 9886742 : static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1167 : {
1168 9886742 : swrap_bind_symbol_all();
1169 :
1170 9886742 : return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1171 : }
1172 :
1173 4137725 : static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1174 : {
1175 4137725 : swrap_bind_symbol_all();
1176 :
1177 4137725 : return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1178 : }
1179 :
1180 45295 : static int libc_recvfrom(int sockfd,
1181 : void *buf,
1182 : size_t len,
1183 : int flags,
1184 : struct sockaddr *src_addr,
1185 : socklen_t *addrlen)
1186 : {
1187 45295 : swrap_bind_symbol_all();
1188 :
1189 45295 : return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1190 : buf,
1191 : len,
1192 : flags,
1193 : src_addr,
1194 : addrlen);
1195 : }
1196 :
1197 424760 : static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1198 : {
1199 424760 : swrap_bind_symbol_all();
1200 :
1201 424760 : return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1202 : }
1203 :
1204 : #ifdef HAVE_RECVMMSG
1205 : #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1206 : /* FreeBSD */
1207 : static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1208 : #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1209 : /* Linux legacy glibc < 2.21 */
1210 : static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1211 : #else
1212 : /* Linux glibc >= 2.21 */
1213 0 : static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1214 : #endif
1215 : {
1216 0 : swrap_bind_symbol_all();
1217 :
1218 0 : return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1219 : }
1220 : #endif
1221 :
1222 980427 : static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1223 : {
1224 980427 : swrap_bind_symbol_all();
1225 :
1226 980427 : return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1227 : }
1228 :
1229 303606 : static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1230 : {
1231 303606 : swrap_bind_symbol_all();
1232 :
1233 303606 : return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1234 : }
1235 :
1236 : #ifdef HAVE_SENDMMSG
1237 : #if defined(HAVE_SENDMMSG_SSIZE_T)
1238 : /* FreeBSD */
1239 : static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1240 : #else
1241 : /* Linux */
1242 58 : static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1243 : #endif
1244 : {
1245 58 : swrap_bind_symbol_all();
1246 :
1247 58 : return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1248 : }
1249 : #endif
1250 :
1251 39077 : static int libc_sendto(int sockfd,
1252 : const void *buf,
1253 : size_t len,
1254 : int flags,
1255 : const struct sockaddr *dst_addr,
1256 : socklen_t addrlen)
1257 : {
1258 39077 : swrap_bind_symbol_all();
1259 :
1260 39077 : return swrap.libc.symbols._libc_sendto.f(sockfd,
1261 : buf,
1262 : len,
1263 : flags,
1264 : dst_addr,
1265 : addrlen);
1266 : }
1267 :
1268 23155 : static int libc_setsockopt(int sockfd,
1269 : int level,
1270 : int optname,
1271 : const void *optval,
1272 : socklen_t optlen)
1273 : {
1274 23155 : swrap_bind_symbol_all();
1275 :
1276 23155 : return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1277 : level,
1278 : optname,
1279 : optval,
1280 : optlen);
1281 : }
1282 :
1283 : #ifdef HAVE_SIGNALFD
1284 0 : static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1285 : {
1286 0 : swrap_bind_symbol_all();
1287 :
1288 0 : return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1289 : }
1290 : #endif
1291 :
1292 1028226 : static int libc_socket(int domain, int type, int protocol)
1293 : {
1294 1028226 : swrap_bind_symbol_all();
1295 :
1296 1028226 : return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1297 : }
1298 :
1299 1117 : static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1300 : {
1301 1117 : swrap_bind_symbol_all();
1302 :
1303 1117 : return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1304 : }
1305 :
1306 : #ifdef HAVE_TIMERFD_CREATE
1307 0 : static int libc_timerfd_create(int clockid, int flags)
1308 : {
1309 0 : swrap_bind_symbol_all();
1310 :
1311 0 : return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1312 : }
1313 : #endif
1314 :
1315 3332505 : static ssize_t libc_write(int fd, const void *buf, size_t count)
1316 : {
1317 3332505 : swrap_bind_symbol_all();
1318 :
1319 3332505 : return swrap.libc.symbols._libc_write.f(fd, buf, count);
1320 : }
1321 :
1322 7976089 : static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1323 : {
1324 7976089 : swrap_bind_symbol_all();
1325 :
1326 7976089 : return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1327 : }
1328 :
1329 : #ifdef HAVE_SYSCALL
1330 : DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1331 313387 : static long int libc_vsyscall(long int sysno, va_list va)
1332 : {
1333 : long int args[8];
1334 : long int rc;
1335 : int i;
1336 :
1337 313387 : swrap_bind_symbol_all();
1338 :
1339 2820483 : for (i = 0; i < 8; i++) {
1340 2507096 : args[i] = va_arg(va, long int);
1341 : }
1342 :
1343 313387 : rc = swrap.libc.symbols._libc_syscall.f(sysno,
1344 : args[0],
1345 : args[1],
1346 : args[2],
1347 : args[3],
1348 : args[4],
1349 : args[5],
1350 : args[6],
1351 : args[7]);
1352 :
1353 313387 : return rc;
1354 : }
1355 :
1356 6559327 : static bool swrap_uwrap_syscall_valid(long int sysno)
1357 : {
1358 6559327 : swrap_bind_symbol_all();
1359 :
1360 6559327 : if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f == NULL) {
1361 0 : return false;
1362 : }
1363 :
1364 6559327 : return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f(
1365 : sysno);
1366 : }
1367 :
1368 : DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1369 6245940 : static long int swrap_uwrap_syscall_va(long int sysno, va_list va)
1370 : {
1371 6245940 : swrap_bind_symbol_all();
1372 :
1373 6245940 : if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f == NULL) {
1374 : /*
1375 : * Fallback to libc, if uid_wrapper_syscall_va is not
1376 : * available.
1377 : */
1378 0 : return libc_vsyscall(sysno, va);
1379 : }
1380 :
1381 6245940 : return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f(
1382 : sysno,
1383 : va);
1384 : }
1385 : #endif /* HAVE_SYSCALL */
1386 :
1387 : /* DO NOT call this function during library initialization! */
1388 58681 : static void __swrap_bind_symbol_all_once(void)
1389 : {
1390 : #ifdef HAVE_ACCEPT4
1391 58681 : swrap_bind_symbol_libsocket(accept4);
1392 : #else
1393 : swrap_bind_symbol_libsocket(accept);
1394 : #endif
1395 58681 : swrap_bind_symbol_libsocket(bind);
1396 58681 : swrap_bind_symbol_libc(close);
1397 : #ifdef HAVE___CLOSE_NOCANCEL
1398 58681 : swrap_bind_symbol_libc(__close_nocancel);
1399 : #endif
1400 58681 : swrap_bind_symbol_libsocket(connect);
1401 58681 : swrap_bind_symbol_libc(dup);
1402 58681 : swrap_bind_symbol_libc(dup2);
1403 58681 : swrap_bind_symbol_libc(fcntl);
1404 58681 : swrap_bind_symbol_libc(fopen);
1405 : #ifdef HAVE_FOPEN64
1406 : swrap_bind_symbol_libc(fopen64);
1407 : #endif
1408 : #ifdef HAVE_EVENTFD
1409 58681 : swrap_bind_symbol_libc(eventfd);
1410 : #endif
1411 58681 : swrap_bind_symbol_libsocket(getpeername);
1412 58681 : swrap_bind_symbol_libsocket(getsockname);
1413 58681 : swrap_bind_symbol_libsocket(getsockopt);
1414 58681 : swrap_bind_symbol_libc(ioctl);
1415 58681 : swrap_bind_symbol_libsocket(listen);
1416 58681 : swrap_bind_symbol_libc(open);
1417 : #ifdef HAVE_OPEN64
1418 : swrap_bind_symbol_libc(open64);
1419 : #endif
1420 58681 : swrap_bind_symbol_libc(openat);
1421 58681 : swrap_bind_symbol_libsocket(pipe);
1422 58681 : swrap_bind_symbol_libc(read);
1423 58681 : swrap_bind_symbol_libsocket(readv);
1424 58681 : swrap_bind_symbol_libsocket(recv);
1425 58681 : swrap_bind_symbol_libsocket(recvfrom);
1426 58681 : swrap_bind_symbol_libsocket(recvmsg);
1427 : #ifdef HAVE_RECVMMSG
1428 58681 : swrap_bind_symbol_libsocket(recvmmsg);
1429 : #endif
1430 58681 : swrap_bind_symbol_libsocket(send);
1431 58681 : swrap_bind_symbol_libsocket(sendmsg);
1432 : #ifdef HAVE_SENDMMSG
1433 58681 : swrap_bind_symbol_libsocket(sendmmsg);
1434 : #endif
1435 58681 : swrap_bind_symbol_libsocket(sendto);
1436 58681 : swrap_bind_symbol_libsocket(setsockopt);
1437 : #ifdef HAVE_SIGNALFD
1438 58681 : swrap_bind_symbol_libsocket(signalfd);
1439 : #endif
1440 58681 : swrap_bind_symbol_libsocket(socket);
1441 58681 : swrap_bind_symbol_libsocket(socketpair);
1442 : #ifdef HAVE_TIMERFD_CREATE
1443 58681 : swrap_bind_symbol_libc(timerfd_create);
1444 : #endif
1445 58681 : swrap_bind_symbol_libc(write);
1446 58681 : swrap_bind_symbol_libsocket(writev);
1447 : #ifdef HAVE_SYSCALL
1448 58681 : swrap_bind_symbol_libc(syscall);
1449 58681 : swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
1450 58681 : swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
1451 : #endif
1452 58681 : }
1453 :
1454 362692120 : static void swrap_bind_symbol_all(void)
1455 : {
1456 : static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1457 :
1458 362692120 : pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1459 362692120 : }
1460 :
1461 : /*********************************************************
1462 : * SWRAP HELPER FUNCTIONS
1463 : *********************************************************/
1464 :
1465 : /*
1466 : * We return 127.0.0.0 (default) or 10.53.57.0.
1467 : *
1468 : * This can be controlled by:
1469 : * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1470 : * or
1471 : * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1472 : */
1473 26881698 : static in_addr_t swrap_ipv4_net(void)
1474 : {
1475 : static int initialized;
1476 : static in_addr_t hv;
1477 26881698 : const char *net_str = NULL;
1478 : struct in_addr nv;
1479 : int ret;
1480 :
1481 26881698 : if (initialized) {
1482 26868275 : return hv;
1483 : }
1484 13423 : initialized = 1;
1485 :
1486 13423 : net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1487 13423 : if (net_str == NULL) {
1488 0 : net_str = "127.0.0.0";
1489 : }
1490 :
1491 13423 : ret = inet_pton(AF_INET, net_str, &nv);
1492 13423 : if (ret <= 0) {
1493 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1494 : "INVALID IPv4 Network [%s]",
1495 : net_str);
1496 0 : abort();
1497 : }
1498 :
1499 13423 : hv = ntohl(nv.s_addr);
1500 :
1501 13423 : switch (hv) {
1502 0 : case 0x7f000000:
1503 : /* 127.0.0.0 */
1504 0 : break;
1505 13423 : case 0x0a353900:
1506 : /* 10.53.57.0 */
1507 13423 : break;
1508 0 : default:
1509 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1510 : "INVALID IPv4 Network [%s][0x%x] should be "
1511 : "127.0.0.0 or 10.53.57.0",
1512 : net_str, (unsigned)hv);
1513 0 : abort();
1514 : }
1515 :
1516 13423 : return hv;
1517 : }
1518 :
1519 : /*
1520 : * This returns 127.255.255.255 or 10.255.255.255
1521 : */
1522 13259899 : static in_addr_t swrap_ipv4_bcast(void)
1523 : {
1524 : in_addr_t hv;
1525 :
1526 13259899 : hv = swrap_ipv4_net();
1527 13259899 : hv |= IN_CLASSA_HOST;
1528 :
1529 13259899 : return hv;
1530 : }
1531 :
1532 : /*
1533 : * This returns 127.0.0.${iface} or 10.53.57.${iface}
1534 : */
1535 348477 : static in_addr_t swrap_ipv4_iface(unsigned int iface)
1536 : {
1537 : in_addr_t hv;
1538 :
1539 348477 : if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1540 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1541 : "swrap_ipv4_iface(%u) invalid!",
1542 : iface);
1543 0 : abort();
1544 : return -1;
1545 : }
1546 :
1547 348477 : hv = swrap_ipv4_net();
1548 348477 : hv |= iface;
1549 :
1550 348477 : return hv;
1551 : }
1552 :
1553 : #ifdef HAVE_IPV6
1554 : /*
1555 : * FD00::5357:5FXX
1556 : */
1557 3092 : static const struct in6_addr *swrap_ipv6(void)
1558 : {
1559 : static struct in6_addr v;
1560 : static int initialized;
1561 : int ret;
1562 :
1563 3092 : if (initialized) {
1564 2515 : return &v;
1565 : }
1566 577 : initialized = 1;
1567 :
1568 577 : ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1569 577 : if (ret <= 0) {
1570 0 : abort();
1571 : }
1572 :
1573 577 : return &v;
1574 : }
1575 : #endif
1576 :
1577 125974 : static void set_port(int family, int prt, struct swrap_address *addr)
1578 : {
1579 125974 : switch (family) {
1580 125742 : case AF_INET:
1581 125742 : addr->sa.in.sin_port = htons(prt);
1582 125742 : break;
1583 : #ifdef HAVE_IPV6
1584 232 : case AF_INET6:
1585 232 : addr->sa.in6.sin6_port = htons(prt);
1586 232 : break;
1587 : #endif
1588 : }
1589 125974 : }
1590 :
1591 100977 : static size_t socket_length(int family)
1592 : {
1593 100977 : switch (family) {
1594 100932 : case AF_INET:
1595 100932 : return sizeof(struct sockaddr_in);
1596 : #ifdef HAVE_IPV6
1597 45 : case AF_INET6:
1598 45 : return sizeof(struct sockaddr_in6);
1599 : #endif
1600 : }
1601 0 : return 0;
1602 : }
1603 :
1604 : struct swrap_sockaddr_buf {
1605 : char str[128];
1606 : };
1607 :
1608 26332408 : static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1609 : const struct sockaddr *saddr)
1610 : {
1611 26332408 : unsigned int port = 0;
1612 26332408 : char addr[64] = {0,};
1613 :
1614 26332408 : switch (saddr->sa_family) {
1615 26330959 : case AF_INET: {
1616 26330959 : const struct sockaddr_in *in =
1617 : (const struct sockaddr_in *)(const void *)saddr;
1618 :
1619 26330959 : port = ntohs(in->sin_port);
1620 :
1621 26330959 : inet_ntop(saddr->sa_family,
1622 26330959 : &in->sin_addr,
1623 : addr, sizeof(addr));
1624 26330959 : break;
1625 : }
1626 : #ifdef HAVE_IPV6
1627 1449 : case AF_INET6: {
1628 1449 : const struct sockaddr_in6 *in6 =
1629 : (const struct sockaddr_in6 *)(const void *)saddr;
1630 :
1631 1449 : port = ntohs(in6->sin6_port);
1632 :
1633 1449 : inet_ntop(saddr->sa_family,
1634 1449 : &in6->sin6_addr,
1635 : addr, sizeof(addr));
1636 1449 : break;
1637 : }
1638 : #endif
1639 0 : default:
1640 0 : snprintf(addr, sizeof(addr),
1641 : "<Unknown address family %u>",
1642 0 : saddr->sa_family);
1643 0 : break;
1644 : }
1645 :
1646 26332408 : snprintf(buf->str, sizeof(buf->str),
1647 : "addr[%s]/port[%u]",
1648 : addr, port);
1649 :
1650 26332408 : return buf->str;
1651 : }
1652 :
1653 42026588 : static struct socket_info *swrap_get_socket_info(int si_index)
1654 : {
1655 42026588 : return (struct socket_info *)(&(sockets[si_index].info));
1656 : }
1657 :
1658 1243791 : static int swrap_get_refcount(struct socket_info *si)
1659 : {
1660 1243791 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1661 1243791 : return sic->meta.refcount;
1662 : }
1663 :
1664 1081102 : static void swrap_inc_refcount(struct socket_info *si)
1665 : {
1666 1081102 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1667 :
1668 1081102 : sic->meta.refcount += 1;
1669 1081102 : }
1670 :
1671 1243791 : static void swrap_dec_refcount(struct socket_info *si)
1672 : {
1673 1243791 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1674 :
1675 1243791 : sic->meta.refcount -= 1;
1676 1243791 : }
1677 :
1678 1065789 : static int swrap_get_next_free(struct socket_info *si)
1679 : {
1680 1065789 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1681 :
1682 1065789 : return sic->meta.next_free;
1683 : }
1684 :
1685 880918206 : static void swrap_set_next_free(struct socket_info *si, int next_free)
1686 : {
1687 880918206 : struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1688 :
1689 880918206 : sic->meta.next_free = next_free;
1690 880918206 : }
1691 :
1692 28306293 : static int swrap_un_path(struct sockaddr_un *un,
1693 : const char *swrap_dir,
1694 : char type,
1695 : unsigned int iface,
1696 : unsigned int prt)
1697 : {
1698 : int ret;
1699 :
1700 28306293 : ret = snprintf(un->sun_path,
1701 : sizeof(un->sun_path),
1702 : "%s/"SOCKET_FORMAT,
1703 : swrap_dir,
1704 : type,
1705 : iface,
1706 : prt);
1707 28306293 : if ((size_t)ret >= sizeof(un->sun_path)) {
1708 0 : return ENAMETOOLONG;
1709 : }
1710 :
1711 28306293 : return 0;
1712 : }
1713 :
1714 3012 : static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1715 : const char *swrap_dir)
1716 : {
1717 : int ret;
1718 :
1719 3012 : ret = snprintf(un->sun_path,
1720 : sizeof(un->sun_path),
1721 : "%s/EINVAL",
1722 : swrap_dir);
1723 :
1724 3012 : if ((size_t)ret >= sizeof(un->sun_path)) {
1725 0 : return ENAMETOOLONG;
1726 : }
1727 :
1728 3012 : return 0;
1729 : }
1730 :
1731 14409845 : static bool swrap_dir_usable(const char *swrap_dir)
1732 : {
1733 : struct sockaddr_un un;
1734 : int ret;
1735 :
1736 14409845 : ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1737 14409845 : if (ret == 0) {
1738 14409845 : return true;
1739 : }
1740 :
1741 0 : ret = swrap_un_path_EINVAL(&un, swrap_dir);
1742 0 : if (ret == 0) {
1743 0 : return true;
1744 : }
1745 :
1746 0 : return false;
1747 : }
1748 :
1749 14409845 : static char *socket_wrapper_dir(void)
1750 : {
1751 14409845 : char *swrap_dir = NULL;
1752 14409845 : char *s = getenv("SOCKET_WRAPPER_DIR");
1753 : char *t;
1754 : bool ok;
1755 :
1756 14409845 : if (s == NULL || s[0] == '\0') {
1757 0 : SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1758 0 : return NULL;
1759 : }
1760 :
1761 14409845 : swrap_dir = realpath(s, NULL);
1762 14409845 : if (swrap_dir == NULL) {
1763 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1764 : "Unable to resolve socket_wrapper dir path: %s - %s",
1765 : s,
1766 : strerror(errno));
1767 0 : abort();
1768 : }
1769 :
1770 14409845 : ok = swrap_dir_usable(swrap_dir);
1771 14409845 : if (ok) {
1772 14409845 : goto done;
1773 : }
1774 :
1775 0 : free(swrap_dir);
1776 :
1777 0 : ok = swrap_dir_usable(s);
1778 0 : if (!ok) {
1779 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1780 0 : abort();
1781 : }
1782 :
1783 0 : t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1784 0 : if (t == NULL) {
1785 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1786 : "realpath(SOCKET_WRAPPER_DIR) too long and "
1787 : "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1788 0 : abort();
1789 :
1790 : }
1791 :
1792 0 : swrap_dir = strdup(s);
1793 0 : if (swrap_dir == NULL) {
1794 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1795 : "Unable to duplicate socket_wrapper dir path");
1796 0 : abort();
1797 : }
1798 :
1799 0 : SWRAP_LOG(SWRAP_LOG_WARN,
1800 : "realpath(SOCKET_WRAPPER_DIR) too long, "
1801 : "using original SOCKET_WRAPPER_DIR\n");
1802 :
1803 14409845 : done:
1804 14409845 : SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1805 14409845 : return swrap_dir;
1806 : }
1807 :
1808 22417164 : static unsigned int socket_wrapper_mtu(void)
1809 : {
1810 : static unsigned int max_mtu = 0;
1811 : unsigned int tmp;
1812 : const char *s;
1813 : char *endp;
1814 :
1815 22417164 : swrap_mutex_lock(&mtu_update_mutex);
1816 :
1817 22417164 : if (max_mtu != 0) {
1818 22392063 : goto done;
1819 : }
1820 :
1821 25101 : max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1822 :
1823 25101 : s = getenv("SOCKET_WRAPPER_MTU");
1824 25101 : if (s == NULL) {
1825 25086 : goto done;
1826 : }
1827 :
1828 15 : tmp = strtol(s, &endp, 10);
1829 15 : if (s == endp) {
1830 0 : goto done;
1831 : }
1832 :
1833 15 : if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1834 0 : goto done;
1835 : }
1836 15 : max_mtu = tmp;
1837 :
1838 22417164 : done:
1839 22417164 : swrap_mutex_unlock(&mtu_update_mutex);
1840 22417164 : return max_mtu;
1841 : }
1842 :
1843 436254 : static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1844 : {
1845 : pthread_mutexattr_t ma;
1846 436254 : bool need_destroy = false;
1847 436254 : int ret = 0;
1848 :
1849 : #define __CHECK(cmd) do { \
1850 : ret = cmd; \
1851 : if (ret != 0) { \
1852 : SWRAP_LOG(SWRAP_LOG_ERROR, \
1853 : "%s: %s - failed %d", \
1854 : name, #cmd, ret); \
1855 : goto done; \
1856 : } \
1857 : } while(0)
1858 :
1859 436254 : *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1860 436254 : __CHECK(pthread_mutexattr_init(&ma));
1861 436254 : need_destroy = true;
1862 436254 : __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1863 436254 : __CHECK(pthread_mutex_init(m, &ma));
1864 436254 : done:
1865 436254 : if (need_destroy) {
1866 436254 : pthread_mutexattr_destroy(&ma);
1867 : }
1868 436254 : return ret;
1869 : }
1870 :
1871 13423 : static size_t socket_wrapper_max_sockets(void)
1872 : {
1873 : const char *s;
1874 : size_t tmp;
1875 : char *endp;
1876 :
1877 13423 : if (socket_info_max != 0) {
1878 0 : return socket_info_max;
1879 : }
1880 :
1881 13423 : socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1882 :
1883 13423 : s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1884 13423 : if (s == NULL || s[0] == '\0') {
1885 13423 : goto done;
1886 : }
1887 :
1888 0 : tmp = strtoul(s, &endp, 10);
1889 0 : if (s == endp) {
1890 0 : goto done;
1891 : }
1892 0 : if (tmp == 0) {
1893 0 : tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1894 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1895 : "Invalid number of sockets specified, "
1896 : "using default (%zu)",
1897 : tmp);
1898 : }
1899 :
1900 0 : if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1901 0 : tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1902 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1903 : "Invalid number of sockets specified, "
1904 : "using maximum (%zu).",
1905 : tmp);
1906 : }
1907 :
1908 0 : socket_info_max = tmp;
1909 :
1910 13423 : done:
1911 13423 : return socket_info_max;
1912 : }
1913 :
1914 13423 : static void socket_wrapper_init_fds_idx(void)
1915 : {
1916 13423 : int *tmp = NULL;
1917 : size_t i;
1918 :
1919 13423 : if (socket_fds_idx != NULL) {
1920 0 : return;
1921 : }
1922 :
1923 13423 : tmp = (int *)calloc(socket_fds_max, sizeof(int));
1924 13423 : if (tmp == NULL) {
1925 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1926 : "Failed to allocate socket fds index array: %s",
1927 : strerror(errno));
1928 0 : exit(-1);
1929 : }
1930 :
1931 3518718643 : for (i = 0; i < socket_fds_max; i++) {
1932 3518705220 : tmp[i] = -1;
1933 : }
1934 :
1935 13423 : socket_fds_idx = tmp;
1936 : }
1937 :
1938 1028502 : static void socket_wrapper_init_sockets(void)
1939 : {
1940 : size_t max_sockets;
1941 : size_t i;
1942 1028502 : int ret = 0;
1943 :
1944 1028502 : swrap_bind_symbol_all();
1945 :
1946 1028502 : swrap_mutex_lock(&sockets_mutex);
1947 :
1948 1028502 : if (sockets != NULL) {
1949 1015079 : swrap_mutex_unlock(&sockets_mutex);
1950 1015079 : return;
1951 : }
1952 :
1953 13423 : SWRAP_LOG(SWRAP_LOG_DEBUG,
1954 : "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1955 : SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1956 :
1957 : /*
1958 : * Intialize the static cache early before
1959 : * any thread is able to start.
1960 : */
1961 13423 : (void)swrap_ipv4_net();
1962 :
1963 13423 : socket_wrapper_init_fds_idx();
1964 :
1965 : /* Needs to be called inside the sockets_mutex lock here. */
1966 13423 : max_sockets = socket_wrapper_max_sockets();
1967 :
1968 13423 : sockets = (struct socket_info_container *)calloc(max_sockets,
1969 : sizeof(struct socket_info_container));
1970 :
1971 13423 : if (sockets == NULL) {
1972 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
1973 : "Failed to allocate sockets array: %s",
1974 : strerror(errno));
1975 0 : swrap_mutex_unlock(&sockets_mutex);
1976 0 : exit(-1);
1977 : }
1978 :
1979 13423 : swrap_mutex_lock(&first_free_mutex);
1980 13423 : swrap_mutex_lock(&sockets_si_global);
1981 :
1982 13423 : first_free = 0;
1983 :
1984 879689728 : for (i = 0; i < max_sockets; i++) {
1985 879676305 : swrap_set_next_free(&sockets[i].info, i+1);
1986 : }
1987 :
1988 : /* mark the end of the free list */
1989 13423 : swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1990 :
1991 13423 : swrap_mutex_unlock(&sockets_si_global);
1992 13423 : swrap_mutex_unlock(&first_free_mutex);
1993 13423 : swrap_mutex_unlock(&sockets_mutex);
1994 13423 : if (ret != 0) {
1995 0 : exit(-1);
1996 : }
1997 : }
1998 :
1999 1028502 : bool socket_wrapper_enabled(void)
2000 : {
2001 1028502 : char *s = socket_wrapper_dir();
2002 :
2003 1028502 : if (s == NULL) {
2004 0 : return false;
2005 : }
2006 :
2007 1028502 : SAFE_FREE(s);
2008 :
2009 1028502 : socket_wrapper_init_sockets();
2010 :
2011 1028502 : return true;
2012 : }
2013 :
2014 252101 : static unsigned int socket_wrapper_default_iface(void)
2015 : {
2016 252101 : const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2017 252101 : if (s) {
2018 : unsigned int iface;
2019 249403 : if (sscanf(s, "%u", &iface) == 1) {
2020 249403 : if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
2021 249403 : return iface;
2022 : }
2023 : }
2024 : }
2025 :
2026 2698 : return 1;/* 127.0.0.1 */
2027 : }
2028 :
2029 2324893 : static void set_socket_info_index(int fd, int idx)
2030 : {
2031 2324893 : SWRAP_LOG(SWRAP_LOG_TRACE,
2032 : "fd=%d idx=%d",
2033 : fd, idx);
2034 2324893 : socket_fds_idx[fd] = idx;
2035 : /* This builtin issues a full memory barrier. */
2036 2324893 : __sync_synchronize();
2037 2324893 : }
2038 :
2039 1243791 : static void reset_socket_info_index(int fd)
2040 : {
2041 1243791 : SWRAP_LOG(SWRAP_LOG_TRACE,
2042 : "fd=%d idx=%d",
2043 : fd, -1);
2044 1243791 : set_socket_info_index(fd, -1);
2045 1243791 : }
2046 :
2047 300354825 : static int find_socket_info_index(int fd)
2048 : {
2049 300354825 : if (fd < 0) {
2050 0 : return -1;
2051 : }
2052 :
2053 300354825 : if (socket_fds_idx == NULL) {
2054 59889334 : return -1;
2055 : }
2056 :
2057 240465491 : if ((size_t)fd >= socket_fds_max) {
2058 : /*
2059 : * Do not add a log here as some applications do stupid things
2060 : * like:
2061 : *
2062 : * for (fd = 0; fd <= getdtablesize(); fd++) {
2063 : * close(fd)
2064 : * };
2065 : *
2066 : * This would produce millions of lines of debug messages.
2067 : */
2068 : #if 0
2069 : SWRAP_LOG(SWRAP_LOG_ERROR,
2070 : "Looking for a socket info for the fd %d is over the "
2071 : "max socket index limit of %zu.",
2072 : fd,
2073 : socket_fds_max);
2074 : #endif
2075 0 : return -1;
2076 : }
2077 :
2078 : /* This builtin issues a full memory barrier. */
2079 240465491 : __sync_synchronize();
2080 240465491 : return socket_fds_idx[fd];
2081 : }
2082 :
2083 1065789 : static int swrap_add_socket_info(const struct socket_info *si_input)
2084 : {
2085 1065789 : struct socket_info *si = NULL;
2086 1065789 : int si_index = -1;
2087 :
2088 1065789 : if (si_input == NULL) {
2089 0 : errno = EINVAL;
2090 0 : return -1;
2091 : }
2092 :
2093 1065789 : swrap_mutex_lock(&first_free_mutex);
2094 1065789 : if (first_free == -1) {
2095 0 : errno = ENFILE;
2096 0 : goto out;
2097 : }
2098 :
2099 1065789 : si_index = first_free;
2100 1065789 : si = swrap_get_socket_info(si_index);
2101 :
2102 1065789 : SWRAP_LOCK_SI(si);
2103 :
2104 1065789 : first_free = swrap_get_next_free(si);
2105 1065789 : *si = *si_input;
2106 1065789 : swrap_inc_refcount(si);
2107 :
2108 1065789 : SWRAP_UNLOCK_SI(si);
2109 :
2110 1065789 : out:
2111 1065789 : swrap_mutex_unlock(&first_free_mutex);
2112 :
2113 1065789 : return si_index;
2114 : }
2115 :
2116 1065365 : static int swrap_create_socket(struct socket_info *si, int fd)
2117 : {
2118 : int idx;
2119 :
2120 1065365 : if ((size_t)fd >= socket_fds_max) {
2121 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
2122 : "The max socket index limit of %zu has been reached, "
2123 : "trying to add %d",
2124 : socket_fds_max,
2125 : fd);
2126 0 : errno = EMFILE;
2127 0 : return -1;
2128 : }
2129 :
2130 1065365 : idx = swrap_add_socket_info(si);
2131 1065365 : if (idx == -1) {
2132 0 : return -1;
2133 : }
2134 :
2135 1065365 : set_socket_info_index(fd, idx);
2136 :
2137 1065365 : return idx;
2138 : }
2139 :
2140 222755 : static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2141 : {
2142 : unsigned int iface;
2143 : unsigned int prt;
2144 : const char *p;
2145 : char type;
2146 :
2147 222755 : p = strrchr(un->sun_path, '/');
2148 222755 : if (p) p++; else p = un->sun_path;
2149 :
2150 222755 : if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2151 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2152 : un->sun_path, p);
2153 0 : errno = EINVAL;
2154 0 : return -1;
2155 : }
2156 :
2157 222755 : if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2158 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2159 : type, iface, prt);
2160 0 : errno = EINVAL;
2161 0 : return -1;
2162 : }
2163 :
2164 222755 : if (prt > 0xFFFF) {
2165 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2166 : type, iface, prt);
2167 0 : errno = EINVAL;
2168 0 : return -1;
2169 : }
2170 :
2171 222755 : SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2172 : type, iface, prt);
2173 :
2174 222755 : switch(type) {
2175 222432 : case SOCKET_TYPE_CHAR_TCP:
2176 : case SOCKET_TYPE_CHAR_UDP: {
2177 222432 : struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2178 :
2179 222432 : if ((*len) < sizeof(*in2)) {
2180 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
2181 : "V4: *len(%zu) < sizeof(*in2)=%zu",
2182 : (size_t)*len, sizeof(*in2));
2183 0 : errno = EINVAL;
2184 0 : return -1;
2185 : }
2186 :
2187 222432 : memset(in2, 0, sizeof(*in2));
2188 222432 : in2->sin_family = AF_INET;
2189 222432 : in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2190 222432 : in2->sin_port = htons(prt);
2191 :
2192 222432 : *len = sizeof(*in2);
2193 222432 : break;
2194 : }
2195 : #ifdef HAVE_IPV6
2196 323 : case SOCKET_TYPE_CHAR_TCP_V6:
2197 : case SOCKET_TYPE_CHAR_UDP_V6: {
2198 323 : struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2199 :
2200 323 : if ((*len) < sizeof(*in2)) {
2201 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
2202 : "V6: *len(%zu) < sizeof(*in2)=%zu",
2203 : (size_t)*len, sizeof(*in2));
2204 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2205 0 : errno = EINVAL;
2206 0 : return -1;
2207 : }
2208 :
2209 323 : memset(in2, 0, sizeof(*in2));
2210 323 : in2->sin6_family = AF_INET6;
2211 323 : in2->sin6_addr = *swrap_ipv6();
2212 323 : in2->sin6_addr.s6_addr[15] = iface;
2213 323 : in2->sin6_port = htons(prt);
2214 :
2215 323 : *len = sizeof(*in2);
2216 323 : break;
2217 : }
2218 : #endif
2219 0 : default:
2220 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2221 : type, iface, prt);
2222 0 : errno = EINVAL;
2223 0 : return -1;
2224 : }
2225 :
2226 222755 : return 0;
2227 : }
2228 :
2229 13257653 : static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2230 : int *bcast)
2231 : {
2232 13257653 : char type = '\0';
2233 : unsigned int prt;
2234 : unsigned int iface;
2235 13257653 : int is_bcast = 0;
2236 13257653 : char *swrap_dir = NULL;
2237 :
2238 13257653 : if (bcast) *bcast = 0;
2239 :
2240 13257653 : switch (inaddr->sa_family) {
2241 13257152 : case AF_INET: {
2242 13257152 : const struct sockaddr_in *in =
2243 : (const struct sockaddr_in *)(const void *)inaddr;
2244 13257152 : unsigned int addr = ntohl(in->sin_addr.s_addr);
2245 13257152 : char u_type = '\0';
2246 13257152 : char b_type = '\0';
2247 13257152 : char a_type = '\0';
2248 13257152 : const unsigned int sw_net_addr = swrap_ipv4_net();
2249 13257152 : const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2250 :
2251 13257152 : switch (si->type) {
2252 100742 : case SOCK_STREAM:
2253 100742 : u_type = SOCKET_TYPE_CHAR_TCP;
2254 100742 : break;
2255 13156410 : case SOCK_DGRAM:
2256 13156410 : u_type = SOCKET_TYPE_CHAR_UDP;
2257 13156410 : a_type = SOCKET_TYPE_CHAR_UDP;
2258 13156410 : b_type = SOCKET_TYPE_CHAR_UDP;
2259 13156410 : break;
2260 0 : default:
2261 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2262 0 : errno = ESOCKTNOSUPPORT;
2263 0 : return -1;
2264 : }
2265 :
2266 13257152 : prt = ntohs(in->sin_port);
2267 13257152 : if (a_type && addr == 0xFFFFFFFF) {
2268 : /* 255.255.255.255 only udp */
2269 0 : is_bcast = 2;
2270 0 : type = a_type;
2271 0 : iface = socket_wrapper_default_iface();
2272 13257152 : } else if (b_type && addr == sw_bcast_addr) {
2273 : /*
2274 : * 127.255.255.255
2275 : * or
2276 : * 10.255.255.255
2277 : * only udp
2278 : */
2279 3012 : is_bcast = 1;
2280 3012 : type = b_type;
2281 3012 : iface = socket_wrapper_default_iface();
2282 13254140 : } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2283 : /* 127.0.0.X or 10.53.57.X */
2284 13247594 : is_bcast = 0;
2285 13247594 : type = u_type;
2286 13247594 : iface = (addr & 0x000000FF);
2287 : } else {
2288 6546 : struct swrap_sockaddr_buf buf = {};
2289 6546 : SWRAP_LOG(SWRAP_LOG_WARN,
2290 : "%s",
2291 : swrap_sockaddr_string(&buf, inaddr));
2292 6546 : errno = ENETUNREACH;
2293 6546 : return -1;
2294 : }
2295 13250606 : if (bcast) *bcast = is_bcast;
2296 13250606 : break;
2297 : }
2298 : #ifdef HAVE_IPV6
2299 501 : case AF_INET6: {
2300 501 : const struct sockaddr_in6 *in =
2301 : (const struct sockaddr_in6 *)(const void *)inaddr;
2302 : struct in6_addr cmp1, cmp2;
2303 :
2304 501 : switch (si->type) {
2305 96 : case SOCK_STREAM:
2306 96 : type = SOCKET_TYPE_CHAR_TCP_V6;
2307 96 : break;
2308 405 : case SOCK_DGRAM:
2309 405 : type = SOCKET_TYPE_CHAR_UDP_V6;
2310 405 : break;
2311 0 : default:
2312 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2313 0 : errno = ESOCKTNOSUPPORT;
2314 0 : return -1;
2315 : }
2316 :
2317 : /* XXX no multicast/broadcast */
2318 :
2319 501 : prt = ntohs(in->sin6_port);
2320 :
2321 501 : cmp1 = *swrap_ipv6();
2322 501 : cmp2 = in->sin6_addr;
2323 501 : cmp2.s6_addr[15] = 0;
2324 501 : if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2325 501 : iface = in->sin6_addr.s6_addr[15];
2326 : } else {
2327 0 : struct swrap_sockaddr_buf buf = {};
2328 0 : SWRAP_LOG(SWRAP_LOG_WARN,
2329 : "%s",
2330 : swrap_sockaddr_string(&buf, inaddr));
2331 0 : errno = ENETUNREACH;
2332 0 : return -1;
2333 : }
2334 :
2335 501 : break;
2336 : }
2337 : #endif
2338 0 : default:
2339 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2340 0 : errno = ENETUNREACH;
2341 0 : return -1;
2342 : }
2343 :
2344 13251107 : if (prt == 0) {
2345 0 : SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2346 0 : errno = EINVAL;
2347 0 : return -1;
2348 : }
2349 :
2350 13251107 : swrap_dir = socket_wrapper_dir();
2351 13251107 : if (swrap_dir == NULL) {
2352 0 : errno = EINVAL;
2353 0 : return -1;
2354 : }
2355 :
2356 13251107 : if (is_bcast) {
2357 3012 : swrap_un_path_EINVAL(un, swrap_dir);
2358 3012 : SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2359 3012 : SAFE_FREE(swrap_dir);
2360 : /* the caller need to do more processing */
2361 3012 : return 0;
2362 : }
2363 :
2364 13248095 : swrap_un_path(un, swrap_dir, type, iface, prt);
2365 13248095 : SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2366 :
2367 13248095 : SAFE_FREE(swrap_dir);
2368 :
2369 13248095 : return 0;
2370 : }
2371 :
2372 3836 : static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2373 : int *bcast)
2374 : {
2375 3836 : char type = '\0';
2376 : unsigned int prt;
2377 : unsigned int iface;
2378 : struct stat st;
2379 3836 : int is_bcast = 0;
2380 3836 : char *swrap_dir = NULL;
2381 :
2382 3836 : if (bcast) *bcast = 0;
2383 :
2384 3836 : switch (si->family) {
2385 2747 : case AF_INET: {
2386 2747 : const struct sockaddr_in *in =
2387 : (const struct sockaddr_in *)(const void *)inaddr;
2388 2747 : unsigned int addr = ntohl(in->sin_addr.s_addr);
2389 2747 : char u_type = '\0';
2390 2747 : char d_type = '\0';
2391 2747 : char b_type = '\0';
2392 2747 : char a_type = '\0';
2393 2747 : const unsigned int sw_net_addr = swrap_ipv4_net();
2394 2747 : const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2395 :
2396 2747 : prt = ntohs(in->sin_port);
2397 :
2398 2747 : switch (si->type) {
2399 1655 : case SOCK_STREAM:
2400 1655 : u_type = SOCKET_TYPE_CHAR_TCP;
2401 1655 : d_type = SOCKET_TYPE_CHAR_TCP;
2402 1655 : break;
2403 1092 : case SOCK_DGRAM:
2404 1092 : u_type = SOCKET_TYPE_CHAR_UDP;
2405 1092 : d_type = SOCKET_TYPE_CHAR_UDP;
2406 1092 : a_type = SOCKET_TYPE_CHAR_UDP;
2407 1092 : b_type = SOCKET_TYPE_CHAR_UDP;
2408 1092 : break;
2409 0 : default:
2410 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2411 0 : errno = ESOCKTNOSUPPORT;
2412 0 : return -1;
2413 : }
2414 :
2415 2747 : if (addr == 0) {
2416 : /* 0.0.0.0 */
2417 1150 : is_bcast = 0;
2418 1150 : type = d_type;
2419 1150 : iface = socket_wrapper_default_iface();
2420 1597 : } else if (a_type && addr == 0xFFFFFFFF) {
2421 : /* 255.255.255.255 only udp */
2422 0 : is_bcast = 2;
2423 0 : type = a_type;
2424 0 : iface = socket_wrapper_default_iface();
2425 1597 : } else if (b_type && addr == sw_bcast_addr) {
2426 : /* 127.255.255.255 only udp */
2427 156 : is_bcast = 1;
2428 156 : type = b_type;
2429 156 : iface = socket_wrapper_default_iface();
2430 1441 : } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2431 : /* 127.0.0.X */
2432 1441 : is_bcast = 0;
2433 1441 : type = u_type;
2434 1441 : iface = (addr & 0x000000FF);
2435 : } else {
2436 0 : errno = EADDRNOTAVAIL;
2437 0 : return -1;
2438 : }
2439 :
2440 : /* Store the bind address for connect() */
2441 2747 : if (si->bindname.sa_socklen == 0) {
2442 : struct sockaddr_in bind_in;
2443 2747 : socklen_t blen = sizeof(struct sockaddr_in);
2444 :
2445 2747 : ZERO_STRUCT(bind_in);
2446 2747 : bind_in.sin_family = in->sin_family;
2447 2747 : bind_in.sin_port = in->sin_port;
2448 2747 : bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2449 2747 : si->bindname.sa_socklen = blen;
2450 2747 : memcpy(&si->bindname.sa.in, &bind_in, blen);
2451 : }
2452 :
2453 2747 : break;
2454 : }
2455 : #ifdef HAVE_IPV6
2456 1089 : case AF_INET6: {
2457 1089 : const struct sockaddr_in6 *in =
2458 : (const struct sockaddr_in6 *)(const void *)inaddr;
2459 : struct in6_addr cmp1, cmp2;
2460 :
2461 1089 : switch (si->type) {
2462 716 : case SOCK_STREAM:
2463 716 : type = SOCKET_TYPE_CHAR_TCP_V6;
2464 716 : break;
2465 373 : case SOCK_DGRAM:
2466 373 : type = SOCKET_TYPE_CHAR_UDP_V6;
2467 373 : break;
2468 0 : default:
2469 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2470 0 : errno = ESOCKTNOSUPPORT;
2471 142 : return -1;
2472 : }
2473 :
2474 : /* XXX no multicast/broadcast */
2475 :
2476 1089 : prt = ntohs(in->sin6_port);
2477 :
2478 1089 : cmp1 = *swrap_ipv6();
2479 1089 : cmp2 = in->sin6_addr;
2480 1089 : cmp2.s6_addr[15] = 0;
2481 1089 : if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2482 717 : iface = socket_wrapper_default_iface();
2483 372 : } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2484 230 : iface = in->sin6_addr.s6_addr[15];
2485 : } else {
2486 142 : errno = EADDRNOTAVAIL;
2487 142 : return -1;
2488 : }
2489 :
2490 : /* Store the bind address for connect() */
2491 947 : if (si->bindname.sa_socklen == 0) {
2492 : struct sockaddr_in6 bind_in;
2493 947 : socklen_t blen = sizeof(struct sockaddr_in6);
2494 :
2495 947 : ZERO_STRUCT(bind_in);
2496 947 : bind_in.sin6_family = in->sin6_family;
2497 947 : bind_in.sin6_port = in->sin6_port;
2498 :
2499 947 : bind_in.sin6_addr = *swrap_ipv6();
2500 947 : bind_in.sin6_addr.s6_addr[15] = iface;
2501 :
2502 947 : memcpy(&si->bindname.sa.in6, &bind_in, blen);
2503 947 : si->bindname.sa_socklen = blen;
2504 : }
2505 :
2506 947 : break;
2507 : }
2508 : #endif
2509 0 : default:
2510 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2511 0 : errno = EADDRNOTAVAIL;
2512 0 : return -1;
2513 : }
2514 :
2515 :
2516 3694 : if (bcast) *bcast = is_bcast;
2517 :
2518 3694 : if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2519 0 : errno = EINVAL;
2520 0 : return -1;
2521 : }
2522 :
2523 3694 : swrap_dir = socket_wrapper_dir();
2524 3694 : if (swrap_dir == NULL) {
2525 0 : errno = EINVAL;
2526 0 : return -1;
2527 : }
2528 :
2529 3694 : if (prt == 0) {
2530 : /* handle auto-allocation of ephemeral ports */
2531 325343 : for (prt = 5001; prt < 10000; prt++) {
2532 325343 : swrap_un_path(un, swrap_dir, type, iface, prt);
2533 325343 : if (stat(un->sun_path, &st) == 0) continue;
2534 :
2535 1222 : set_port(si->family, prt, &si->myname);
2536 1222 : set_port(si->family, prt, &si->bindname);
2537 :
2538 1222 : break;
2539 : }
2540 :
2541 1222 : if (prt == 10000) {
2542 0 : errno = ENFILE;
2543 0 : SAFE_FREE(swrap_dir);
2544 0 : return -1;
2545 : }
2546 : }
2547 :
2548 3694 : swrap_un_path(un, swrap_dir, type, iface, prt);
2549 3694 : SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2550 :
2551 3694 : SAFE_FREE(swrap_dir);
2552 :
2553 3694 : return 0;
2554 : }
2555 :
2556 46140070 : static struct socket_info *find_socket_info(int fd)
2557 : {
2558 46140070 : int idx = find_socket_info_index(fd);
2559 :
2560 46140070 : if (idx == -1) {
2561 8198438 : return NULL;
2562 : }
2563 :
2564 37941632 : return swrap_get_socket_info(idx);
2565 : }
2566 :
2567 : #if 0 /* FIXME */
2568 : static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2569 : {
2570 : struct socket_info_fd *f;
2571 : const struct socket_info *last_s = NULL;
2572 :
2573 : /* first catch invalid input */
2574 : switch (sa->sa_family) {
2575 : case AF_INET:
2576 : if (len < sizeof(struct sockaddr_in)) {
2577 : return false;
2578 : }
2579 : break;
2580 : #ifdef HAVE_IPV6
2581 : case AF_INET6:
2582 : if (len < sizeof(struct sockaddr_in6)) {
2583 : return false;
2584 : }
2585 : break;
2586 : #endif
2587 : default:
2588 : return false;
2589 : break;
2590 : }
2591 :
2592 : for (f = socket_fds; f; f = f->next) {
2593 : struct socket_info *s = swrap_get_socket_info(f->si_index);
2594 :
2595 : if (s == last_s) {
2596 : continue;
2597 : }
2598 : last_s = s;
2599 :
2600 : if (s->myname == NULL) {
2601 : continue;
2602 : }
2603 : if (s->myname->sa_family != sa->sa_family) {
2604 : continue;
2605 : }
2606 : switch (s->myname->sa_family) {
2607 : case AF_INET: {
2608 : struct sockaddr_in *sin1, *sin2;
2609 :
2610 : sin1 = (struct sockaddr_in *)s->myname;
2611 : sin2 = (struct sockaddr_in *)sa;
2612 :
2613 : if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2614 : continue;
2615 : }
2616 : if (sin1->sin_port != sin2->sin_port) {
2617 : continue;
2618 : }
2619 : if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2620 : continue;
2621 : }
2622 :
2623 : /* found */
2624 : return true;
2625 : break;
2626 : }
2627 : #ifdef HAVE_IPV6
2628 : case AF_INET6: {
2629 : struct sockaddr_in6 *sin1, *sin2;
2630 :
2631 : sin1 = (struct sockaddr_in6 *)s->myname;
2632 : sin2 = (struct sockaddr_in6 *)sa;
2633 :
2634 : if (sin1->sin6_port != sin2->sin6_port) {
2635 : continue;
2636 : }
2637 : if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2638 : &sin2->sin6_addr))
2639 : {
2640 : continue;
2641 : }
2642 :
2643 : /* found */
2644 : return true;
2645 : break;
2646 : }
2647 : #endif
2648 : default:
2649 : continue;
2650 : break;
2651 :
2652 : }
2653 : }
2654 :
2655 : return false;
2656 : }
2657 : #endif
2658 :
2659 : static void swrap_remove_stale(int fd);
2660 :
2661 13261489 : static int sockaddr_convert_to_un(struct socket_info *si,
2662 : const struct sockaddr *in_addr,
2663 : socklen_t in_len,
2664 : struct sockaddr_un *out_addr,
2665 : int alloc_sock,
2666 : int *bcast)
2667 : {
2668 13261489 : struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2669 :
2670 : (void) in_len; /* unused */
2671 :
2672 13261489 : if (out_addr == NULL) {
2673 0 : return 0;
2674 : }
2675 :
2676 13261489 : out->sa_family = AF_UNIX;
2677 : #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2678 : out->sa_len = sizeof(*out_addr);
2679 : #endif
2680 :
2681 13261489 : switch (in_addr->sa_family) {
2682 0 : case AF_UNSPEC: {
2683 : const struct sockaddr_in *sin;
2684 0 : if (si->family != AF_INET) {
2685 0 : break;
2686 : }
2687 0 : if (in_len < sizeof(struct sockaddr_in)) {
2688 0 : break;
2689 : }
2690 0 : sin = (const struct sockaddr_in *)(const void *)in_addr;
2691 0 : if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2692 0 : break;
2693 : }
2694 :
2695 : /*
2696 : * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2697 : * AF_UNSPEC is mapped to AF_INET and must be treated here.
2698 : */
2699 :
2700 : FALL_THROUGH;
2701 : }
2702 : case AF_INET:
2703 : #ifdef HAVE_IPV6
2704 : case AF_INET6:
2705 : #endif
2706 13261489 : switch (si->type) {
2707 13261489 : case SOCK_STREAM:
2708 : case SOCK_DGRAM:
2709 13261489 : break;
2710 0 : default:
2711 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2712 0 : errno = ESOCKTNOSUPPORT;
2713 0 : return -1;
2714 : }
2715 13261489 : if (alloc_sock) {
2716 3836 : return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2717 : } else {
2718 13257653 : return convert_in_un_remote(si, in_addr, out_addr, bcast);
2719 : }
2720 0 : default:
2721 0 : break;
2722 : }
2723 :
2724 0 : errno = EAFNOSUPPORT;
2725 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2726 0 : return -1;
2727 : }
2728 :
2729 222755 : static int sockaddr_convert_from_un(const struct socket_info *si,
2730 : const struct sockaddr_un *in_addr,
2731 : socklen_t un_addrlen,
2732 : int family,
2733 : struct sockaddr *out_addr,
2734 : socklen_t *out_addrlen)
2735 : {
2736 : int ret;
2737 :
2738 222755 : if (out_addr == NULL || out_addrlen == NULL)
2739 0 : return 0;
2740 :
2741 222755 : if (un_addrlen == 0) {
2742 0 : *out_addrlen = 0;
2743 0 : return 0;
2744 : }
2745 :
2746 222755 : switch (family) {
2747 222755 : case AF_INET:
2748 : #ifdef HAVE_IPV6
2749 : case AF_INET6:
2750 : #endif
2751 222755 : switch (si->type) {
2752 222755 : case SOCK_STREAM:
2753 : case SOCK_DGRAM:
2754 222755 : break;
2755 0 : default:
2756 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2757 0 : errno = ESOCKTNOSUPPORT;
2758 0 : return -1;
2759 : }
2760 222755 : ret = convert_un_in(in_addr, out_addr, out_addrlen);
2761 : #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2762 : out_addr->sa_len = *out_addrlen;
2763 : #endif
2764 222755 : return ret;
2765 0 : default:
2766 0 : break;
2767 : }
2768 :
2769 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2770 0 : errno = EAFNOSUPPORT;
2771 0 : return -1;
2772 : }
2773 :
2774 : enum swrap_packet_type {
2775 : SWRAP_CONNECT_SEND,
2776 : SWRAP_CONNECT_UNREACH,
2777 : SWRAP_CONNECT_RECV,
2778 : SWRAP_CONNECT_ACK,
2779 : SWRAP_ACCEPT_SEND,
2780 : SWRAP_ACCEPT_RECV,
2781 : SWRAP_ACCEPT_ACK,
2782 : SWRAP_RECVFROM,
2783 : SWRAP_SENDTO,
2784 : SWRAP_SENDTO_UNREACH,
2785 : SWRAP_PENDING_RST,
2786 : SWRAP_RECV,
2787 : SWRAP_RECV_RST,
2788 : SWRAP_SEND,
2789 : SWRAP_SEND_RST,
2790 : SWRAP_CLOSE_SEND,
2791 : SWRAP_CLOSE_RECV,
2792 : SWRAP_CLOSE_ACK,
2793 : };
2794 :
2795 : struct swrap_file_hdr {
2796 : uint32_t magic;
2797 : uint16_t version_major;
2798 : uint16_t version_minor;
2799 : int32_t timezone;
2800 : uint32_t sigfigs;
2801 : uint32_t frame_max_len;
2802 : #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2803 : uint32_t link_type;
2804 : };
2805 : #define SWRAP_FILE_HDR_SIZE 24
2806 :
2807 : struct swrap_packet_frame {
2808 : uint32_t seconds;
2809 : uint32_t micro_seconds;
2810 : uint32_t recorded_length;
2811 : uint32_t full_length;
2812 : };
2813 : #define SWRAP_PACKET_FRAME_SIZE 16
2814 :
2815 : union swrap_packet_ip {
2816 : struct {
2817 : uint8_t ver_hdrlen;
2818 : uint8_t tos;
2819 : uint16_t packet_length;
2820 : uint16_t identification;
2821 : uint8_t flags;
2822 : uint8_t fragment;
2823 : uint8_t ttl;
2824 : uint8_t protocol;
2825 : uint16_t hdr_checksum;
2826 : uint32_t src_addr;
2827 : uint32_t dest_addr;
2828 : } v4;
2829 : #define SWRAP_PACKET_IP_V4_SIZE 20
2830 : struct {
2831 : uint8_t ver_prio;
2832 : uint8_t flow_label_high;
2833 : uint16_t flow_label_low;
2834 : uint16_t payload_length;
2835 : uint8_t next_header;
2836 : uint8_t hop_limit;
2837 : uint8_t src_addr[16];
2838 : uint8_t dest_addr[16];
2839 : } v6;
2840 : #define SWRAP_PACKET_IP_V6_SIZE 40
2841 : };
2842 : #define SWRAP_PACKET_IP_SIZE 40
2843 :
2844 : union swrap_packet_payload {
2845 : struct {
2846 : uint16_t source_port;
2847 : uint16_t dest_port;
2848 : uint32_t seq_num;
2849 : uint32_t ack_num;
2850 : uint8_t hdr_length;
2851 : uint8_t control;
2852 : uint16_t window;
2853 : uint16_t checksum;
2854 : uint16_t urg;
2855 : } tcp;
2856 : #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2857 : struct {
2858 : uint16_t source_port;
2859 : uint16_t dest_port;
2860 : uint16_t length;
2861 : uint16_t checksum;
2862 : } udp;
2863 : #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2864 : struct {
2865 : uint8_t type;
2866 : uint8_t code;
2867 : uint16_t checksum;
2868 : uint32_t unused;
2869 : } icmp4;
2870 : #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2871 : struct {
2872 : uint8_t type;
2873 : uint8_t code;
2874 : uint16_t checksum;
2875 : uint32_t unused;
2876 : } icmp6;
2877 : #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2878 : };
2879 : #define SWRAP_PACKET_PAYLOAD_SIZE 20
2880 :
2881 : #define SWRAP_PACKET_MIN_ALLOC \
2882 : (SWRAP_PACKET_FRAME_SIZE + \
2883 : SWRAP_PACKET_IP_SIZE + \
2884 : SWRAP_PACKET_PAYLOAD_SIZE)
2885 :
2886 23855461 : static const char *swrap_pcap_init_file(void)
2887 : {
2888 : static int initialized = 0;
2889 : static const char *s = NULL;
2890 : static const struct swrap_file_hdr h;
2891 : static const struct swrap_packet_frame f;
2892 : static const union swrap_packet_ip i;
2893 : static const union swrap_packet_payload p;
2894 :
2895 23855461 : if (initialized == 1) {
2896 23849153 : return s;
2897 : }
2898 6308 : initialized = 1;
2899 :
2900 : /*
2901 : * TODO: don't use the structs use plain buffer offsets
2902 : * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2903 : *
2904 : * for now make sure we disable PCAP support
2905 : * if the struct has alignment!
2906 : */
2907 : if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2908 : return NULL;
2909 : }
2910 : if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2911 : return NULL;
2912 : }
2913 : if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2914 : return NULL;
2915 : }
2916 : if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2917 : return NULL;
2918 : }
2919 : if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2920 : return NULL;
2921 : }
2922 : if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2923 : return NULL;
2924 : }
2925 : if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2926 : return NULL;
2927 : }
2928 : if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2929 : return NULL;
2930 : }
2931 : if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2932 : return NULL;
2933 : }
2934 : if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2935 : return NULL;
2936 : }
2937 :
2938 6308 : s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2939 6308 : if (s == NULL) {
2940 33 : return NULL;
2941 : }
2942 6275 : if (strncmp(s, "./", 2) == 0) {
2943 0 : s += 2;
2944 : }
2945 6275 : SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2946 6275 : return s;
2947 : }
2948 :
2949 23703005 : static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2950 : const struct sockaddr *src,
2951 : const struct sockaddr *dest,
2952 : int socket_type,
2953 : const uint8_t *payload,
2954 : size_t payload_len,
2955 : unsigned long tcp_seqno,
2956 : unsigned long tcp_ack,
2957 : unsigned char tcp_ctl,
2958 : int unreachable,
2959 : size_t *_packet_len)
2960 : {
2961 23703005 : uint8_t *base = NULL;
2962 23703005 : uint8_t *buf = NULL;
2963 : union {
2964 : uint8_t *ptr;
2965 : struct swrap_packet_frame *frame;
2966 : } f;
2967 : union {
2968 : uint8_t *ptr;
2969 : union swrap_packet_ip *ip;
2970 : } i;
2971 : union swrap_packet_payload *pay;
2972 : size_t packet_len;
2973 : size_t alloc_len;
2974 23703005 : size_t nonwire_len = sizeof(struct swrap_packet_frame);
2975 23703005 : size_t wire_hdr_len = 0;
2976 23703005 : size_t wire_len = 0;
2977 23703005 : size_t ip_hdr_len = 0;
2978 23703005 : size_t icmp_hdr_len = 0;
2979 23703005 : size_t icmp_truncate_len = 0;
2980 23703005 : uint8_t protocol = 0, icmp_protocol = 0;
2981 23703005 : const struct sockaddr_in *src_in = NULL;
2982 23703005 : const struct sockaddr_in *dest_in = NULL;
2983 : #ifdef HAVE_IPV6
2984 23703005 : const struct sockaddr_in6 *src_in6 = NULL;
2985 23703005 : const struct sockaddr_in6 *dest_in6 = NULL;
2986 : #endif
2987 : uint16_t src_port;
2988 : uint16_t dest_port;
2989 :
2990 23703005 : switch (src->sa_family) {
2991 23695878 : case AF_INET:
2992 23695878 : src_in = (const struct sockaddr_in *)(const void *)src;
2993 23695878 : dest_in = (const struct sockaddr_in *)(const void *)dest;
2994 23695878 : src_port = src_in->sin_port;
2995 23695878 : dest_port = dest_in->sin_port;
2996 23695878 : ip_hdr_len = sizeof(i.ip->v4);
2997 23695878 : break;
2998 : #ifdef HAVE_IPV6
2999 7127 : case AF_INET6:
3000 7127 : src_in6 = (const struct sockaddr_in6 *)(const void *)src;
3001 7127 : dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
3002 7127 : src_port = src_in6->sin6_port;
3003 7127 : dest_port = dest_in6->sin6_port;
3004 7127 : ip_hdr_len = sizeof(i.ip->v6);
3005 7127 : break;
3006 : #endif
3007 0 : default:
3008 0 : return NULL;
3009 : }
3010 :
3011 23703005 : switch (socket_type) {
3012 23595327 : case SOCK_STREAM:
3013 23595327 : protocol = 0x06; /* TCP */
3014 23595327 : wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
3015 23595327 : wire_len = wire_hdr_len + payload_len;
3016 23595327 : break;
3017 :
3018 107678 : case SOCK_DGRAM:
3019 107678 : protocol = 0x11; /* UDP */
3020 107678 : wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
3021 107678 : wire_len = wire_hdr_len + payload_len;
3022 107678 : break;
3023 :
3024 0 : default:
3025 0 : return NULL;
3026 : }
3027 :
3028 23703005 : if (unreachable) {
3029 57 : icmp_protocol = protocol;
3030 57 : switch (src->sa_family) {
3031 57 : case AF_INET:
3032 57 : protocol = 0x01; /* ICMPv4 */
3033 57 : icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
3034 57 : break;
3035 : #ifdef HAVE_IPV6
3036 0 : case AF_INET6:
3037 0 : protocol = 0x3A; /* ICMPv6 */
3038 0 : icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
3039 0 : break;
3040 : #endif
3041 : }
3042 57 : if (wire_len > 64 ) {
3043 57 : icmp_truncate_len = wire_len - 64;
3044 : }
3045 57 : wire_len += icmp_hdr_len;
3046 : }
3047 :
3048 23703005 : packet_len = nonwire_len + wire_len;
3049 23703005 : alloc_len = packet_len;
3050 23703005 : if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
3051 6107631 : alloc_len = SWRAP_PACKET_MIN_ALLOC;
3052 : }
3053 :
3054 23703005 : base = (uint8_t *)calloc(1, alloc_len);
3055 23703005 : if (base == NULL) {
3056 0 : return NULL;
3057 : }
3058 :
3059 23703005 : buf = base;
3060 23703005 : f.ptr = buf;
3061 :
3062 23703005 : f.frame->seconds = tval->tv_sec;
3063 23703005 : f.frame->micro_seconds = tval->tv_usec;
3064 23703005 : f.frame->recorded_length = wire_len - icmp_truncate_len;
3065 23703005 : f.frame->full_length = wire_len - icmp_truncate_len;
3066 :
3067 23703005 : buf += SWRAP_PACKET_FRAME_SIZE;
3068 :
3069 23703005 : i.ptr = buf;
3070 23703005 : switch (src->sa_family) {
3071 23695878 : case AF_INET:
3072 23695878 : if (src_in == NULL || dest_in == NULL) {
3073 0 : SAFE_FREE(base);
3074 0 : return NULL;
3075 : }
3076 :
3077 23695878 : i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3078 23695878 : i.ip->v4.tos = 0x00;
3079 23695878 : i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3080 23695878 : i.ip->v4.identification = htons(0xFFFF);
3081 23695878 : i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3082 23695878 : i.ip->v4.fragment = htons(0x0000);
3083 23695878 : i.ip->v4.ttl = 0xFF;
3084 23695878 : i.ip->v4.protocol = protocol;
3085 23695878 : i.ip->v4.hdr_checksum = htons(0x0000);
3086 23695878 : i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3087 23695878 : i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3088 23695878 : buf += SWRAP_PACKET_IP_V4_SIZE;
3089 23695878 : break;
3090 : #ifdef HAVE_IPV6
3091 7127 : case AF_INET6:
3092 7127 : if (src_in6 == NULL || dest_in6 == NULL) {
3093 0 : SAFE_FREE(base);
3094 0 : return NULL;
3095 : }
3096 :
3097 7127 : i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3098 7127 : i.ip->v6.flow_label_high = 0x00;
3099 7127 : i.ip->v6.flow_label_low = 0x0000;
3100 7127 : i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3101 7127 : i.ip->v6.next_header = protocol;
3102 7127 : memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3103 7127 : memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3104 7127 : buf += SWRAP_PACKET_IP_V6_SIZE;
3105 7127 : break;
3106 : #endif
3107 : }
3108 :
3109 23703005 : if (unreachable) {
3110 57 : pay = (union swrap_packet_payload *)(void *)buf;
3111 57 : switch (src->sa_family) {
3112 57 : case AF_INET:
3113 57 : pay->icmp4.type = 0x03; /* destination unreachable */
3114 57 : pay->icmp4.code = 0x01; /* host unreachable */
3115 57 : pay->icmp4.checksum = htons(0x0000);
3116 57 : pay->icmp4.unused = htonl(0x00000000);
3117 :
3118 57 : buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3119 :
3120 : /* set the ip header in the ICMP payload */
3121 57 : i.ptr = buf;
3122 57 : i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3123 57 : i.ip->v4.tos = 0x00;
3124 57 : i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3125 57 : i.ip->v4.identification = htons(0xFFFF);
3126 57 : i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3127 57 : i.ip->v4.fragment = htons(0x0000);
3128 57 : i.ip->v4.ttl = 0xFF;
3129 57 : i.ip->v4.protocol = icmp_protocol;
3130 57 : i.ip->v4.hdr_checksum = htons(0x0000);
3131 57 : i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3132 57 : i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3133 :
3134 57 : buf += SWRAP_PACKET_IP_V4_SIZE;
3135 :
3136 57 : src_port = dest_in->sin_port;
3137 57 : dest_port = src_in->sin_port;
3138 57 : break;
3139 : #ifdef HAVE_IPV6
3140 0 : case AF_INET6:
3141 0 : pay->icmp6.type = 0x01; /* destination unreachable */
3142 0 : pay->icmp6.code = 0x03; /* address unreachable */
3143 0 : pay->icmp6.checksum = htons(0x0000);
3144 0 : pay->icmp6.unused = htonl(0x00000000);
3145 0 : buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3146 :
3147 : /* set the ip header in the ICMP payload */
3148 0 : i.ptr = buf;
3149 0 : i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3150 0 : i.ip->v6.flow_label_high = 0x00;
3151 0 : i.ip->v6.flow_label_low = 0x0000;
3152 0 : i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3153 0 : i.ip->v6.next_header = protocol;
3154 0 : memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3155 0 : memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3156 :
3157 0 : buf += SWRAP_PACKET_IP_V6_SIZE;
3158 :
3159 0 : src_port = dest_in6->sin6_port;
3160 0 : dest_port = src_in6->sin6_port;
3161 0 : break;
3162 : #endif
3163 : }
3164 : }
3165 :
3166 23703005 : pay = (union swrap_packet_payload *)(void *)buf;
3167 :
3168 23703005 : switch (socket_type) {
3169 23595327 : case SOCK_STREAM:
3170 23595327 : pay->tcp.source_port = src_port;
3171 23595327 : pay->tcp.dest_port = dest_port;
3172 23595327 : pay->tcp.seq_num = htonl(tcp_seqno);
3173 23595327 : pay->tcp.ack_num = htonl(tcp_ack);
3174 23595327 : pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3175 23595327 : pay->tcp.control = tcp_ctl;
3176 23595327 : pay->tcp.window = htons(0x7FFF);
3177 23595327 : pay->tcp.checksum = htons(0x0000);
3178 23595327 : pay->tcp.urg = htons(0x0000);
3179 23595327 : buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3180 :
3181 23595327 : break;
3182 :
3183 107678 : case SOCK_DGRAM:
3184 107678 : pay->udp.source_port = src_port;
3185 107678 : pay->udp.dest_port = dest_port;
3186 107678 : pay->udp.length = htons(8 + payload_len);
3187 107678 : pay->udp.checksum = htons(0x0000);
3188 107678 : buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3189 :
3190 107678 : break;
3191 : }
3192 :
3193 23703005 : if (payload && payload_len > 0) {
3194 22400876 : memcpy(buf, payload, payload_len);
3195 : }
3196 :
3197 23703005 : *_packet_len = packet_len - icmp_truncate_len;
3198 23703005 : return base;
3199 : }
3200 :
3201 23703005 : static int swrap_pcap_get_fd(const char *fname)
3202 : {
3203 : static int fd = -1;
3204 :
3205 23703005 : if (fd != -1) {
3206 0 : return fd;
3207 : }
3208 :
3209 23703005 : fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3210 23703005 : if (fd != -1) {
3211 : struct swrap_file_hdr file_hdr;
3212 0 : file_hdr.magic = 0xA1B2C3D4;
3213 0 : file_hdr.version_major = 0x0002;
3214 0 : file_hdr.version_minor = 0x0004;
3215 0 : file_hdr.timezone = 0x00000000;
3216 0 : file_hdr.sigfigs = 0x00000000;
3217 0 : file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3218 0 : file_hdr.link_type = 0x0065; /* 101 RAW IP */
3219 :
3220 0 : if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3221 0 : libc_close(fd);
3222 0 : fd = -1;
3223 : }
3224 0 : return fd;
3225 : }
3226 :
3227 23703005 : fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3228 :
3229 23703005 : return fd;
3230 : }
3231 :
3232 23813058 : static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3233 : const struct sockaddr *addr,
3234 : enum swrap_packet_type type,
3235 : const void *buf, size_t len,
3236 : size_t *packet_len)
3237 : {
3238 : const struct sockaddr *src_addr;
3239 : const struct sockaddr *dest_addr;
3240 23813058 : unsigned long tcp_seqno = 0;
3241 23813058 : unsigned long tcp_ack = 0;
3242 23813058 : unsigned char tcp_ctl = 0;
3243 23813058 : int unreachable = 0;
3244 :
3245 : struct timeval tv;
3246 :
3247 23813058 : switch (si->family) {
3248 23805231 : case AF_INET:
3249 23805231 : break;
3250 : #ifdef HAVE_IPV6
3251 7827 : case AF_INET6:
3252 7827 : break;
3253 : #endif
3254 0 : default:
3255 0 : return NULL;
3256 : }
3257 :
3258 23813058 : switch (type) {
3259 100836 : case SWRAP_CONNECT_SEND:
3260 100836 : if (si->type != SOCK_STREAM) {
3261 0 : return NULL;
3262 : }
3263 :
3264 100836 : src_addr = &si->myname.sa.s;
3265 100836 : dest_addr = addr;
3266 :
3267 100836 : tcp_seqno = si->io.pck_snd;
3268 100836 : tcp_ack = si->io.pck_rcv;
3269 100836 : tcp_ctl = 0x02; /* SYN */
3270 :
3271 100836 : si->io.pck_snd += 1;
3272 :
3273 100836 : break;
3274 :
3275 122447 : case SWRAP_CONNECT_RECV:
3276 122447 : if (si->type != SOCK_STREAM) {
3277 21611 : return NULL;
3278 : }
3279 :
3280 100836 : dest_addr = &si->myname.sa.s;
3281 100836 : src_addr = addr;
3282 :
3283 100836 : tcp_seqno = si->io.pck_rcv;
3284 100836 : tcp_ack = si->io.pck_snd;
3285 100836 : tcp_ctl = 0x12; /** SYN,ACK */
3286 :
3287 100836 : si->io.pck_rcv += 1;
3288 :
3289 100836 : break;
3290 :
3291 0 : case SWRAP_CONNECT_UNREACH:
3292 0 : if (si->type != SOCK_STREAM) {
3293 0 : return NULL;
3294 : }
3295 :
3296 0 : dest_addr = &si->myname.sa.s;
3297 0 : src_addr = addr;
3298 :
3299 : /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3300 0 : tcp_seqno = si->io.pck_snd - 1;
3301 0 : tcp_ack = si->io.pck_rcv;
3302 0 : tcp_ctl = 0x02; /* SYN */
3303 0 : unreachable = 1;
3304 :
3305 0 : break;
3306 :
3307 122447 : case SWRAP_CONNECT_ACK:
3308 122447 : if (si->type != SOCK_STREAM) {
3309 21611 : return NULL;
3310 : }
3311 :
3312 100836 : src_addr = &si->myname.sa.s;
3313 100836 : dest_addr = addr;
3314 :
3315 100836 : tcp_seqno = si->io.pck_snd;
3316 100836 : tcp_ack = si->io.pck_rcv;
3317 100836 : tcp_ctl = 0x10; /* ACK */
3318 :
3319 100836 : break;
3320 :
3321 90332 : case SWRAP_ACCEPT_SEND:
3322 90332 : if (si->type != SOCK_STREAM) {
3323 0 : return NULL;
3324 : }
3325 :
3326 90332 : dest_addr = &si->myname.sa.s;
3327 90332 : src_addr = addr;
3328 :
3329 90332 : tcp_seqno = si->io.pck_rcv;
3330 90332 : tcp_ack = si->io.pck_snd;
3331 90332 : tcp_ctl = 0x02; /* SYN */
3332 :
3333 90332 : si->io.pck_rcv += 1;
3334 :
3335 90332 : break;
3336 :
3337 90332 : case SWRAP_ACCEPT_RECV:
3338 90332 : if (si->type != SOCK_STREAM) {
3339 0 : return NULL;
3340 : }
3341 :
3342 90332 : src_addr = &si->myname.sa.s;
3343 90332 : dest_addr = addr;
3344 :
3345 90332 : tcp_seqno = si->io.pck_snd;
3346 90332 : tcp_ack = si->io.pck_rcv;
3347 90332 : tcp_ctl = 0x12; /* SYN,ACK */
3348 :
3349 90332 : si->io.pck_snd += 1;
3350 :
3351 90332 : break;
3352 :
3353 90332 : case SWRAP_ACCEPT_ACK:
3354 90332 : if (si->type != SOCK_STREAM) {
3355 0 : return NULL;
3356 : }
3357 :
3358 90332 : dest_addr = &si->myname.sa.s;
3359 90332 : src_addr = addr;
3360 :
3361 90332 : tcp_seqno = si->io.pck_rcv;
3362 90332 : tcp_ack = si->io.pck_snd;
3363 90332 : tcp_ctl = 0x10; /* ACK */
3364 :
3365 90332 : break;
3366 :
3367 8683670 : case SWRAP_SEND:
3368 8683670 : src_addr = &si->myname.sa.s;
3369 8683670 : dest_addr = &si->peername.sa.s;
3370 :
3371 8683670 : tcp_seqno = si->io.pck_snd;
3372 8683670 : tcp_ack = si->io.pck_rcv;
3373 8683670 : tcp_ctl = 0x18; /* PSH,ACK */
3374 :
3375 8683670 : si->io.pck_snd += len;
3376 :
3377 8683670 : break;
3378 :
3379 2955 : case SWRAP_SEND_RST:
3380 2955 : dest_addr = &si->myname.sa.s;
3381 2955 : src_addr = &si->peername.sa.s;
3382 :
3383 2955 : if (si->type == SOCK_DGRAM) {
3384 0 : return swrap_pcap_marshall_packet(si,
3385 0 : &si->peername.sa.s,
3386 : SWRAP_SENDTO_UNREACH,
3387 : buf,
3388 : len,
3389 : packet_len);
3390 : }
3391 :
3392 2955 : tcp_seqno = si->io.pck_rcv;
3393 2955 : tcp_ack = si->io.pck_snd;
3394 2955 : tcp_ctl = 0x14; /** RST,ACK */
3395 :
3396 2955 : break;
3397 :
3398 2082 : case SWRAP_PENDING_RST:
3399 2082 : dest_addr = &si->myname.sa.s;
3400 2082 : src_addr = &si->peername.sa.s;
3401 :
3402 2082 : if (si->type == SOCK_DGRAM) {
3403 2082 : return NULL;
3404 : }
3405 :
3406 0 : tcp_seqno = si->io.pck_rcv;
3407 0 : tcp_ack = si->io.pck_snd;
3408 0 : tcp_ctl = 0x14; /* RST,ACK */
3409 :
3410 0 : break;
3411 :
3412 13629059 : case SWRAP_RECV:
3413 13629059 : dest_addr = &si->myname.sa.s;
3414 13629059 : src_addr = &si->peername.sa.s;
3415 :
3416 13629059 : tcp_seqno = si->io.pck_rcv;
3417 13629059 : tcp_ack = si->io.pck_snd;
3418 13629059 : tcp_ctl = 0x18; /* PSH,ACK */
3419 :
3420 13629059 : si->io.pck_rcv += len;
3421 :
3422 13629059 : break;
3423 :
3424 91589 : case SWRAP_RECV_RST:
3425 91589 : dest_addr = &si->myname.sa.s;
3426 91589 : src_addr = &si->peername.sa.s;
3427 :
3428 91589 : if (si->type == SOCK_DGRAM) {
3429 0 : return NULL;
3430 : }
3431 :
3432 91589 : tcp_seqno = si->io.pck_rcv;
3433 91589 : tcp_ack = si->io.pck_snd;
3434 91589 : tcp_ctl = 0x14; /* RST,ACK */
3435 :
3436 91589 : break;
3437 :
3438 48308 : case SWRAP_SENDTO:
3439 48308 : src_addr = &si->myname.sa.s;
3440 48308 : dest_addr = addr;
3441 :
3442 48308 : si->io.pck_snd += len;
3443 :
3444 48308 : break;
3445 :
3446 57 : case SWRAP_SENDTO_UNREACH:
3447 57 : dest_addr = &si->myname.sa.s;
3448 57 : src_addr = addr;
3449 :
3450 57 : unreachable = 1;
3451 :
3452 57 : break;
3453 :
3454 39786 : case SWRAP_RECVFROM:
3455 39786 : dest_addr = &si->myname.sa.s;
3456 39786 : src_addr = addr;
3457 :
3458 39786 : si->io.pck_rcv += len;
3459 :
3460 39786 : break;
3461 :
3462 232942 : case SWRAP_CLOSE_SEND:
3463 232942 : if (si->type != SOCK_STREAM) {
3464 21583 : return NULL;
3465 : }
3466 :
3467 211359 : src_addr = &si->myname.sa.s;
3468 211359 : dest_addr = &si->peername.sa.s;
3469 :
3470 211359 : tcp_seqno = si->io.pck_snd;
3471 211359 : tcp_ack = si->io.pck_rcv;
3472 211359 : tcp_ctl = 0x11; /* FIN, ACK */
3473 :
3474 211359 : si->io.pck_snd += 1;
3475 :
3476 211359 : break;
3477 :
3478 232942 : case SWRAP_CLOSE_RECV:
3479 232942 : if (si->type != SOCK_STREAM) {
3480 21583 : return NULL;
3481 : }
3482 :
3483 211359 : dest_addr = &si->myname.sa.s;
3484 211359 : src_addr = &si->peername.sa.s;
3485 :
3486 211359 : tcp_seqno = si->io.pck_rcv;
3487 211359 : tcp_ack = si->io.pck_snd;
3488 211359 : tcp_ctl = 0x11; /* FIN,ACK */
3489 :
3490 211359 : si->io.pck_rcv += 1;
3491 :
3492 211359 : break;
3493 :
3494 232942 : case SWRAP_CLOSE_ACK:
3495 232942 : if (si->type != SOCK_STREAM) {
3496 21583 : return NULL;
3497 : }
3498 :
3499 211359 : src_addr = &si->myname.sa.s;
3500 211359 : dest_addr = &si->peername.sa.s;
3501 :
3502 211359 : tcp_seqno = si->io.pck_snd;
3503 211359 : tcp_ack = si->io.pck_rcv;
3504 211359 : tcp_ctl = 0x10; /* ACK */
3505 :
3506 211359 : break;
3507 0 : default:
3508 0 : return NULL;
3509 : }
3510 :
3511 23703005 : swrapGetTimeOfDay(&tv);
3512 :
3513 23703005 : return swrap_pcap_packet_init(&tv,
3514 : src_addr,
3515 : dest_addr,
3516 : si->type,
3517 : (const uint8_t *)buf,
3518 : len,
3519 : tcp_seqno,
3520 : tcp_ack,
3521 : tcp_ctl,
3522 : unreachable,
3523 : packet_len);
3524 : }
3525 :
3526 23855461 : static void swrap_pcap_dump_packet(struct socket_info *si,
3527 : const struct sockaddr *addr,
3528 : enum swrap_packet_type type,
3529 : const void *buf, size_t len)
3530 : {
3531 : const char *file_name;
3532 : uint8_t *packet;
3533 23855461 : size_t packet_len = 0;
3534 : int fd;
3535 :
3536 23855461 : swrap_mutex_lock(&pcap_dump_mutex);
3537 :
3538 23855461 : file_name = swrap_pcap_init_file();
3539 23855461 : if (!file_name) {
3540 42403 : goto done;
3541 : }
3542 :
3543 23813058 : packet = swrap_pcap_marshall_packet(si,
3544 : addr,
3545 : type,
3546 : buf,
3547 : len,
3548 : &packet_len);
3549 23813058 : if (packet == NULL) {
3550 110053 : goto done;
3551 : }
3552 :
3553 23703005 : fd = swrap_pcap_get_fd(file_name);
3554 23703005 : if (fd != -1) {
3555 0 : if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3556 0 : free(packet);
3557 0 : goto done;
3558 : }
3559 : }
3560 :
3561 23703005 : free(packet);
3562 :
3563 23855461 : done:
3564 23855461 : swrap_mutex_unlock(&pcap_dump_mutex);
3565 23855461 : }
3566 :
3567 : /****************************************************************************
3568 : * SIGNALFD
3569 : ***************************************************************************/
3570 :
3571 : #ifdef HAVE_SIGNALFD
3572 0 : static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3573 : {
3574 : int rc;
3575 :
3576 0 : rc = libc_signalfd(fd, mask, flags);
3577 0 : if (rc != -1) {
3578 0 : swrap_remove_stale(fd);
3579 : }
3580 :
3581 0 : return rc;
3582 : }
3583 :
3584 : int signalfd(int fd, const sigset_t *mask, int flags)
3585 : {
3586 0 : return swrap_signalfd(fd, mask, flags);
3587 : }
3588 : #endif
3589 :
3590 : /****************************************************************************
3591 : * SOCKET
3592 : ***************************************************************************/
3593 :
3594 1028226 : static int swrap_socket(int family, int type, int protocol)
3595 : {
3596 1028226 : struct socket_info *si = NULL;
3597 1028226 : struct socket_info _si = { 0 };
3598 : int fd;
3599 : int ret;
3600 1028226 : int real_type = type;
3601 :
3602 : /*
3603 : * Remove possible addition flags passed to socket() so
3604 : * do not fail checking the type.
3605 : * See https://lwn.net/Articles/281965/
3606 : */
3607 : #ifdef SOCK_CLOEXEC
3608 1028226 : real_type &= ~SOCK_CLOEXEC;
3609 : #endif
3610 : #ifdef SOCK_NONBLOCK
3611 1028226 : real_type &= ~SOCK_NONBLOCK;
3612 : #endif
3613 :
3614 1028226 : if (!socket_wrapper_enabled()) {
3615 0 : return libc_socket(family, type, protocol);
3616 : }
3617 :
3618 1028226 : switch (family) {
3619 975033 : case AF_INET:
3620 : #ifdef HAVE_IPV6
3621 : case AF_INET6:
3622 : #endif
3623 975033 : break;
3624 : #ifdef AF_NETLINK
3625 53193 : case AF_NETLINK:
3626 : #endif /* AF_NETLINK */
3627 : #ifdef AF_PACKET
3628 : case AF_PACKET:
3629 : #endif /* AF_PACKET */
3630 : case AF_UNIX:
3631 53193 : fd = libc_socket(family, type, protocol);
3632 53193 : if (fd != -1) {
3633 : /* Check if we have a stale fd and remove it */
3634 53193 : swrap_remove_stale(fd);
3635 53193 : SWRAP_LOG(SWRAP_LOG_TRACE,
3636 : "Unix socket fd=%d",
3637 : fd);
3638 : }
3639 53193 : return fd;
3640 0 : default:
3641 0 : errno = EAFNOSUPPORT;
3642 0 : return -1;
3643 : }
3644 :
3645 975033 : switch (real_type) {
3646 102254 : case SOCK_STREAM:
3647 102254 : break;
3648 872779 : case SOCK_DGRAM:
3649 872779 : break;
3650 0 : default:
3651 0 : errno = EPROTONOSUPPORT;
3652 0 : return -1;
3653 : }
3654 :
3655 975033 : switch (protocol) {
3656 939923 : case 0:
3657 939923 : break;
3658 32913 : case 6:
3659 32913 : if (real_type == SOCK_STREAM) {
3660 32913 : break;
3661 : }
3662 : FALL_THROUGH;
3663 : case 17:
3664 2197 : if (real_type == SOCK_DGRAM) {
3665 2197 : break;
3666 : }
3667 : FALL_THROUGH;
3668 : default:
3669 0 : errno = EPROTONOSUPPORT;
3670 0 : return -1;
3671 : }
3672 :
3673 : /*
3674 : * We must call libc_socket with type, from the caller, not the version
3675 : * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3676 : */
3677 975033 : fd = libc_socket(AF_UNIX, type, 0);
3678 :
3679 975033 : if (fd == -1) {
3680 0 : return -1;
3681 : }
3682 :
3683 : /* Check if we have a stale fd and remove it */
3684 975033 : swrap_remove_stale(fd);
3685 :
3686 975033 : si = &_si;
3687 975033 : si->family = family;
3688 :
3689 : /* however, the rest of the socket_wrapper code expects just
3690 : * the type, not the flags */
3691 975033 : si->type = real_type;
3692 975033 : si->protocol = protocol;
3693 :
3694 : /*
3695 : * Setup myname so getsockname() can succeed to find out the socket
3696 : * type.
3697 : */
3698 975033 : switch(si->family) {
3699 973670 : case AF_INET: {
3700 973670 : struct sockaddr_in sin = {
3701 : .sin_family = AF_INET,
3702 : };
3703 :
3704 973670 : si->myname.sa_socklen = sizeof(struct sockaddr_in);
3705 973670 : memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3706 973670 : break;
3707 : }
3708 : #ifdef HAVE_IPV6
3709 1363 : case AF_INET6: {
3710 1363 : struct sockaddr_in6 sin6 = {
3711 : .sin6_family = AF_INET6,
3712 : };
3713 :
3714 1363 : si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3715 1363 : memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3716 1363 : break;
3717 : }
3718 : #endif
3719 0 : default:
3720 0 : errno = EINVAL;
3721 0 : return -1;
3722 : }
3723 :
3724 975033 : ret = swrap_create_socket(si, fd);
3725 975033 : if (ret == -1) {
3726 0 : int saved_errno = errno;
3727 0 : libc_close(fd);
3728 0 : errno = saved_errno;
3729 0 : return -1;
3730 : }
3731 :
3732 975033 : SWRAP_LOG(SWRAP_LOG_TRACE,
3733 : "Created %s socket for protocol %s, fd=%d",
3734 : family == AF_INET ? "IPv4" : "IPv6",
3735 : real_type == SOCK_DGRAM ? "UDP" : "TCP",
3736 : fd);
3737 :
3738 975033 : return fd;
3739 : }
3740 :
3741 : int socket(int family, int type, int protocol)
3742 : {
3743 1028226 : return swrap_socket(family, type, protocol);
3744 : }
3745 :
3746 : /****************************************************************************
3747 : * SOCKETPAIR
3748 : ***************************************************************************/
3749 :
3750 1117 : static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3751 : {
3752 : int rc;
3753 :
3754 1117 : rc = libc_socketpair(family, type, protocol, sv);
3755 1117 : if (rc != -1) {
3756 1117 : swrap_remove_stale(sv[0]);
3757 1117 : swrap_remove_stale(sv[1]);
3758 : }
3759 :
3760 1117 : return rc;
3761 : }
3762 :
3763 : int socketpair(int family, int type, int protocol, int sv[2])
3764 : {
3765 1117 : return swrap_socketpair(family, type, protocol, sv);
3766 : }
3767 :
3768 : /****************************************************************************
3769 : * SOCKETPAIR
3770 : ***************************************************************************/
3771 :
3772 : #ifdef HAVE_TIMERFD_CREATE
3773 0 : static int swrap_timerfd_create(int clockid, int flags)
3774 : {
3775 : int fd;
3776 :
3777 0 : fd = libc_timerfd_create(clockid, flags);
3778 0 : if (fd != -1) {
3779 0 : swrap_remove_stale(fd);
3780 : }
3781 :
3782 0 : return fd;
3783 : }
3784 :
3785 : int timerfd_create(int clockid, int flags)
3786 : {
3787 0 : return swrap_timerfd_create(clockid, flags);
3788 : }
3789 : #endif
3790 :
3791 : /****************************************************************************
3792 : * PIPE
3793 : ***************************************************************************/
3794 :
3795 318218 : static int swrap_pipe(int pipefd[2])
3796 : {
3797 : int rc;
3798 :
3799 318218 : rc = libc_pipe(pipefd);
3800 318218 : if (rc != -1) {
3801 318218 : swrap_remove_stale(pipefd[0]);
3802 318218 : swrap_remove_stale(pipefd[1]);
3803 : }
3804 :
3805 318218 : return rc;
3806 : }
3807 :
3808 : int pipe(int pipefd[2])
3809 : {
3810 318218 : return swrap_pipe(pipefd);
3811 : }
3812 :
3813 : /****************************************************************************
3814 : * ACCEPT
3815 : ***************************************************************************/
3816 :
3817 112073 : static int swrap_accept(int s,
3818 : struct sockaddr *addr,
3819 : socklen_t *addrlen,
3820 : int flags)
3821 : {
3822 : struct socket_info *parent_si, *child_si;
3823 112073 : struct socket_info new_si = { 0 };
3824 : int fd;
3825 : int idx;
3826 112073 : struct swrap_address un_addr = {
3827 : .sa_socklen = sizeof(struct sockaddr_un),
3828 : };
3829 112073 : struct swrap_address un_my_addr = {
3830 : .sa_socklen = sizeof(struct sockaddr_un),
3831 : };
3832 112073 : struct swrap_address in_addr = {
3833 : .sa_socklen = sizeof(struct sockaddr_storage),
3834 : };
3835 112073 : struct swrap_address in_my_addr = {
3836 : .sa_socklen = sizeof(struct sockaddr_storage),
3837 : };
3838 : int ret;
3839 :
3840 112073 : parent_si = find_socket_info(s);
3841 112073 : if (!parent_si) {
3842 : #ifdef HAVE_ACCEPT4
3843 11096 : return libc_accept4(s, addr, addrlen, flags);
3844 : #else
3845 : UNUSED(flags);
3846 : return libc_accept(s, addr, addrlen);
3847 : #endif
3848 : }
3849 :
3850 :
3851 : /*
3852 : * prevent parent_si from being altered / closed
3853 : * while we read it
3854 : */
3855 100977 : SWRAP_LOCK_SI(parent_si);
3856 :
3857 : /*
3858 : * assume out sockaddr have the same size as the in parent
3859 : * socket family
3860 : */
3861 100977 : in_addr.sa_socklen = socket_length(parent_si->family);
3862 100977 : if (in_addr.sa_socklen <= 0) {
3863 0 : SWRAP_UNLOCK_SI(parent_si);
3864 0 : errno = EINVAL;
3865 0 : return -1;
3866 : }
3867 :
3868 100977 : SWRAP_UNLOCK_SI(parent_si);
3869 :
3870 : #ifdef HAVE_ACCEPT4
3871 100977 : ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3872 : #else
3873 : UNUSED(flags);
3874 : ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3875 : #endif
3876 100977 : if (ret == -1) {
3877 10645 : int saved_errno = errno;
3878 10645 : if (saved_errno == ENOTSOCK) {
3879 : /* Remove stale fds */
3880 0 : swrap_remove_stale(s);
3881 : }
3882 10645 : errno = saved_errno;
3883 10645 : return ret;
3884 : }
3885 :
3886 90332 : fd = ret;
3887 :
3888 : /* Check if we have a stale fd and remove it */
3889 90332 : swrap_remove_stale(fd);
3890 :
3891 90332 : if (un_addr.sa.un.sun_path[0] == '\0') {
3892 : /*
3893 : * FreeBSD seems to have a problem where
3894 : * accept4() on the unix socket doesn't
3895 : * ECONNABORTED for already disconnected connections.
3896 : *
3897 : * Let's try libc_getpeername() to get the peer address
3898 : * as a fallback, but it'll likely return ENOTCONN,
3899 : * which we have to map to ECONNABORTED.
3900 : */
3901 0 : un_addr.sa_socklen = sizeof(struct sockaddr_un),
3902 0 : ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3903 0 : if (ret == -1) {
3904 0 : int saved_errno = errno;
3905 0 : libc_close(fd);
3906 0 : if (saved_errno == ENOTCONN) {
3907 : /*
3908 : * If the connection is already disconnected
3909 : * we should return ECONNABORTED.
3910 : */
3911 0 : saved_errno = ECONNABORTED;
3912 : }
3913 0 : errno = saved_errno;
3914 0 : return ret;
3915 : }
3916 : }
3917 :
3918 90332 : ret = libc_getsockname(fd,
3919 : &un_my_addr.sa.s,
3920 : &un_my_addr.sa_socklen);
3921 90332 : if (ret == -1) {
3922 0 : int saved_errno = errno;
3923 0 : libc_close(fd);
3924 0 : if (saved_errno == ENOTCONN) {
3925 : /*
3926 : * If the connection is already disconnected
3927 : * we should return ECONNABORTED.
3928 : */
3929 0 : saved_errno = ECONNABORTED;
3930 : }
3931 0 : errno = saved_errno;
3932 0 : return ret;
3933 : }
3934 :
3935 90332 : SWRAP_LOCK_SI(parent_si);
3936 :
3937 90332 : ret = sockaddr_convert_from_un(parent_si,
3938 : &un_addr.sa.un,
3939 : un_addr.sa_socklen,
3940 : parent_si->family,
3941 : &in_addr.sa.s,
3942 : &in_addr.sa_socklen);
3943 90332 : if (ret == -1) {
3944 0 : int saved_errno = errno;
3945 0 : SWRAP_UNLOCK_SI(parent_si);
3946 0 : libc_close(fd);
3947 0 : errno = saved_errno;
3948 0 : return ret;
3949 : }
3950 :
3951 90332 : child_si = &new_si;
3952 :
3953 90332 : child_si->family = parent_si->family;
3954 90332 : child_si->type = parent_si->type;
3955 90332 : child_si->protocol = parent_si->protocol;
3956 90332 : child_si->bound = 1;
3957 90332 : child_si->is_server = 1;
3958 90332 : child_si->connected = 1;
3959 :
3960 90332 : SWRAP_UNLOCK_SI(parent_si);
3961 :
3962 90332 : child_si->peername = (struct swrap_address) {
3963 90332 : .sa_socklen = in_addr.sa_socklen,
3964 : };
3965 90332 : memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3966 :
3967 90332 : if (addr != NULL && addrlen != NULL) {
3968 90332 : size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3969 90332 : if (copy_len > 0) {
3970 90332 : memcpy(addr, &in_addr.sa.ss, copy_len);
3971 : }
3972 90332 : *addrlen = in_addr.sa_socklen;
3973 : }
3974 :
3975 90332 : ret = sockaddr_convert_from_un(child_si,
3976 : &un_my_addr.sa.un,
3977 : un_my_addr.sa_socklen,
3978 : child_si->family,
3979 : &in_my_addr.sa.s,
3980 : &in_my_addr.sa_socklen);
3981 90332 : if (ret == -1) {
3982 0 : int saved_errno = errno;
3983 0 : libc_close(fd);
3984 0 : errno = saved_errno;
3985 0 : return ret;
3986 : }
3987 :
3988 90332 : SWRAP_LOG(SWRAP_LOG_TRACE,
3989 : "accept() path=%s, fd=%d",
3990 : un_my_addr.sa.un.sun_path, s);
3991 :
3992 90332 : child_si->myname = (struct swrap_address) {
3993 90332 : .sa_socklen = in_my_addr.sa_socklen,
3994 : };
3995 90332 : memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3996 :
3997 90332 : idx = swrap_create_socket(&new_si, fd);
3998 90332 : if (idx == -1) {
3999 0 : int saved_errno = errno;
4000 0 : libc_close(fd);
4001 0 : errno = saved_errno;
4002 0 : return -1;
4003 : }
4004 :
4005 90332 : if (addr != NULL) {
4006 90332 : struct socket_info *si = swrap_get_socket_info(idx);
4007 :
4008 90332 : SWRAP_LOCK_SI(si);
4009 90332 : swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
4010 90332 : swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
4011 90332 : swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
4012 90332 : SWRAP_UNLOCK_SI(si);
4013 : }
4014 :
4015 90332 : return fd;
4016 : }
4017 :
4018 : #ifdef HAVE_ACCEPT4
4019 : int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
4020 : {
4021 0 : return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
4022 : }
4023 : #endif
4024 :
4025 : #ifdef HAVE_ACCEPT_PSOCKLEN_T
4026 : int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
4027 : #else
4028 : int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
4029 : #endif
4030 : {
4031 112073 : return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
4032 : }
4033 :
4034 : static int autobind_start_init;
4035 : static int autobind_start;
4036 :
4037 : /* using sendto() or connect() on an unbound socket would give the
4038 : recipient no way to reply, as unlike UDP and TCP, a unix domain
4039 : socket can't auto-assign ephemeral port numbers, so we need to
4040 : assign it here.
4041 : Note: this might change the family from ipv6 to ipv4
4042 : */
4043 123530 : static int swrap_auto_bind(int fd, struct socket_info *si, int family)
4044 : {
4045 123530 : struct swrap_address un_addr = {
4046 : .sa_socklen = sizeof(struct sockaddr_un),
4047 : };
4048 : int i;
4049 : char type;
4050 : int ret;
4051 : int port;
4052 123530 : char *swrap_dir = NULL;
4053 :
4054 123530 : swrap_mutex_lock(&autobind_start_mutex);
4055 :
4056 123530 : if (autobind_start_init != 1) {
4057 5889 : autobind_start_init = 1;
4058 5889 : autobind_start = getpid();
4059 5889 : autobind_start %= 50000;
4060 5889 : autobind_start += 10000;
4061 : }
4062 :
4063 123530 : un_addr.sa.un.sun_family = AF_UNIX;
4064 :
4065 123530 : switch (family) {
4066 123298 : case AF_INET: {
4067 : struct sockaddr_in in;
4068 :
4069 123298 : switch (si->type) {
4070 99720 : case SOCK_STREAM:
4071 99720 : type = SOCKET_TYPE_CHAR_TCP;
4072 99720 : break;
4073 23578 : case SOCK_DGRAM:
4074 23578 : type = SOCKET_TYPE_CHAR_UDP;
4075 23578 : break;
4076 0 : default:
4077 0 : errno = ESOCKTNOSUPPORT;
4078 0 : ret = -1;
4079 0 : goto done;
4080 : }
4081 :
4082 123298 : memset(&in, 0, sizeof(in));
4083 123298 : in.sin_family = AF_INET;
4084 123298 : in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4085 : socket_wrapper_default_iface()));
4086 :
4087 123298 : si->myname = (struct swrap_address) {
4088 : .sa_socklen = sizeof(in),
4089 : };
4090 123298 : memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4091 123298 : break;
4092 : }
4093 : #ifdef HAVE_IPV6
4094 232 : case AF_INET6: {
4095 : struct sockaddr_in6 in6;
4096 :
4097 232 : if (si->family != family) {
4098 0 : errno = ENETUNREACH;
4099 0 : ret = -1;
4100 0 : goto done;
4101 : }
4102 :
4103 232 : switch (si->type) {
4104 96 : case SOCK_STREAM:
4105 96 : type = SOCKET_TYPE_CHAR_TCP_V6;
4106 96 : break;
4107 136 : case SOCK_DGRAM:
4108 136 : type = SOCKET_TYPE_CHAR_UDP_V6;
4109 136 : break;
4110 0 : default:
4111 0 : errno = ESOCKTNOSUPPORT;
4112 0 : ret = -1;
4113 0 : goto done;
4114 : }
4115 :
4116 232 : memset(&in6, 0, sizeof(in6));
4117 232 : in6.sin6_family = AF_INET6;
4118 232 : in6.sin6_addr = *swrap_ipv6();
4119 232 : in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4120 :
4121 232 : si->myname = (struct swrap_address) {
4122 : .sa_socklen = sizeof(in6),
4123 : };
4124 232 : memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4125 232 : break;
4126 : }
4127 : #endif
4128 0 : default:
4129 0 : errno = ESOCKTNOSUPPORT;
4130 0 : ret = -1;
4131 0 : goto done;
4132 : }
4133 :
4134 123530 : if (autobind_start > 60000) {
4135 0 : autobind_start = 10000;
4136 : }
4137 :
4138 123530 : swrap_dir = socket_wrapper_dir();
4139 123530 : if (swrap_dir == NULL) {
4140 0 : errno = EINVAL;
4141 0 : ret = -1;
4142 0 : goto done;
4143 : }
4144 :
4145 123536 : for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4146 123536 : port = autobind_start + i;
4147 123536 : swrap_un_path(&un_addr.sa.un,
4148 : swrap_dir,
4149 : type,
4150 : socket_wrapper_default_iface(),
4151 : port);
4152 :
4153 123536 : ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4154 123536 : if (ret == -1) {
4155 6 : if (errno == EALREADY || errno == EADDRINUSE) {
4156 6 : continue;
4157 : }
4158 0 : goto done;
4159 : }
4160 :
4161 123530 : si->un_addr = un_addr.sa.un;
4162 :
4163 123530 : si->bound = 1;
4164 123530 : autobind_start = port + 1;
4165 123530 : break;
4166 : }
4167 123530 : if (i == SOCKET_MAX_SOCKETS) {
4168 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4169 : "interface "SOCKET_FORMAT,
4170 : SOCKET_MAX_SOCKETS,
4171 : type,
4172 : socket_wrapper_default_iface(),
4173 : 0);
4174 0 : errno = ENFILE;
4175 0 : ret = -1;
4176 0 : goto done;
4177 : }
4178 :
4179 123530 : si->family = family;
4180 123530 : set_port(si->family, port, &si->myname);
4181 :
4182 123530 : ret = 0;
4183 :
4184 123530 : done:
4185 123530 : SAFE_FREE(swrap_dir);
4186 123530 : swrap_mutex_unlock(&autobind_start_mutex);
4187 123530 : return ret;
4188 : }
4189 :
4190 : /****************************************************************************
4191 : * CONNECT
4192 : ***************************************************************************/
4193 :
4194 149126 : static int swrap_connect(int s, const struct sockaddr *serv_addr,
4195 : socklen_t addrlen)
4196 : {
4197 : int ret;
4198 149126 : struct swrap_address un_addr = {
4199 : .sa_socklen = sizeof(struct sockaddr_un),
4200 : };
4201 149126 : struct socket_info *si = find_socket_info(s);
4202 149126 : struct swrap_sockaddr_buf buf = {};
4203 149126 : int bcast = 0;
4204 :
4205 149126 : if (!si) {
4206 25833 : return libc_connect(s, serv_addr, addrlen);
4207 : }
4208 :
4209 123293 : SWRAP_LOCK_SI(si);
4210 :
4211 123293 : if (si->bound == 0) {
4212 122214 : ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4213 122214 : if (ret == -1) {
4214 0 : goto done;
4215 : }
4216 : }
4217 :
4218 123293 : if (si->family != serv_addr->sa_family) {
4219 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
4220 : "called for fd=%d (family=%d) called with invalid family=%d",
4221 : s, si->family, serv_addr->sa_family);
4222 0 : errno = EINVAL;
4223 0 : ret = -1;
4224 0 : goto done;
4225 : }
4226 :
4227 123293 : ret = sockaddr_convert_to_un(si, serv_addr,
4228 : addrlen, &un_addr.sa.un, 0, &bcast);
4229 123293 : if (ret == -1) {
4230 0 : goto done;
4231 : }
4232 :
4233 123293 : if (bcast) {
4234 0 : errno = ENETUNREACH;
4235 0 : ret = -1;
4236 0 : goto done;
4237 : }
4238 :
4239 123293 : if (si->type == SOCK_DGRAM) {
4240 22455 : si->defer_connect = 1;
4241 22455 : ret = 0;
4242 : } else {
4243 100838 : swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4244 :
4245 100838 : ret = libc_connect(s,
4246 : &un_addr.sa.s,
4247 : un_addr.sa_socklen);
4248 : }
4249 :
4250 123293 : SWRAP_LOG(SWRAP_LOG_TRACE,
4251 : "connect(%s) path=%s, fd=%d",
4252 : swrap_sockaddr_string(&buf, serv_addr),
4253 : un_addr.sa.un.sun_path, s);
4254 :
4255 :
4256 : /* to give better errors */
4257 123293 : if (ret == -1 && errno == ENOENT) {
4258 0 : errno = EHOSTUNREACH;
4259 : }
4260 :
4261 123293 : if (ret == 0) {
4262 123293 : si->peername = (struct swrap_address) {
4263 : .sa_socklen = addrlen,
4264 : };
4265 :
4266 123293 : memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4267 123293 : si->connected = 1;
4268 :
4269 : /*
4270 : * When we connect() on a socket than we have to bind the
4271 : * outgoing connection on the interface we use for the
4272 : * transport. We already bound it on the right interface
4273 : * but here we have to update the name so getsockname()
4274 : * returns correct information.
4275 : */
4276 123293 : if (si->bindname.sa_socklen > 0) {
4277 1051 : si->myname = (struct swrap_address) {
4278 1051 : .sa_socklen = si->bindname.sa_socklen,
4279 : };
4280 :
4281 1051 : memcpy(&si->myname.sa.ss,
4282 1051 : &si->bindname.sa.ss,
4283 1051 : si->bindname.sa_socklen);
4284 :
4285 : /* Cleanup bindname */
4286 1051 : si->bindname = (struct swrap_address) {
4287 : .sa_socklen = 0,
4288 : };
4289 : }
4290 :
4291 123293 : swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4292 123293 : swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4293 : } else {
4294 0 : swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4295 : }
4296 :
4297 123293 : done:
4298 123293 : SWRAP_UNLOCK_SI(si);
4299 123293 : return ret;
4300 : }
4301 :
4302 : int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4303 : {
4304 149126 : return swrap_connect(s, serv_addr, addrlen);
4305 : }
4306 :
4307 : /****************************************************************************
4308 : * BIND
4309 : ***************************************************************************/
4310 :
4311 31167 : static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4312 : {
4313 : int ret;
4314 31167 : struct swrap_address un_addr = {
4315 : .sa_socklen = sizeof(struct sockaddr_un),
4316 : };
4317 31167 : struct socket_info *si = find_socket_info(s);
4318 31167 : struct swrap_sockaddr_buf buf = {};
4319 31167 : int ret_errno = errno;
4320 31167 : int bind_error = 0;
4321 : #if 0 /* FIXME */
4322 : bool in_use;
4323 : #endif
4324 :
4325 31167 : if (!si) {
4326 27331 : return libc_bind(s, myaddr, addrlen);
4327 : }
4328 :
4329 3836 : SWRAP_LOCK_SI(si);
4330 :
4331 3836 : switch (si->family) {
4332 2747 : case AF_INET: {
4333 : const struct sockaddr_in *sin;
4334 2747 : if (addrlen < sizeof(struct sockaddr_in)) {
4335 0 : bind_error = EINVAL;
4336 0 : break;
4337 : }
4338 :
4339 2747 : sin = (const struct sockaddr_in *)(const void *)myaddr;
4340 :
4341 2747 : if (sin->sin_family != AF_INET) {
4342 0 : bind_error = EAFNOSUPPORT;
4343 : }
4344 :
4345 : /* special case for AF_UNSPEC */
4346 2747 : if (sin->sin_family == AF_UNSPEC &&
4347 0 : (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4348 : {
4349 0 : bind_error = 0;
4350 : }
4351 :
4352 2747 : break;
4353 : }
4354 : #ifdef HAVE_IPV6
4355 1089 : case AF_INET6: {
4356 : const struct sockaddr_in6 *sin6;
4357 1089 : if (addrlen < sizeof(struct sockaddr_in6)) {
4358 0 : bind_error = EINVAL;
4359 0 : break;
4360 : }
4361 :
4362 1089 : sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4363 :
4364 1089 : if (sin6->sin6_family != AF_INET6) {
4365 0 : bind_error = EAFNOSUPPORT;
4366 : }
4367 :
4368 1089 : break;
4369 : }
4370 : #endif
4371 0 : default:
4372 0 : bind_error = EINVAL;
4373 0 : break;
4374 : }
4375 :
4376 3836 : if (bind_error != 0) {
4377 0 : ret_errno = bind_error;
4378 0 : ret = -1;
4379 0 : goto out;
4380 : }
4381 :
4382 : #if 0 /* FIXME */
4383 : in_use = check_addr_port_in_use(myaddr, addrlen);
4384 : if (in_use) {
4385 : errno = EADDRINUSE;
4386 : ret = -1;
4387 : goto out;
4388 : }
4389 : #endif
4390 :
4391 3836 : si->myname.sa_socklen = addrlen;
4392 3836 : memcpy(&si->myname.sa.ss, myaddr, addrlen);
4393 :
4394 3836 : ret = sockaddr_convert_to_un(si,
4395 : myaddr,
4396 : addrlen,
4397 : &un_addr.sa.un,
4398 : 1,
4399 : &si->bcast);
4400 3836 : if (ret == -1) {
4401 142 : ret_errno = errno;
4402 142 : goto out;
4403 : }
4404 :
4405 3694 : unlink(un_addr.sa.un.sun_path);
4406 :
4407 3694 : ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4408 3694 : if (ret == -1) {
4409 0 : ret_errno = errno;
4410 : }
4411 :
4412 3694 : SWRAP_LOG(SWRAP_LOG_TRACE,
4413 : "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4414 : swrap_sockaddr_string(&buf, myaddr),
4415 : un_addr.sa.un.sun_path, s, ret, ret_errno);
4416 :
4417 3694 : if (ret == 0) {
4418 3694 : si->bound = 1;
4419 : }
4420 :
4421 0 : out:
4422 3836 : SWRAP_UNLOCK_SI(si);
4423 3836 : errno = ret_errno;
4424 3836 : return ret;
4425 : }
4426 :
4427 : int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4428 : {
4429 31167 : return swrap_bind(s, myaddr, addrlen);
4430 : }
4431 :
4432 : /****************************************************************************
4433 : * BINDRESVPORT
4434 : ***************************************************************************/
4435 :
4436 : #ifdef HAVE_BINDRESVPORT
4437 : static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4438 :
4439 0 : static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4440 : {
4441 0 : struct swrap_address myaddr = {
4442 : .sa_socklen = sizeof(struct sockaddr_storage),
4443 : };
4444 : socklen_t salen;
4445 : static uint16_t port;
4446 : uint16_t i;
4447 0 : int rc = -1;
4448 : int af;
4449 :
4450 : #define SWRAP_STARTPORT 600
4451 : #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4452 : #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4453 :
4454 0 : if (port == 0) {
4455 0 : port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4456 : }
4457 :
4458 0 : if (sa == NULL) {
4459 0 : salen = myaddr.sa_socklen;
4460 0 : sa = &myaddr.sa.s;
4461 :
4462 0 : rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4463 0 : if (rc < 0) {
4464 0 : return -1;
4465 : }
4466 :
4467 0 : af = sa->sa_family;
4468 0 : memset(&myaddr.sa.ss, 0, salen);
4469 : } else {
4470 0 : af = sa->sa_family;
4471 : }
4472 :
4473 0 : for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4474 0 : switch(af) {
4475 0 : case AF_INET: {
4476 0 : struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4477 :
4478 0 : salen = sizeof(struct sockaddr_in);
4479 0 : sinp->sin_port = htons(port);
4480 0 : break;
4481 : }
4482 0 : case AF_INET6: {
4483 0 : struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4484 :
4485 0 : salen = sizeof(struct sockaddr_in6);
4486 0 : sin6p->sin6_port = htons(port);
4487 0 : break;
4488 : }
4489 0 : default:
4490 0 : errno = EAFNOSUPPORT;
4491 0 : return -1;
4492 : }
4493 0 : sa->sa_family = af;
4494 :
4495 0 : if (port > SWRAP_ENDPORT) {
4496 0 : port = SWRAP_STARTPORT;
4497 : }
4498 :
4499 0 : rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4500 0 : if (rc == 0 || errno != EADDRINUSE) {
4501 : break;
4502 : }
4503 : }
4504 :
4505 0 : return rc;
4506 : }
4507 :
4508 : int bindresvport(int sockfd, struct sockaddr_in *sinp)
4509 : {
4510 0 : return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4511 : }
4512 : #endif
4513 :
4514 : /****************************************************************************
4515 : * LISTEN
4516 : ***************************************************************************/
4517 :
4518 2863 : static int swrap_listen(int s, int backlog)
4519 : {
4520 : int ret;
4521 2863 : struct socket_info *si = find_socket_info(s);
4522 :
4523 2863 : if (!si) {
4524 1656 : return libc_listen(s, backlog);
4525 : }
4526 :
4527 1207 : SWRAP_LOCK_SI(si);
4528 :
4529 1207 : if (si->bound == 0) {
4530 0 : ret = swrap_auto_bind(s, si, si->family);
4531 0 : if (ret == -1) {
4532 0 : errno = EADDRINUSE;
4533 0 : goto out;
4534 : }
4535 : }
4536 :
4537 1207 : ret = libc_listen(s, backlog);
4538 1207 : if (ret == 0) {
4539 1207 : si->listening = 1;
4540 : }
4541 :
4542 0 : out:
4543 1207 : SWRAP_UNLOCK_SI(si);
4544 :
4545 1207 : return ret;
4546 : }
4547 :
4548 : int listen(int s, int backlog)
4549 : {
4550 2863 : return swrap_listen(s, backlog);
4551 : }
4552 :
4553 : /****************************************************************************
4554 : * FOPEN
4555 : ***************************************************************************/
4556 :
4557 1595690 : static FILE *swrap_fopen(const char *name, const char *mode)
4558 : {
4559 : FILE *fp;
4560 :
4561 1595690 : fp = libc_fopen(name, mode);
4562 1595690 : if (fp != NULL) {
4563 816308 : int fd = fileno(fp);
4564 :
4565 816308 : swrap_remove_stale(fd);
4566 : }
4567 :
4568 1595690 : return fp;
4569 : }
4570 :
4571 : FILE *fopen(const char *name, const char *mode)
4572 : {
4573 1595690 : return swrap_fopen(name, mode);
4574 : }
4575 :
4576 : /****************************************************************************
4577 : * FOPEN64
4578 : ***************************************************************************/
4579 :
4580 : #ifdef HAVE_FOPEN64
4581 : static FILE *swrap_fopen64(const char *name, const char *mode)
4582 : {
4583 : FILE *fp;
4584 :
4585 : fp = libc_fopen64(name, mode);
4586 : if (fp != NULL) {
4587 : int fd = fileno(fp);
4588 :
4589 : swrap_remove_stale(fd);
4590 : }
4591 :
4592 : return fp;
4593 : }
4594 :
4595 : FILE *fopen64(const char *name, const char *mode)
4596 : {
4597 : return swrap_fopen64(name, mode);
4598 : }
4599 : #endif /* HAVE_FOPEN64 */
4600 :
4601 : /****************************************************************************
4602 : * OPEN
4603 : ***************************************************************************/
4604 :
4605 1873884 : static int swrap_vopen(const char *pathname, int flags, va_list ap)
4606 : {
4607 : int ret;
4608 :
4609 1873884 : ret = libc_vopen(pathname, flags, ap);
4610 1873884 : if (ret != -1) {
4611 : /*
4612 : * There are methods for closing descriptors (libc-internal code
4613 : * paths, direct syscalls) which close descriptors in ways that
4614 : * we can't intercept, so try to recover when we notice that
4615 : * that's happened
4616 : */
4617 1810632 : swrap_remove_stale(ret);
4618 : }
4619 1873884 : return ret;
4620 : }
4621 :
4622 : int open(const char *pathname, int flags, ...)
4623 : {
4624 : va_list ap;
4625 : int fd;
4626 :
4627 1873884 : va_start(ap, flags);
4628 1873884 : fd = swrap_vopen(pathname, flags, ap);
4629 1873884 : va_end(ap);
4630 :
4631 1873884 : return fd;
4632 : }
4633 :
4634 : /****************************************************************************
4635 : * OPEN64
4636 : ***************************************************************************/
4637 :
4638 : #ifdef HAVE_OPEN64
4639 : static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4640 : {
4641 : int ret;
4642 :
4643 : ret = libc_vopen64(pathname, flags, ap);
4644 : if (ret != -1) {
4645 : /*
4646 : * There are methods for closing descriptors (libc-internal code
4647 : * paths, direct syscalls) which close descriptors in ways that
4648 : * we can't intercept, so try to recover when we notice that
4649 : * that's happened
4650 : */
4651 : swrap_remove_stale(ret);
4652 : }
4653 : return ret;
4654 : }
4655 :
4656 : int open64(const char *pathname, int flags, ...)
4657 : {
4658 : va_list ap;
4659 : int fd;
4660 :
4661 : va_start(ap, flags);
4662 : fd = swrap_vopen64(pathname, flags, ap);
4663 : va_end(ap);
4664 :
4665 : return fd;
4666 : }
4667 : #endif /* HAVE_OPEN64 */
4668 :
4669 : /****************************************************************************
4670 : * OPENAT
4671 : ***************************************************************************/
4672 :
4673 131789 : static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4674 : {
4675 : int ret;
4676 :
4677 131789 : ret = libc_vopenat(dirfd, path, flags, ap);
4678 131789 : if (ret != -1) {
4679 : /*
4680 : * There are methods for closing descriptors (libc-internal code
4681 : * paths, direct syscalls) which close descriptors in ways that
4682 : * we can't intercept, so try to recover when we notice that
4683 : * that's happened
4684 : */
4685 93445 : swrap_remove_stale(ret);
4686 : }
4687 :
4688 131789 : return ret;
4689 : }
4690 :
4691 : int openat(int dirfd, const char *path, int flags, ...)
4692 : {
4693 : va_list ap;
4694 : int fd;
4695 :
4696 131789 : va_start(ap, flags);
4697 131789 : fd = swrap_vopenat(dirfd, path, flags, ap);
4698 131789 : va_end(ap);
4699 :
4700 131789 : return fd;
4701 : }
4702 :
4703 : /****************************************************************************
4704 : * GETPEERNAME
4705 : ***************************************************************************/
4706 :
4707 127792 : static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4708 : {
4709 127792 : struct socket_info *si = find_socket_info(s);
4710 : socklen_t len;
4711 127792 : int ret = -1;
4712 :
4713 127792 : if (!si) {
4714 6577 : return libc_getpeername(s, name, addrlen);
4715 : }
4716 :
4717 121215 : SWRAP_LOCK_SI(si);
4718 :
4719 121215 : if (si->peername.sa_socklen == 0)
4720 : {
4721 61 : errno = ENOTCONN;
4722 61 : goto out;
4723 : }
4724 :
4725 121154 : len = MIN(*addrlen, si->peername.sa_socklen);
4726 121154 : if (len == 0) {
4727 0 : ret = 0;
4728 0 : goto out;
4729 : }
4730 :
4731 121154 : memcpy(name, &si->peername.sa.ss, len);
4732 121154 : *addrlen = si->peername.sa_socklen;
4733 :
4734 121154 : ret = 0;
4735 121215 : out:
4736 121215 : SWRAP_UNLOCK_SI(si);
4737 :
4738 121215 : return ret;
4739 : }
4740 :
4741 : #ifdef HAVE_ACCEPT_PSOCKLEN_T
4742 : int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4743 : #else
4744 : int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4745 : #endif
4746 : {
4747 127792 : return swrap_getpeername(s, name, (socklen_t *)addrlen);
4748 : }
4749 :
4750 : /****************************************************************************
4751 : * GETSOCKNAME
4752 : ***************************************************************************/
4753 :
4754 465193 : static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4755 : {
4756 465193 : struct socket_info *si = find_socket_info(s);
4757 : socklen_t len;
4758 465193 : int ret = -1;
4759 :
4760 465193 : if (!si) {
4761 308891 : return libc_getsockname(s, name, addrlen);
4762 : }
4763 :
4764 156302 : SWRAP_LOCK_SI(si);
4765 :
4766 156302 : len = MIN(*addrlen, si->myname.sa_socklen);
4767 156302 : if (len == 0) {
4768 0 : ret = 0;
4769 0 : goto out;
4770 : }
4771 :
4772 156302 : memcpy(name, &si->myname.sa.ss, len);
4773 156302 : *addrlen = si->myname.sa_socklen;
4774 :
4775 156302 : ret = 0;
4776 156302 : out:
4777 156302 : SWRAP_UNLOCK_SI(si);
4778 :
4779 156302 : return ret;
4780 : }
4781 :
4782 : #ifdef HAVE_ACCEPT_PSOCKLEN_T
4783 : int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4784 : #else
4785 : int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4786 : #endif
4787 : {
4788 465193 : return swrap_getsockname(s, name, (socklen_t *)addrlen);
4789 : }
4790 :
4791 : /****************************************************************************
4792 : * GETSOCKOPT
4793 : ***************************************************************************/
4794 :
4795 : #ifndef SO_PROTOCOL
4796 : # ifdef SO_PROTOTYPE /* The Solaris name */
4797 : # define SO_PROTOCOL SO_PROTOTYPE
4798 : # endif /* SO_PROTOTYPE */
4799 : #endif /* SO_PROTOCOL */
4800 :
4801 374346 : static int swrap_getsockopt(int s, int level, int optname,
4802 : void *optval, socklen_t *optlen)
4803 : {
4804 374346 : struct socket_info *si = find_socket_info(s);
4805 : int ret;
4806 :
4807 374346 : if (!si) {
4808 4547 : return libc_getsockopt(s,
4809 : level,
4810 : optname,
4811 : optval,
4812 : optlen);
4813 : }
4814 :
4815 369799 : SWRAP_LOCK_SI(si);
4816 :
4817 369799 : if (level == SOL_SOCKET) {
4818 369799 : switch (optname) {
4819 : #ifdef SO_DOMAIN
4820 0 : case SO_DOMAIN:
4821 0 : if (optval == NULL || optlen == NULL ||
4822 0 : *optlen < (socklen_t)sizeof(int)) {
4823 0 : errno = EINVAL;
4824 0 : ret = -1;
4825 0 : goto done;
4826 : }
4827 :
4828 0 : *optlen = sizeof(int);
4829 0 : *(int *)optval = si->family;
4830 0 : ret = 0;
4831 0 : goto done;
4832 : #endif /* SO_DOMAIN */
4833 :
4834 : #ifdef SO_PROTOCOL
4835 0 : case SO_PROTOCOL:
4836 0 : if (optval == NULL || optlen == NULL ||
4837 0 : *optlen < (socklen_t)sizeof(int)) {
4838 0 : errno = EINVAL;
4839 0 : ret = -1;
4840 0 : goto done;
4841 : }
4842 :
4843 0 : *optlen = sizeof(int);
4844 0 : *(int *)optval = si->protocol;
4845 0 : ret = 0;
4846 0 : goto done;
4847 : #endif /* SO_PROTOCOL */
4848 0 : case SO_TYPE:
4849 0 : if (optval == NULL || optlen == NULL ||
4850 0 : *optlen < (socklen_t)sizeof(int)) {
4851 0 : errno = EINVAL;
4852 0 : ret = -1;
4853 0 : goto done;
4854 : }
4855 :
4856 0 : *optlen = sizeof(int);
4857 0 : *(int *)optval = si->type;
4858 0 : ret = 0;
4859 0 : goto done;
4860 369799 : default:
4861 369799 : ret = libc_getsockopt(s,
4862 : level,
4863 : optname,
4864 : optval,
4865 : optlen);
4866 369799 : goto done;
4867 : }
4868 0 : } else if (level == IPPROTO_TCP) {
4869 0 : switch (optname) {
4870 : #ifdef TCP_NODELAY
4871 0 : case TCP_NODELAY:
4872 : /*
4873 : * This enables sending packets directly out over TCP.
4874 : * As a unix socket is doing that any way, report it as
4875 : * enabled.
4876 : */
4877 0 : if (optval == NULL || optlen == NULL ||
4878 0 : *optlen < (socklen_t)sizeof(int)) {
4879 0 : errno = EINVAL;
4880 0 : ret = -1;
4881 0 : goto done;
4882 : }
4883 :
4884 0 : *optlen = sizeof(int);
4885 0 : *(int *)optval = si->tcp_nodelay;
4886 :
4887 0 : ret = 0;
4888 0 : goto done;
4889 : #endif /* TCP_NODELAY */
4890 : #ifdef TCP_INFO
4891 0 : case TCP_INFO: {
4892 : struct tcp_info info;
4893 0 : socklen_t ilen = sizeof(info);
4894 :
4895 : #ifdef HAVE_NETINET_TCP_FSM_H
4896 : /* This is FreeBSD */
4897 : # define __TCP_LISTEN TCPS_LISTEN
4898 : # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4899 : # define __TCP_CLOSE TCPS_CLOSED
4900 : #else
4901 : /* This is Linux */
4902 : # define __TCP_LISTEN TCP_LISTEN
4903 : # define __TCP_ESTABLISHED TCP_ESTABLISHED
4904 : # define __TCP_CLOSE TCP_CLOSE
4905 : #endif
4906 :
4907 0 : ZERO_STRUCT(info);
4908 0 : if (si->listening) {
4909 0 : info.tcpi_state = __TCP_LISTEN;
4910 0 : } else if (si->connected) {
4911 : /*
4912 : * For now we just fake a few values
4913 : * supported both by FreeBSD and Linux
4914 : */
4915 0 : info.tcpi_state = __TCP_ESTABLISHED;
4916 0 : info.tcpi_rto = 200000; /* 200 msec */
4917 0 : info.tcpi_rtt = 5000; /* 5 msec */
4918 0 : info.tcpi_rttvar = 5000; /* 5 msec */
4919 : } else {
4920 0 : info.tcpi_state = __TCP_CLOSE;
4921 0 : info.tcpi_rto = 1000000; /* 1 sec */
4922 0 : info.tcpi_rtt = 0;
4923 0 : info.tcpi_rttvar = 250000; /* 250 msec */
4924 : }
4925 :
4926 0 : if (optval == NULL || optlen == NULL ||
4927 0 : *optlen < (socklen_t)ilen) {
4928 0 : errno = EINVAL;
4929 0 : ret = -1;
4930 0 : goto done;
4931 : }
4932 :
4933 0 : *optlen = ilen;
4934 0 : memcpy(optval, &info, ilen);
4935 :
4936 0 : ret = 0;
4937 0 : goto done;
4938 : }
4939 : #endif /* TCP_INFO */
4940 0 : default:
4941 0 : break;
4942 : }
4943 : }
4944 :
4945 0 : errno = ENOPROTOOPT;
4946 0 : ret = -1;
4947 :
4948 369799 : done:
4949 369799 : SWRAP_UNLOCK_SI(si);
4950 369799 : return ret;
4951 : }
4952 :
4953 : #ifdef HAVE_ACCEPT_PSOCKLEN_T
4954 : int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4955 : #else
4956 : int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4957 : #endif
4958 : {
4959 374346 : return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4960 : }
4961 :
4962 : /****************************************************************************
4963 : * SETSOCKOPT
4964 : ***************************************************************************/
4965 :
4966 38765 : static int swrap_setsockopt(int s, int level, int optname,
4967 : const void *optval, socklen_t optlen)
4968 : {
4969 38765 : struct socket_info *si = find_socket_info(s);
4970 : int ret;
4971 :
4972 38765 : if (!si) {
4973 0 : return libc_setsockopt(s,
4974 : level,
4975 : optname,
4976 : optval,
4977 : optlen);
4978 : }
4979 :
4980 38765 : if (level == SOL_SOCKET) {
4981 23155 : return libc_setsockopt(s,
4982 : level,
4983 : optname,
4984 : optval,
4985 : optlen);
4986 : }
4987 :
4988 15610 : SWRAP_LOCK_SI(si);
4989 :
4990 15610 : if (level == IPPROTO_TCP) {
4991 14524 : switch (optname) {
4992 : #ifdef TCP_NODELAY
4993 14509 : case TCP_NODELAY: {
4994 : int i;
4995 :
4996 : /*
4997 : * This enables sending packets directly out over TCP.
4998 : * A unix socket is doing that any way.
4999 : */
5000 14509 : if (optval == NULL || optlen == 0 ||
5001 : optlen < (socklen_t)sizeof(int)) {
5002 0 : errno = EINVAL;
5003 0 : ret = -1;
5004 0 : goto done;
5005 : }
5006 :
5007 14509 : i = *discard_const_p(int, optval);
5008 14509 : if (i != 0 && i != 1) {
5009 0 : errno = EINVAL;
5010 0 : ret = -1;
5011 0 : goto done;
5012 : }
5013 14509 : si->tcp_nodelay = i;
5014 :
5015 14509 : ret = 0;
5016 14509 : goto done;
5017 : }
5018 : #endif /* TCP_NODELAY */
5019 15 : default:
5020 15 : break;
5021 : }
5022 : }
5023 :
5024 1101 : switch (si->family) {
5025 44 : case AF_INET:
5026 44 : if (level == IPPROTO_IP) {
5027 : #ifdef IP_PKTINFO
5028 29 : if (optname == IP_PKTINFO) {
5029 0 : si->pktinfo = AF_INET;
5030 : }
5031 : #endif /* IP_PKTINFO */
5032 : }
5033 44 : ret = 0;
5034 44 : goto done;
5035 : #ifdef HAVE_IPV6
5036 1057 : case AF_INET6:
5037 1057 : if (level == IPPROTO_IPV6) {
5038 : #ifdef IPV6_RECVPKTINFO
5039 1057 : if (optname == IPV6_RECVPKTINFO) {
5040 0 : si->pktinfo = AF_INET6;
5041 : }
5042 : #endif /* IPV6_PKTINFO */
5043 : }
5044 1057 : ret = 0;
5045 1057 : goto done;
5046 : #endif
5047 0 : default:
5048 0 : errno = ENOPROTOOPT;
5049 0 : ret = -1;
5050 0 : goto done;
5051 : }
5052 :
5053 15610 : done:
5054 15610 : SWRAP_UNLOCK_SI(si);
5055 15610 : return ret;
5056 : }
5057 :
5058 : int setsockopt(int s, int level, int optname,
5059 : const void *optval, socklen_t optlen)
5060 : {
5061 38765 : return swrap_setsockopt(s, level, optname, optval, optlen);
5062 : }
5063 :
5064 : /****************************************************************************
5065 : * IOCTL
5066 : ***************************************************************************/
5067 :
5068 1575696 : static int swrap_vioctl(int s, unsigned long int r, va_list va)
5069 : {
5070 1575696 : struct socket_info *si = find_socket_info(s);
5071 : va_list ap;
5072 1575696 : int *value_ptr = NULL;
5073 : int rc;
5074 :
5075 1575696 : if (!si) {
5076 167031 : return libc_vioctl(s, r, va);
5077 : }
5078 :
5079 1408665 : SWRAP_LOCK_SI(si);
5080 :
5081 1408665 : va_copy(ap, va);
5082 :
5083 1408665 : rc = libc_vioctl(s, r, va);
5084 :
5085 1408665 : switch (r) {
5086 109594 : case FIONREAD:
5087 109594 : if (rc == 0) {
5088 109594 : value_ptr = ((int *)va_arg(ap, int *));
5089 : }
5090 :
5091 109594 : if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5092 0 : swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5093 109594 : } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5094 2082 : swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5095 : }
5096 109594 : break;
5097 : #ifdef FIONWRITE
5098 : case FIONWRITE:
5099 : /* this is FreeBSD */
5100 : FALL_THROUGH; /* to TIOCOUTQ */
5101 : #endif /* FIONWRITE */
5102 0 : case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5103 : /*
5104 : * This may return more bytes then the application
5105 : * sent into the socket, for tcp it should
5106 : * return the number of unacked bytes.
5107 : *
5108 : * On AF_UNIX, all bytes are immediately acked!
5109 : */
5110 0 : if (rc == 0) {
5111 0 : value_ptr = ((int *)va_arg(ap, int *));
5112 0 : *value_ptr = 0;
5113 : }
5114 0 : break;
5115 : }
5116 :
5117 1408665 : va_end(ap);
5118 :
5119 1408665 : SWRAP_UNLOCK_SI(si);
5120 1408665 : return rc;
5121 : }
5122 :
5123 : #ifdef HAVE_IOCTL_INT
5124 : int ioctl(int s, int r, ...)
5125 : #else
5126 : int ioctl(int s, unsigned long int r, ...)
5127 : #endif
5128 : {
5129 : va_list va;
5130 : int rc;
5131 :
5132 1575696 : va_start(va, r);
5133 :
5134 1575696 : rc = swrap_vioctl(s, (unsigned long int) r, va);
5135 :
5136 1575696 : va_end(va);
5137 :
5138 1575696 : return rc;
5139 : }
5140 :
5141 : /*****************
5142 : * CMSG
5143 : *****************/
5144 :
5145 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5146 :
5147 : #ifndef CMSG_ALIGN
5148 : # ifdef _ALIGN /* BSD */
5149 : #define CMSG_ALIGN _ALIGN
5150 : # else
5151 : #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5152 : # endif /* _ALIGN */
5153 : #endif /* CMSG_ALIGN */
5154 :
5155 : /**
5156 : * @brief Add a cmsghdr to a msghdr.
5157 : *
5158 : * This is an function to add any type of cmsghdr. It will operate on the
5159 : * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5160 : * the buffer position after the added cmsg element. Hence, this function is
5161 : * intended to be used with an intermediate msghdr and not on the original
5162 : * one handed in by the client.
5163 : *
5164 : * @param[in] msg The msghdr to which to add the cmsg.
5165 : *
5166 : * @param[in] level The cmsg level to set.
5167 : *
5168 : * @param[in] type The cmsg type to set.
5169 : *
5170 : * @param[in] data The cmsg data to set.
5171 : *
5172 : * @param[in] len the length of the data to set.
5173 : */
5174 0 : static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5175 : int level,
5176 : int type,
5177 : const void *data,
5178 : size_t len)
5179 0 : {
5180 0 : size_t cmlen = CMSG_LEN(len);
5181 0 : size_t cmspace = CMSG_SPACE(len);
5182 0 : uint8_t cmbuf[cmspace];
5183 0 : void *cast_ptr = (void *)cmbuf;
5184 0 : struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5185 : uint8_t *p;
5186 :
5187 0 : memset(cmbuf, 0, cmspace);
5188 :
5189 0 : if (msg->msg_controllen < cmlen) {
5190 0 : cmlen = msg->msg_controllen;
5191 0 : msg->msg_flags |= MSG_CTRUNC;
5192 : }
5193 :
5194 0 : if (msg->msg_controllen < cmspace) {
5195 0 : cmspace = msg->msg_controllen;
5196 : }
5197 :
5198 : /*
5199 : * We copy the full input data into an intermediate cmsghdr first
5200 : * in order to more easily cope with truncation.
5201 : */
5202 0 : cm->cmsg_len = cmlen;
5203 0 : cm->cmsg_level = level;
5204 0 : cm->cmsg_type = type;
5205 0 : memcpy(CMSG_DATA(cm), data, len);
5206 :
5207 : /*
5208 : * We now copy the possibly truncated buffer.
5209 : * We copy cmlen bytes, but consume cmspace bytes,
5210 : * leaving the possible padding uninitialiazed.
5211 : */
5212 0 : p = (uint8_t *)msg->msg_control;
5213 0 : memcpy(p, cm, cmlen);
5214 0 : p += cmspace;
5215 0 : msg->msg_control = p;
5216 0 : msg->msg_controllen -= cmspace;
5217 :
5218 0 : return;
5219 : }
5220 :
5221 0 : static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5222 : struct msghdr *msg)
5223 : {
5224 : /* Add packet info */
5225 0 : switch (si->pktinfo) {
5226 : #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5227 0 : case AF_INET: {
5228 : struct sockaddr_in *sin;
5229 : #if defined(HAVE_STRUCT_IN_PKTINFO)
5230 : struct in_pktinfo pkt;
5231 : #elif defined(IP_RECVDSTADDR)
5232 : struct in_addr pkt;
5233 : #endif
5234 :
5235 0 : if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5236 0 : sin = &si->bindname.sa.in;
5237 : } else {
5238 0 : if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5239 0 : return 0;
5240 : }
5241 0 : sin = &si->myname.sa.in;
5242 : }
5243 :
5244 0 : ZERO_STRUCT(pkt);
5245 :
5246 : #if defined(HAVE_STRUCT_IN_PKTINFO)
5247 0 : pkt.ipi_ifindex = socket_wrapper_default_iface();
5248 0 : pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5249 : #elif defined(IP_RECVDSTADDR)
5250 : pkt = sin->sin_addr;
5251 : #endif
5252 :
5253 0 : swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5254 : &pkt, sizeof(pkt));
5255 :
5256 0 : break;
5257 : }
5258 : #endif /* IP_PKTINFO */
5259 : #if defined(HAVE_IPV6)
5260 0 : case AF_INET6: {
5261 : #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5262 : struct sockaddr_in6 *sin6;
5263 : struct in6_pktinfo pkt6;
5264 :
5265 0 : if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5266 0 : sin6 = &si->bindname.sa.in6;
5267 : } else {
5268 0 : if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5269 0 : return 0;
5270 : }
5271 0 : sin6 = &si->myname.sa.in6;
5272 : }
5273 :
5274 0 : ZERO_STRUCT(pkt6);
5275 :
5276 0 : pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5277 0 : pkt6.ipi6_addr = sin6->sin6_addr;
5278 :
5279 0 : swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5280 : &pkt6, sizeof(pkt6));
5281 : #endif /* HAVE_STRUCT_IN6_PKTINFO */
5282 :
5283 0 : break;
5284 : }
5285 : #endif /* IPV6_PKTINFO */
5286 0 : default:
5287 0 : return -1;
5288 : }
5289 :
5290 0 : return 0;
5291 : }
5292 :
5293 0 : static int swrap_msghdr_add_socket_info(struct socket_info *si,
5294 : struct msghdr *omsg)
5295 : {
5296 0 : int rc = 0;
5297 :
5298 0 : if (si->pktinfo > 0) {
5299 0 : rc = swrap_msghdr_add_pktinfo(si, omsg);
5300 : }
5301 :
5302 0 : return rc;
5303 : }
5304 :
5305 : static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5306 : uint8_t **cm_data,
5307 : size_t *cm_data_space);
5308 : static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5309 : uint8_t **cm_data,
5310 : size_t *cm_data_space);
5311 : static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5312 : uint8_t **cm_data,
5313 : size_t *cm_data_space);
5314 :
5315 0 : static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5316 : uint8_t **cm_data,
5317 : size_t *cm_data_space)
5318 : {
5319 0 : struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5320 : struct cmsghdr *cmsg;
5321 0 : int rc = -1;
5322 :
5323 : /* Nothing to do */
5324 0 : if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5325 0 : return 0;
5326 : }
5327 :
5328 0 : for (cmsg = CMSG_FIRSTHDR(msg);
5329 0 : cmsg != NULL;
5330 0 : cmsg = CMSG_NXTHDR(msg, cmsg)) {
5331 0 : switch (cmsg->cmsg_level) {
5332 0 : case IPPROTO_IP:
5333 0 : rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5334 : cm_data,
5335 : cm_data_space);
5336 0 : break;
5337 0 : case SOL_SOCKET:
5338 0 : rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5339 : cm_data,
5340 : cm_data_space);
5341 0 : break;
5342 0 : default:
5343 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
5344 : cm_data,
5345 : cm_data_space);
5346 0 : break;
5347 : }
5348 0 : if (rc < 0) {
5349 0 : int saved_errno = errno;
5350 0 : SAFE_FREE(*cm_data);
5351 0 : *cm_data_space = 0;
5352 0 : errno = saved_errno;
5353 0 : return rc;
5354 : }
5355 : }
5356 :
5357 0 : return rc;
5358 : }
5359 :
5360 0 : static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5361 : uint8_t **cm_data,
5362 : size_t *cm_data_space)
5363 : {
5364 : size_t cmspace;
5365 : uint8_t *p;
5366 :
5367 0 : cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5368 :
5369 0 : p = realloc((*cm_data), cmspace);
5370 0 : if (p == NULL) {
5371 0 : return -1;
5372 : }
5373 0 : (*cm_data) = p;
5374 :
5375 0 : p = (*cm_data) + (*cm_data_space);
5376 0 : *cm_data_space = cmspace;
5377 :
5378 0 : memcpy(p, cmsg, cmsg->cmsg_len);
5379 :
5380 0 : return 0;
5381 : }
5382 :
5383 : static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5384 : uint8_t **cm_data,
5385 : size_t *cm_data_space);
5386 :
5387 :
5388 0 : static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5389 : uint8_t **cm_data,
5390 : size_t *cm_data_space)
5391 : {
5392 0 : int rc = -1;
5393 :
5394 0 : switch(cmsg->cmsg_type) {
5395 : #ifdef IP_PKTINFO
5396 0 : case IP_PKTINFO:
5397 0 : rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5398 : cm_data,
5399 : cm_data_space);
5400 0 : break;
5401 : #endif
5402 : #ifdef IPV6_PKTINFO
5403 0 : case IPV6_PKTINFO:
5404 0 : rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5405 : cm_data,
5406 : cm_data_space);
5407 0 : break;
5408 : #endif
5409 0 : default:
5410 0 : break;
5411 : }
5412 :
5413 0 : return rc;
5414 : }
5415 :
5416 0 : static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5417 : uint8_t **cm_data,
5418 : size_t *cm_data_space)
5419 : {
5420 : (void)cmsg; /* unused */
5421 : (void)cm_data; /* unused */
5422 : (void)cm_data_space; /* unused */
5423 :
5424 : /*
5425 : * Passing a IP pktinfo to a unix socket might be rejected by the
5426 : * Kernel, at least on FreeBSD. So skip this cmsg.
5427 : */
5428 0 : return 0;
5429 : }
5430 :
5431 0 : static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5432 : uint8_t **cm_data,
5433 : size_t *cm_data_space)
5434 : {
5435 0 : int rc = -1;
5436 :
5437 0 : switch (cmsg->cmsg_type) {
5438 0 : case SCM_RIGHTS:
5439 0 : SWRAP_LOG(SWRAP_LOG_TRACE,
5440 : "Ignoring SCM_RIGHTS on inet socket!");
5441 0 : rc = 0;
5442 0 : break;
5443 : #ifdef SCM_CREDENTIALS
5444 0 : case SCM_CREDENTIALS:
5445 0 : SWRAP_LOG(SWRAP_LOG_TRACE,
5446 : "Ignoring SCM_CREDENTIALS on inet socket!");
5447 0 : rc = 0;
5448 0 : break;
5449 : #endif /* SCM_CREDENTIALS */
5450 0 : default:
5451 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
5452 : cm_data,
5453 : cm_data_space);
5454 0 : break;
5455 : }
5456 :
5457 0 : return rc;
5458 : }
5459 :
5460 : static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5461 :
5462 : /*
5463 : * We only allow up to 6 fds at a time
5464 : * as that's more than enough for Samba
5465 : * and it means we can keep the logic simple
5466 : * and work with fixed size arrays.
5467 : *
5468 : * We also keep sizeof(struct swrap_unix_scm_rights)
5469 : * under PIPE_BUF (4096) in order to allow a non-blocking
5470 : * write into the pipe.
5471 : */
5472 : #ifndef PIPE_BUF
5473 : #define PIPE_BUF 4096
5474 : #endif
5475 : #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5476 : #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5477 : struct swrap_unix_scm_rights_payload {
5478 : uint8_t num_idxs;
5479 : int8_t idxs[SWRAP_MAX_PASSED_FDS];
5480 : struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5481 : };
5482 : struct swrap_unix_scm_rights {
5483 : uint64_t magic;
5484 : char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5485 : char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5486 : uint32_t full_size;
5487 : uint32_t payload_size;
5488 : struct swrap_unix_scm_rights_payload payload;
5489 : };
5490 :
5491 0 : static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5492 : {
5493 0 : int saved_errno = errno;
5494 : size_t i;
5495 :
5496 0 : for (i = 0; i < num; i++) {
5497 0 : struct socket_info *si = array[i];
5498 0 : if (si == NULL) {
5499 0 : continue;
5500 : }
5501 :
5502 0 : SWRAP_LOCK_SI(si);
5503 0 : swrap_dec_refcount(si);
5504 0 : if (si->fd_passed > 0) {
5505 0 : si->fd_passed -= 1;
5506 : }
5507 0 : SWRAP_UNLOCK_SI(si);
5508 0 : array[i] = NULL;
5509 : }
5510 :
5511 0 : errno = saved_errno;
5512 0 : }
5513 :
5514 0 : static void swrap_undo_si_idx_array(size_t num, int *array)
5515 : {
5516 0 : int saved_errno = errno;
5517 : size_t i;
5518 :
5519 0 : swrap_mutex_lock(&first_free_mutex);
5520 :
5521 0 : for (i = 0; i < num; i++) {
5522 0 : struct socket_info *si = NULL;
5523 :
5524 0 : if (array[i] == -1) {
5525 0 : continue;
5526 : }
5527 :
5528 0 : si = swrap_get_socket_info(array[i]);
5529 0 : if (si == NULL) {
5530 0 : continue;
5531 : }
5532 :
5533 0 : SWRAP_LOCK_SI(si);
5534 0 : swrap_dec_refcount(si);
5535 0 : SWRAP_UNLOCK_SI(si);
5536 :
5537 0 : swrap_set_next_free(si, first_free);
5538 0 : first_free = array[i];
5539 0 : array[i] = -1;
5540 : }
5541 :
5542 0 : swrap_mutex_unlock(&first_free_mutex);
5543 0 : errno = saved_errno;
5544 0 : }
5545 :
5546 0 : static void swrap_close_fd_array(size_t num, const int *array)
5547 : {
5548 0 : int saved_errno = errno;
5549 : size_t i;
5550 :
5551 0 : for (i = 0; i < num; i++) {
5552 0 : if (array[i] == -1) {
5553 0 : continue;
5554 : }
5555 0 : libc_close(array[i]);
5556 : }
5557 :
5558 0 : errno = saved_errno;
5559 0 : }
5560 :
5561 : union __swrap_fds {
5562 : const uint8_t *p;
5563 : int *fds;
5564 : };
5565 :
5566 : union __swrap_cmsghdr {
5567 : const uint8_t *p;
5568 : struct cmsghdr *cmsg;
5569 : };
5570 :
5571 848 : static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5572 : uint8_t **cm_data,
5573 : size_t *cm_data_space,
5574 : int *scm_rights_pipe_fd)
5575 : {
5576 : struct swrap_unix_scm_rights info;
5577 848 : struct swrap_unix_scm_rights_payload *payload = NULL;
5578 : int si_idx_array[SWRAP_MAX_PASSED_FDS];
5579 848 : struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5580 848 : size_t info_idx = 0;
5581 : size_t size_fds_in;
5582 : size_t num_fds_in;
5583 848 : union __swrap_fds __fds_in = { .p = NULL, };
5584 848 : const int *fds_in = NULL;
5585 : size_t num_fds_out;
5586 : size_t size_fds_out;
5587 848 : union __swrap_fds __fds_out = { .p = NULL, };
5588 848 : int *fds_out = NULL;
5589 : size_t cmsg_len;
5590 : size_t cmsg_space;
5591 : size_t new_cm_data_space;
5592 848 : union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5593 848 : struct cmsghdr *new_cmsg = NULL;
5594 848 : uint8_t *p = NULL;
5595 : size_t i;
5596 848 : int pipefd[2] = { -1, -1 };
5597 : int rc;
5598 : ssize_t sret;
5599 :
5600 : /*
5601 : * We pass this a buffer to the kernel make sure any padding
5602 : * is also cleared.
5603 : */
5604 848 : ZERO_STRUCT(info);
5605 848 : info.magic = swrap_unix_scm_right_magic;
5606 848 : memcpy(info.package_name,
5607 : SOCKET_WRAPPER_PACKAGE,
5608 : sizeof(info.package_name));
5609 848 : memcpy(info.package_version,
5610 : SOCKET_WRAPPER_VERSION,
5611 : sizeof(info.package_version));
5612 848 : info.full_size = sizeof(info);
5613 848 : info.payload_size = sizeof(info.payload);
5614 848 : payload = &info.payload;
5615 :
5616 848 : if (*scm_rights_pipe_fd != -1) {
5617 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5618 : "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5619 0 : errno = EINVAL;
5620 0 : return -1;
5621 : }
5622 :
5623 848 : if (cmsg->cmsg_len < CMSG_LEN(0)) {
5624 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5625 : "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5626 : (size_t)cmsg->cmsg_len,
5627 : CMSG_LEN(0));
5628 0 : errno = EINVAL;
5629 0 : return -1;
5630 : }
5631 848 : size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5632 848 : if ((size_fds_in % sizeof(int)) != 0) {
5633 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5634 : "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5635 : (size_t)cmsg->cmsg_len,
5636 : size_fds_in,
5637 : sizeof(int));
5638 0 : errno = EINVAL;
5639 0 : return -1;
5640 : }
5641 848 : num_fds_in = size_fds_in / sizeof(int);
5642 848 : if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5643 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5644 : "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5645 : "num_fds_in=%zu > "
5646 : "SWRAP_MAX_PASSED_FDS(%zu)",
5647 : (size_t)cmsg->cmsg_len,
5648 : size_fds_in,
5649 : num_fds_in,
5650 : SWRAP_MAX_PASSED_FDS);
5651 0 : errno = EINVAL;
5652 0 : return -1;
5653 : }
5654 848 : if (num_fds_in == 0) {
5655 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5656 : "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5657 : "num_fds_in=%zu",
5658 : (size_t)cmsg->cmsg_len,
5659 : size_fds_in,
5660 : num_fds_in);
5661 0 : errno = EINVAL;
5662 0 : return -1;
5663 : }
5664 848 : __fds_in.p = CMSG_DATA(cmsg);
5665 848 : fds_in = __fds_in.fds;
5666 848 : num_fds_out = num_fds_in + 1;
5667 :
5668 848 : SWRAP_LOG(SWRAP_LOG_TRACE,
5669 : "num_fds_in=%zu num_fds_out=%zu",
5670 : num_fds_in, num_fds_out);
5671 :
5672 848 : size_fds_out = sizeof(int) * num_fds_out;
5673 848 : cmsg_len = CMSG_LEN(size_fds_out);
5674 848 : cmsg_space = CMSG_SPACE(size_fds_out);
5675 :
5676 848 : new_cm_data_space = *cm_data_space + cmsg_space;
5677 :
5678 848 : p = realloc((*cm_data), new_cm_data_space);
5679 848 : if (p == NULL) {
5680 0 : return -1;
5681 : }
5682 848 : (*cm_data) = p;
5683 848 : p = (*cm_data) + (*cm_data_space);
5684 848 : memset(p, 0, cmsg_space);
5685 848 : __new_cmsg.p = p;
5686 848 : new_cmsg = __new_cmsg.cmsg;
5687 848 : *new_cmsg = *cmsg;
5688 848 : __fds_out.p = CMSG_DATA(new_cmsg);
5689 848 : fds_out = __fds_out.fds;
5690 848 : memcpy(fds_out, fds_in, size_fds_in);
5691 848 : new_cmsg->cmsg_len = cmsg->cmsg_len;
5692 :
5693 1696 : for (i = 0; i < num_fds_in; i++) {
5694 : size_t j;
5695 :
5696 848 : payload->idxs[i] = -1;
5697 848 : payload->num_idxs++;
5698 :
5699 848 : si_idx_array[i] = find_socket_info_index(fds_in[i]);
5700 848 : if (si_idx_array[i] == -1) {
5701 424 : continue;
5702 : }
5703 :
5704 424 : si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5705 424 : if (si_array[i] == NULL) {
5706 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5707 : "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5708 : i, fds_in[i], i, si_idx_array[i]);
5709 0 : errno = EINVAL;
5710 0 : return -1;
5711 : }
5712 :
5713 424 : for (j = 0; j < i; j++) {
5714 0 : if (si_array[j] == si_array[i]) {
5715 0 : payload->idxs[i] = payload->idxs[j];
5716 0 : break;
5717 : }
5718 : }
5719 424 : if (payload->idxs[i] == -1) {
5720 424 : if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5721 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5722 : "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5723 : "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5724 : i, fds_in[i], i, si_idx_array[i],
5725 : info_idx,
5726 : SWRAP_MAX_PASSED_SOCKET_INFO);
5727 0 : errno = EINVAL;
5728 0 : return -1;
5729 : }
5730 424 : payload->idxs[i] = info_idx;
5731 424 : info_idx += 1;
5732 424 : continue;
5733 : }
5734 : }
5735 :
5736 1696 : for (i = 0; i < num_fds_in; i++) {
5737 848 : struct socket_info *si = si_array[i];
5738 :
5739 848 : if (si == NULL) {
5740 424 : SWRAP_LOG(SWRAP_LOG_TRACE,
5741 : "fds_in[%zu]=%d not an inet socket",
5742 : i, fds_in[i]);
5743 424 : continue;
5744 : }
5745 :
5746 424 : SWRAP_LOG(SWRAP_LOG_TRACE,
5747 : "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5748 : "passing as info.idxs[%zu]=%d!",
5749 : i, fds_in[i],
5750 : i, si_idx_array[i],
5751 : i, payload->idxs[i]);
5752 :
5753 424 : SWRAP_LOCK_SI(si);
5754 424 : si->fd_passed += 1;
5755 424 : payload->infos[payload->idxs[i]] = *si;
5756 424 : payload->infos[payload->idxs[i]].fd_passed = 0;
5757 424 : SWRAP_UNLOCK_SI(si);
5758 : }
5759 :
5760 848 : rc = pipe(pipefd);
5761 848 : if (rc == -1) {
5762 0 : int saved_errno = errno;
5763 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5764 : "pipe() failed - %d %s",
5765 : saved_errno,
5766 : strerror(saved_errno));
5767 0 : swrap_dec_fd_passed_array(num_fds_in, si_array);
5768 0 : errno = saved_errno;
5769 0 : return -1;
5770 : }
5771 :
5772 848 : sret = libc_write(pipefd[1], &info, sizeof(info));
5773 848 : if (sret != sizeof(info)) {
5774 0 : int saved_errno = errno;
5775 0 : if (sret != -1) {
5776 0 : saved_errno = EINVAL;
5777 : }
5778 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5779 : "write() failed - sret=%zd - %d %s",
5780 : sret, saved_errno,
5781 : strerror(saved_errno));
5782 0 : swrap_dec_fd_passed_array(num_fds_in, si_array);
5783 0 : libc_close(pipefd[1]);
5784 0 : libc_close(pipefd[0]);
5785 0 : errno = saved_errno;
5786 0 : return -1;
5787 : }
5788 848 : libc_close(pipefd[1]);
5789 :
5790 : /*
5791 : * Add the pipe read end to the end of the passed fd array
5792 : */
5793 848 : fds_out[num_fds_in] = pipefd[0];
5794 848 : new_cmsg->cmsg_len = cmsg_len;
5795 :
5796 : /* we're done ... */
5797 848 : *scm_rights_pipe_fd = pipefd[0];
5798 848 : *cm_data_space = new_cm_data_space;
5799 :
5800 848 : return 0;
5801 : }
5802 :
5803 848 : static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5804 : uint8_t **cm_data,
5805 : size_t *cm_data_space,
5806 : int *scm_rights_pipe_fd)
5807 : {
5808 848 : int rc = -1;
5809 :
5810 848 : switch (cmsg->cmsg_type) {
5811 848 : case SCM_RIGHTS:
5812 848 : rc = swrap_sendmsg_unix_scm_rights(cmsg,
5813 : cm_data,
5814 : cm_data_space,
5815 : scm_rights_pipe_fd);
5816 848 : break;
5817 0 : default:
5818 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
5819 : cm_data,
5820 : cm_data_space);
5821 0 : break;
5822 : }
5823 :
5824 848 : return rc;
5825 : }
5826 :
5827 748 : static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5828 : uint8_t **cm_data,
5829 : size_t *cm_data_space)
5830 : {
5831 748 : int scm_rights_pipe_fd = -1;
5832 : struct swrap_unix_scm_rights info;
5833 748 : struct swrap_unix_scm_rights_payload *payload = NULL;
5834 : int si_idx_array[SWRAP_MAX_PASSED_FDS];
5835 : size_t size_fds_in;
5836 : size_t num_fds_in;
5837 748 : union __swrap_fds __fds_in = { .p = NULL, };
5838 748 : const int *fds_in = NULL;
5839 : size_t num_fds_out;
5840 : size_t size_fds_out;
5841 748 : union __swrap_fds __fds_out = { .p = NULL, };
5842 748 : int *fds_out = NULL;
5843 : size_t cmsg_len;
5844 : size_t cmsg_space;
5845 : size_t new_cm_data_space;
5846 748 : union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5847 748 : struct cmsghdr *new_cmsg = NULL;
5848 748 : uint8_t *p = NULL;
5849 : ssize_t sret;
5850 : size_t i;
5851 : int cmp;
5852 :
5853 748 : if (cmsg->cmsg_len < CMSG_LEN(0)) {
5854 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5855 : "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5856 : (size_t)cmsg->cmsg_len,
5857 : CMSG_LEN(0));
5858 0 : errno = EINVAL;
5859 0 : return -1;
5860 : }
5861 748 : size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5862 748 : if ((size_fds_in % sizeof(int)) != 0) {
5863 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5864 : "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5865 : (size_t)cmsg->cmsg_len,
5866 : size_fds_in,
5867 : sizeof(int));
5868 0 : errno = EINVAL;
5869 0 : return -1;
5870 : }
5871 748 : num_fds_in = size_fds_in / sizeof(int);
5872 748 : if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5873 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5874 : "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5875 : "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5876 : (size_t)cmsg->cmsg_len,
5877 : size_fds_in,
5878 : num_fds_in,
5879 : SWRAP_MAX_PASSED_FDS+1);
5880 0 : errno = EINVAL;
5881 0 : return -1;
5882 : }
5883 748 : if (num_fds_in <= 1) {
5884 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5885 : "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5886 : "num_fds_in=%zu",
5887 : (size_t)cmsg->cmsg_len,
5888 : size_fds_in,
5889 : num_fds_in);
5890 0 : errno = EINVAL;
5891 0 : return -1;
5892 : }
5893 748 : __fds_in.p = CMSG_DATA(cmsg);
5894 748 : fds_in = __fds_in.fds;
5895 748 : num_fds_out = num_fds_in - 1;
5896 :
5897 748 : SWRAP_LOG(SWRAP_LOG_TRACE,
5898 : "num_fds_in=%zu num_fds_out=%zu",
5899 : num_fds_in, num_fds_out);
5900 :
5901 2244 : for (i = 0; i < num_fds_in; i++) {
5902 : /* Check if we have a stale fd and remove it */
5903 1496 : swrap_remove_stale(fds_in[i]);
5904 : }
5905 :
5906 748 : scm_rights_pipe_fd = fds_in[num_fds_out];
5907 748 : size_fds_out = sizeof(int) * num_fds_out;
5908 748 : cmsg_len = CMSG_LEN(size_fds_out);
5909 748 : cmsg_space = CMSG_SPACE(size_fds_out);
5910 :
5911 748 : new_cm_data_space = *cm_data_space + cmsg_space;
5912 :
5913 748 : p = realloc((*cm_data), new_cm_data_space);
5914 748 : if (p == NULL) {
5915 0 : swrap_close_fd_array(num_fds_in, fds_in);
5916 0 : return -1;
5917 : }
5918 748 : (*cm_data) = p;
5919 748 : p = (*cm_data) + (*cm_data_space);
5920 748 : memset(p, 0, cmsg_space);
5921 748 : __new_cmsg.p = p;
5922 748 : new_cmsg = __new_cmsg.cmsg;
5923 748 : *new_cmsg = *cmsg;
5924 748 : __fds_out.p = CMSG_DATA(new_cmsg);
5925 748 : fds_out = __fds_out.fds;
5926 748 : memcpy(fds_out, fds_in, size_fds_out);
5927 748 : new_cmsg->cmsg_len = cmsg_len;
5928 :
5929 748 : sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5930 748 : if (sret != sizeof(info)) {
5931 0 : int saved_errno = errno;
5932 0 : if (sret != -1) {
5933 0 : saved_errno = EINVAL;
5934 : }
5935 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5936 : "read() failed - sret=%zd - %d %s",
5937 : sret, saved_errno,
5938 : strerror(saved_errno));
5939 0 : swrap_close_fd_array(num_fds_in, fds_in);
5940 0 : errno = saved_errno;
5941 0 : return -1;
5942 : }
5943 748 : libc_close(scm_rights_pipe_fd);
5944 748 : payload = &info.payload;
5945 :
5946 748 : if (info.magic != swrap_unix_scm_right_magic) {
5947 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5948 : "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5949 : (unsigned long long)info.magic,
5950 : (unsigned long long)swrap_unix_scm_right_magic);
5951 0 : swrap_close_fd_array(num_fds_out, fds_out);
5952 0 : errno = EINVAL;
5953 0 : return -1;
5954 : }
5955 :
5956 748 : cmp = memcmp(info.package_name,
5957 : SOCKET_WRAPPER_PACKAGE,
5958 : sizeof(info.package_name));
5959 748 : if (cmp != 0) {
5960 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5961 : "info.package_name='%.*s' != '%s'",
5962 : (int)sizeof(info.package_name),
5963 : info.package_name,
5964 : SOCKET_WRAPPER_PACKAGE);
5965 0 : swrap_close_fd_array(num_fds_out, fds_out);
5966 0 : errno = EINVAL;
5967 0 : return -1;
5968 : }
5969 :
5970 748 : cmp = memcmp(info.package_version,
5971 : SOCKET_WRAPPER_VERSION,
5972 : sizeof(info.package_version));
5973 748 : if (cmp != 0) {
5974 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5975 : "info.package_version='%.*s' != '%s'",
5976 : (int)sizeof(info.package_version),
5977 : info.package_version,
5978 : SOCKET_WRAPPER_VERSION);
5979 0 : swrap_close_fd_array(num_fds_out, fds_out);
5980 0 : errno = EINVAL;
5981 0 : return -1;
5982 : }
5983 :
5984 748 : if (info.full_size != sizeof(info)) {
5985 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5986 : "info.full_size=%zu != sizeof(info)=%zu",
5987 : (size_t)info.full_size,
5988 : sizeof(info));
5989 0 : swrap_close_fd_array(num_fds_out, fds_out);
5990 0 : errno = EINVAL;
5991 0 : return -1;
5992 : }
5993 :
5994 748 : if (info.payload_size != sizeof(info.payload)) {
5995 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
5996 : "info.payload_size=%zu != sizeof(info.payload)=%zu",
5997 : (size_t)info.payload_size,
5998 : sizeof(info.payload));
5999 0 : swrap_close_fd_array(num_fds_out, fds_out);
6000 0 : errno = EINVAL;
6001 0 : return -1;
6002 : }
6003 :
6004 748 : if (payload->num_idxs != num_fds_out) {
6005 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6006 : "info.num_idxs=%u != num_fds_out=%zu",
6007 : payload->num_idxs, num_fds_out);
6008 0 : swrap_close_fd_array(num_fds_out, fds_out);
6009 0 : errno = EINVAL;
6010 0 : return -1;
6011 : }
6012 :
6013 1496 : for (i = 0; i < num_fds_out; i++) {
6014 : size_t j;
6015 :
6016 748 : si_idx_array[i] = -1;
6017 :
6018 748 : if (payload->idxs[i] == -1) {
6019 324 : SWRAP_LOG(SWRAP_LOG_TRACE,
6020 : "fds_out[%zu]=%d not an inet socket",
6021 : i, fds_out[i]);
6022 324 : continue;
6023 : }
6024 :
6025 424 : if (payload->idxs[i] < 0) {
6026 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6027 : "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6028 : i, fds_out[i], i, payload->idxs[i]);
6029 0 : swrap_close_fd_array(num_fds_out, fds_out);
6030 0 : errno = EINVAL;
6031 0 : return -1;
6032 : }
6033 :
6034 424 : if (payload->idxs[i] >= payload->num_idxs) {
6035 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6036 : "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6037 : i, fds_out[i], i, payload->idxs[i],
6038 : payload->num_idxs);
6039 0 : swrap_close_fd_array(num_fds_out, fds_out);
6040 0 : errno = EINVAL;
6041 0 : return -1;
6042 : }
6043 :
6044 424 : if ((size_t)fds_out[i] >= socket_fds_max) {
6045 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6046 : "The max socket index limit of %zu has been reached, "
6047 : "trying to add %d",
6048 : socket_fds_max,
6049 : fds_out[i]);
6050 0 : swrap_close_fd_array(num_fds_out, fds_out);
6051 0 : errno = EMFILE;
6052 0 : return -1;
6053 : }
6054 :
6055 424 : SWRAP_LOG(SWRAP_LOG_TRACE,
6056 : "fds_in[%zu]=%d "
6057 : "received as info.idxs[%zu]=%d!",
6058 : i, fds_out[i],
6059 : i, payload->idxs[i]);
6060 :
6061 424 : for (j = 0; j < i; j++) {
6062 0 : if (payload->idxs[j] == -1) {
6063 0 : continue;
6064 : }
6065 0 : if (payload->idxs[j] == payload->idxs[i]) {
6066 0 : si_idx_array[i] = si_idx_array[j];
6067 : }
6068 : }
6069 424 : if (si_idx_array[i] == -1) {
6070 424 : const struct socket_info *si = &payload->infos[payload->idxs[i]];
6071 :
6072 424 : si_idx_array[i] = swrap_add_socket_info(si);
6073 424 : if (si_idx_array[i] == -1) {
6074 0 : int saved_errno = errno;
6075 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6076 : "The max socket index limit of %zu has been reached, "
6077 : "trying to add %d",
6078 : socket_fds_max,
6079 : fds_out[i]);
6080 0 : swrap_undo_si_idx_array(i, si_idx_array);
6081 0 : swrap_close_fd_array(num_fds_out, fds_out);
6082 0 : errno = saved_errno;
6083 0 : return -1;
6084 : }
6085 424 : SWRAP_LOG(SWRAP_LOG_TRACE,
6086 : "Imported %s socket for protocol %s, fd=%d",
6087 : si->family == AF_INET ? "IPv4" : "IPv6",
6088 : si->type == SOCK_DGRAM ? "UDP" : "TCP",
6089 : fds_out[i]);
6090 : }
6091 : }
6092 :
6093 1496 : for (i = 0; i < num_fds_out; i++) {
6094 748 : if (si_idx_array[i] == -1) {
6095 324 : continue;
6096 : }
6097 424 : set_socket_info_index(fds_out[i], si_idx_array[i]);
6098 : }
6099 :
6100 : /* we're done ... */
6101 748 : *cm_data_space = new_cm_data_space;
6102 :
6103 748 : return 0;
6104 : }
6105 :
6106 748 : static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6107 : uint8_t **cm_data,
6108 : size_t *cm_data_space)
6109 : {
6110 748 : int rc = -1;
6111 :
6112 748 : switch (cmsg->cmsg_type) {
6113 748 : case SCM_RIGHTS:
6114 748 : rc = swrap_recvmsg_unix_scm_rights(cmsg,
6115 : cm_data,
6116 : cm_data_space);
6117 748 : break;
6118 0 : default:
6119 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
6120 : cm_data,
6121 : cm_data_space);
6122 0 : break;
6123 : }
6124 :
6125 748 : return rc;
6126 : }
6127 :
6128 : #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6129 :
6130 20686 : static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6131 : struct msghdr *msg_tmp,
6132 : int *scm_rights_pipe_fd)
6133 : {
6134 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6135 20686 : struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6136 20686 : struct cmsghdr *cmsg = NULL;
6137 20686 : uint8_t *cm_data = NULL;
6138 20686 : size_t cm_data_space = 0;
6139 20686 : int rc = -1;
6140 :
6141 20686 : *msg_tmp = *msg_in;
6142 20686 : *scm_rights_pipe_fd = -1;
6143 :
6144 : /* Nothing to do */
6145 20686 : if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6146 19838 : return 0;
6147 : }
6148 :
6149 848 : for (cmsg = CMSG_FIRSTHDR(msg_in);
6150 1696 : cmsg != NULL;
6151 848 : cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6152 848 : switch (cmsg->cmsg_level) {
6153 848 : case SOL_SOCKET:
6154 848 : rc = swrap_sendmsg_unix_sol_socket(cmsg,
6155 : &cm_data,
6156 : &cm_data_space,
6157 : scm_rights_pipe_fd);
6158 848 : break;
6159 :
6160 0 : default:
6161 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
6162 : &cm_data,
6163 : &cm_data_space);
6164 0 : break;
6165 : }
6166 848 : if (rc < 0) {
6167 0 : int saved_errno = errno;
6168 0 : SAFE_FREE(cm_data);
6169 0 : errno = saved_errno;
6170 0 : return rc;
6171 : }
6172 : }
6173 :
6174 848 : msg_tmp->msg_controllen = cm_data_space;
6175 848 : msg_tmp->msg_control = cm_data;
6176 :
6177 848 : return 0;
6178 : #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6179 : *msg_tmp = *_msg_in;
6180 : return 0;
6181 : #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6182 : }
6183 :
6184 20686 : static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6185 : ssize_t ret,
6186 : int scm_rights_pipe_fd)
6187 : {
6188 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6189 20686 : int saved_errno = errno;
6190 20686 : SAFE_FREE(msg_tmp->msg_control);
6191 20686 : if (scm_rights_pipe_fd != -1) {
6192 848 : libc_close(scm_rights_pipe_fd);
6193 : }
6194 20686 : errno = saved_errno;
6195 : #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6196 20686 : return ret;
6197 : }
6198 :
6199 17144 : static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6200 : struct msghdr *msg_tmp,
6201 : uint8_t **tmp_control)
6202 : {
6203 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6204 17144 : const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6205 17144 : uint8_t *cm_data = NULL;
6206 17144 : size_t cm_data_space = 0;
6207 :
6208 17144 : *msg_tmp = *msg_in;
6209 17144 : *tmp_control = NULL;
6210 :
6211 17144 : SWRAP_LOG(SWRAP_LOG_TRACE,
6212 : "msg_in->msg_controllen=%zu",
6213 : (size_t)msg_in->msg_controllen);
6214 :
6215 : /* Nothing to do */
6216 17144 : if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6217 0 : return 0;
6218 : }
6219 :
6220 : /*
6221 : * We need to give the kernel a bit more space in order
6222 : * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6223 : * swrap_recvmsg_after_unix() will hide it again.
6224 : */
6225 17144 : cm_data_space = msg_in->msg_controllen;
6226 17144 : if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6227 17144 : cm_data_space += cm_extra_space;
6228 : }
6229 17144 : cm_data = calloc(1, cm_data_space);
6230 17144 : if (cm_data == NULL) {
6231 0 : return -1;
6232 : }
6233 :
6234 17144 : msg_tmp->msg_controllen = cm_data_space;
6235 17144 : msg_tmp->msg_control = cm_data;
6236 17144 : *tmp_control = cm_data;
6237 :
6238 17144 : SWRAP_LOG(SWRAP_LOG_TRACE,
6239 : "msg_tmp->msg_controllen=%zu",
6240 : (size_t)msg_tmp->msg_controllen);
6241 17144 : return 0;
6242 : #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6243 : *msg_tmp = *msg_in;
6244 : *tmp_control = NULL;
6245 : return 0;
6246 : #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6247 : }
6248 :
6249 17144 : static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6250 : uint8_t **tmp_control,
6251 : struct msghdr *msg_out,
6252 : ssize_t ret)
6253 : {
6254 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6255 17144 : struct cmsghdr *cmsg = NULL;
6256 17144 : uint8_t *cm_data = NULL;
6257 17144 : size_t cm_data_space = 0;
6258 17144 : int rc = -1;
6259 :
6260 17144 : if (ret < 0) {
6261 0 : int saved_errno = errno;
6262 0 : SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6263 : saved_errno, strerror(saved_errno));
6264 0 : SAFE_FREE(*tmp_control);
6265 : /* msg_out should not be touched on error */
6266 0 : errno = saved_errno;
6267 0 : return ret;
6268 : }
6269 :
6270 17144 : SWRAP_LOG(SWRAP_LOG_TRACE,
6271 : "msg_tmp->msg_controllen=%zu",
6272 : (size_t)msg_tmp->msg_controllen);
6273 :
6274 : /* Nothing to do */
6275 17144 : if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6276 16396 : int saved_errno = errno;
6277 16396 : *msg_out = *msg_tmp;
6278 16396 : SAFE_FREE(*tmp_control);
6279 16396 : errno = saved_errno;
6280 16396 : return ret;
6281 : }
6282 :
6283 748 : for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6284 1496 : cmsg != NULL;
6285 748 : cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6286 748 : switch (cmsg->cmsg_level) {
6287 748 : case SOL_SOCKET:
6288 748 : rc = swrap_recvmsg_unix_sol_socket(cmsg,
6289 : &cm_data,
6290 : &cm_data_space);
6291 748 : break;
6292 :
6293 0 : default:
6294 0 : rc = swrap_sendmsg_copy_cmsg(cmsg,
6295 : &cm_data,
6296 : &cm_data_space);
6297 0 : break;
6298 : }
6299 748 : if (rc < 0) {
6300 0 : int saved_errno = errno;
6301 0 : SAFE_FREE(cm_data);
6302 0 : SAFE_FREE(*tmp_control);
6303 0 : errno = saved_errno;
6304 0 : return rc;
6305 : }
6306 : }
6307 :
6308 : /*
6309 : * msg_tmp->msg_control (*tmp_control) was created by
6310 : * swrap_recvmsg_before_unix() and msg_out->msg_control
6311 : * is still the buffer of the caller.
6312 : */
6313 748 : msg_tmp->msg_control = msg_out->msg_control;
6314 748 : msg_tmp->msg_controllen = msg_out->msg_controllen;
6315 748 : *msg_out = *msg_tmp;
6316 :
6317 748 : cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6318 748 : memcpy(msg_out->msg_control, cm_data, cm_data_space);
6319 748 : msg_out->msg_controllen = cm_data_space;
6320 748 : SAFE_FREE(cm_data);
6321 748 : SAFE_FREE(*tmp_control);
6322 :
6323 748 : SWRAP_LOG(SWRAP_LOG_TRACE,
6324 : "msg_out->msg_controllen=%zu",
6325 : (size_t)msg_out->msg_controllen);
6326 748 : return ret;
6327 : #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6328 : int saved_errno = errno;
6329 : *msg_out = *msg_tmp;
6330 : SAFE_FREE(*tmp_control);
6331 : errno = saved_errno;
6332 : return ret;
6333 : #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6334 : }
6335 :
6336 21829016 : static ssize_t swrap_sendmsg_before(int fd,
6337 : struct socket_info *si,
6338 : struct msghdr *msg,
6339 : struct iovec *tmp_iov,
6340 : struct sockaddr_un *tmp_un,
6341 : const struct sockaddr_un **to_un,
6342 : const struct sockaddr **to,
6343 : int *bcast)
6344 : {
6345 21829016 : size_t i, len = 0;
6346 21829016 : ssize_t ret = -1;
6347 21829016 : struct swrap_sockaddr_buf buf = {};
6348 :
6349 21829016 : if (to_un) {
6350 320294 : *to_un = NULL;
6351 : }
6352 21829016 : if (to) {
6353 320294 : *to = NULL;
6354 : }
6355 21829016 : if (bcast) {
6356 320294 : *bcast = 0;
6357 : }
6358 :
6359 21829016 : SWRAP_LOCK_SI(si);
6360 :
6361 21829016 : switch (si->type) {
6362 8694329 : case SOCK_STREAM: {
6363 : unsigned long mtu;
6364 :
6365 8694329 : if (!si->connected) {
6366 0 : errno = ENOTCONN;
6367 0 : goto out;
6368 : }
6369 :
6370 8694329 : if (msg->msg_iovlen == 0) {
6371 0 : break;
6372 : }
6373 :
6374 8694329 : mtu = socket_wrapper_mtu();
6375 17430365 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6376 : size_t nlen;
6377 13838492 : nlen = len + msg->msg_iov[i].iov_len;
6378 13838492 : if (nlen < len) {
6379 : /* overflow */
6380 0 : errno = EMSGSIZE;
6381 0 : goto out;
6382 : }
6383 13838492 : if (nlen > mtu) {
6384 5102456 : break;
6385 : }
6386 : }
6387 8694329 : msg->msg_iovlen = i;
6388 8694329 : if (msg->msg_iovlen == 0) {
6389 4984487 : *tmp_iov = msg->msg_iov[0];
6390 4984487 : tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6391 : (size_t)mtu);
6392 4984487 : msg->msg_iov = tmp_iov;
6393 4984487 : msg->msg_iovlen = 1;
6394 : }
6395 8694329 : break;
6396 : }
6397 13134687 : case SOCK_DGRAM:
6398 13134687 : if (si->connected) {
6399 13099601 : if (msg->msg_name != NULL) {
6400 : /*
6401 : * We are dealing with unix sockets and if we
6402 : * are connected, we should only talk to the
6403 : * connected unix path. Using the fd to send
6404 : * to another server would be hard to achieve.
6405 : */
6406 0 : msg->msg_name = NULL;
6407 0 : msg->msg_namelen = 0;
6408 : }
6409 13099601 : SWRAP_LOG(SWRAP_LOG_TRACE,
6410 : "connected(%s) fd=%d",
6411 : swrap_sockaddr_string(&buf, &si->peername.sa.s),
6412 : fd);
6413 : } else {
6414 : const struct sockaddr *msg_name;
6415 35086 : msg_name = (const struct sockaddr *)msg->msg_name;
6416 :
6417 35086 : if (msg_name == NULL) {
6418 0 : errno = ENOTCONN;
6419 0 : goto out;
6420 : }
6421 :
6422 :
6423 35086 : ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6424 : tmp_un, 0, bcast);
6425 35086 : if (ret == -1) {
6426 6546 : goto out;
6427 : }
6428 :
6429 28540 : if (to_un) {
6430 28540 : *to_un = tmp_un;
6431 : }
6432 28540 : if (to) {
6433 28540 : *to = msg_name;
6434 : }
6435 28540 : msg->msg_name = tmp_un;
6436 28540 : msg->msg_namelen = sizeof(*tmp_un);
6437 : }
6438 :
6439 13128141 : if (si->bound == 0) {
6440 1316 : ret = swrap_auto_bind(fd, si, si->family);
6441 1316 : if (ret == -1) {
6442 0 : SWRAP_UNLOCK_SI(si);
6443 0 : if (errno == ENOTSOCK) {
6444 0 : swrap_remove_stale(fd);
6445 0 : ret = -ENOTSOCK;
6446 : } else {
6447 0 : SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6448 : }
6449 0 : return ret;
6450 : }
6451 : }
6452 :
6453 13128141 : if (!si->defer_connect) {
6454 28867 : break;
6455 : }
6456 :
6457 26198548 : ret = sockaddr_convert_to_un(si,
6458 13099274 : &si->peername.sa.s,
6459 : si->peername.sa_socklen,
6460 : tmp_un,
6461 : 0,
6462 : NULL);
6463 13099274 : if (ret == -1) {
6464 0 : goto out;
6465 : }
6466 :
6467 13099274 : SWRAP_LOG(SWRAP_LOG_TRACE,
6468 : "deferred connect(%s) path=%s, fd=%d",
6469 : swrap_sockaddr_string(&buf, &si->peername.sa.s),
6470 : tmp_un->sun_path, fd);
6471 :
6472 13099274 : ret = libc_connect(fd,
6473 : (struct sockaddr *)(void *)tmp_un,
6474 : sizeof(*tmp_un));
6475 :
6476 : /* to give better errors */
6477 13099274 : if (ret == -1 && errno == ENOENT) {
6478 13076846 : errno = EHOSTUNREACH;
6479 : }
6480 :
6481 13099274 : if (ret == -1) {
6482 13076880 : goto out;
6483 : }
6484 :
6485 22394 : si->defer_connect = 0;
6486 22394 : break;
6487 0 : default:
6488 0 : errno = EHOSTUNREACH;
6489 0 : goto out;
6490 : }
6491 :
6492 8745590 : ret = 0;
6493 21829016 : out:
6494 21829016 : SWRAP_UNLOCK_SI(si);
6495 :
6496 21829016 : return ret;
6497 : }
6498 :
6499 8742578 : static void swrap_sendmsg_after(int fd,
6500 : struct socket_info *si,
6501 : struct msghdr *msg,
6502 : const struct sockaddr *to,
6503 : ssize_t ret)
6504 : {
6505 8742578 : int saved_errno = errno;
6506 8742578 : size_t i, len = 0;
6507 : uint8_t *buf;
6508 8742578 : off_t ofs = 0;
6509 8742578 : size_t avail = 0;
6510 : size_t remain;
6511 :
6512 : /* to give better errors */
6513 8742578 : if (ret == -1) {
6514 3015 : if (saved_errno == ENOENT) {
6515 51 : saved_errno = EHOSTUNREACH;
6516 2964 : } else if (saved_errno == ENOTSOCK) {
6517 : /* If the fd is not a socket, remove it */
6518 0 : swrap_remove_stale(fd);
6519 : }
6520 : }
6521 :
6522 22511412 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6523 13768834 : avail += msg->msg_iov[i].iov_len;
6524 : }
6525 :
6526 8742578 : if (ret == -1) {
6527 3015 : remain = MIN(80, avail);
6528 : } else {
6529 8739563 : remain = ret;
6530 : }
6531 :
6532 : /* we capture it as one single packet */
6533 8742578 : buf = (uint8_t *)malloc(remain);
6534 8742578 : if (!buf) {
6535 : /* we just not capture the packet */
6536 0 : errno = saved_errno;
6537 0 : return;
6538 : }
6539 :
6540 22511412 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6541 13768834 : size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6542 13768834 : if (this_time > 0) {
6543 13181716 : memcpy(buf + ofs,
6544 13181716 : msg->msg_iov[i].iov_base,
6545 : this_time);
6546 : }
6547 13768834 : ofs += this_time;
6548 13768834 : remain -= this_time;
6549 : }
6550 8742578 : len = ofs;
6551 :
6552 8742578 : SWRAP_LOCK_SI(si);
6553 :
6554 8742578 : switch (si->type) {
6555 8694329 : case SOCK_STREAM:
6556 8694329 : if (ret == -1) {
6557 2955 : swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6558 2955 : swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6559 : } else {
6560 8691374 : swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6561 : }
6562 8694329 : break;
6563 :
6564 48249 : case SOCK_DGRAM:
6565 48249 : if (si->connected) {
6566 22721 : to = &si->peername.sa.s;
6567 : }
6568 48249 : if (ret == -1) {
6569 60 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6570 60 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6571 : } else {
6572 48189 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6573 : }
6574 48249 : break;
6575 : }
6576 :
6577 8742578 : SWRAP_UNLOCK_SI(si);
6578 :
6579 8742578 : free(buf);
6580 8742578 : errno = saved_errno;
6581 : }
6582 :
6583 13788528 : static int swrap_recvmsg_before(int fd,
6584 : struct socket_info *si,
6585 : struct msghdr *msg,
6586 : struct iovec *tmp_iov)
6587 : {
6588 13788528 : size_t i, len = 0;
6589 13788528 : int ret = -1;
6590 :
6591 13788528 : SWRAP_LOCK_SI(si);
6592 :
6593 : (void)fd; /* unused */
6594 :
6595 13788528 : switch (si->type) {
6596 13722835 : case SOCK_STREAM: {
6597 : unsigned int mtu;
6598 13722835 : if (!si->connected) {
6599 0 : errno = ENOTCONN;
6600 0 : goto out;
6601 : }
6602 :
6603 13722835 : if (msg->msg_iovlen == 0) {
6604 0 : break;
6605 : }
6606 :
6607 13722835 : mtu = socket_wrapper_mtu();
6608 23237898 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6609 : size_t nlen;
6610 13722835 : nlen = len + msg->msg_iov[i].iov_len;
6611 13722835 : if (nlen > mtu) {
6612 4207772 : break;
6613 : }
6614 : }
6615 13722835 : msg->msg_iovlen = i;
6616 13722835 : if (msg->msg_iovlen == 0) {
6617 4207772 : *tmp_iov = msg->msg_iov[0];
6618 4207772 : tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6619 : (size_t)mtu);
6620 4207772 : msg->msg_iov = tmp_iov;
6621 4207772 : msg->msg_iovlen = 1;
6622 : }
6623 13722835 : break;
6624 : }
6625 65693 : case SOCK_DGRAM:
6626 65693 : if (msg->msg_name == NULL) {
6627 0 : errno = EINVAL;
6628 0 : goto out;
6629 : }
6630 :
6631 65693 : if (msg->msg_iovlen == 0) {
6632 0 : break;
6633 : }
6634 :
6635 65693 : if (si->bound == 0) {
6636 0 : ret = swrap_auto_bind(fd, si, si->family);
6637 0 : if (ret == -1) {
6638 0 : SWRAP_UNLOCK_SI(si);
6639 : /*
6640 : * When attempting to read or write to a
6641 : * descriptor, if an underlying autobind fails
6642 : * because it's not a socket, stop intercepting
6643 : * uses of that descriptor.
6644 : */
6645 0 : if (errno == ENOTSOCK) {
6646 0 : swrap_remove_stale(fd);
6647 0 : ret = -ENOTSOCK;
6648 : } else {
6649 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
6650 : "swrap_recvmsg_before failed");
6651 : }
6652 0 : return ret;
6653 : }
6654 : }
6655 65693 : break;
6656 0 : default:
6657 0 : errno = EHOSTUNREACH;
6658 0 : goto out;
6659 : }
6660 :
6661 13788528 : ret = 0;
6662 13788528 : out:
6663 13788528 : SWRAP_UNLOCK_SI(si);
6664 :
6665 13788528 : return ret;
6666 : }
6667 :
6668 13785295 : static int swrap_recvmsg_after(int fd,
6669 : struct socket_info *si,
6670 : struct msghdr *msg,
6671 : const struct sockaddr_un *un_addr,
6672 : socklen_t un_addrlen,
6673 : ssize_t ret)
6674 : {
6675 13785295 : int saved_errno = errno;
6676 : size_t i;
6677 13785295 : uint8_t *buf = NULL;
6678 13785295 : off_t ofs = 0;
6679 13785295 : size_t avail = 0;
6680 : size_t remain;
6681 : int rc;
6682 :
6683 : /* to give better errors */
6684 13785295 : if (ret == -1) {
6685 937 : if (saved_errno == ENOENT) {
6686 0 : saved_errno = EHOSTUNREACH;
6687 937 : } else if (saved_errno == ENOTSOCK) {
6688 : /* If the fd is not a socket, remove it */
6689 0 : swrap_remove_stale(fd);
6690 : }
6691 : }
6692 :
6693 27570590 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6694 13785295 : avail += msg->msg_iov[i].iov_len;
6695 : }
6696 :
6697 13785295 : SWRAP_LOCK_SI(si);
6698 :
6699 : /* Convert the socket address before we leave */
6700 13785295 : if (si->type == SOCK_DGRAM && un_addr != NULL) {
6701 42091 : rc = sockaddr_convert_from_un(si,
6702 : un_addr,
6703 : un_addrlen,
6704 : si->family,
6705 42091 : msg->msg_name,
6706 : &msg->msg_namelen);
6707 42091 : if (rc == -1) {
6708 0 : goto done;
6709 : }
6710 : }
6711 :
6712 13785295 : if (avail == 0) {
6713 4 : rc = 0;
6714 4 : goto done;
6715 : }
6716 :
6717 13785291 : if (ret == -1) {
6718 937 : remain = MIN(80, avail);
6719 : } else {
6720 13784354 : remain = ret;
6721 : }
6722 :
6723 : /* we capture it as one single packet */
6724 13785291 : buf = (uint8_t *)malloc(remain);
6725 13785291 : if (buf == NULL) {
6726 : /* we just not capture the packet */
6727 0 : SWRAP_UNLOCK_SI(si);
6728 0 : errno = saved_errno;
6729 0 : return -1;
6730 : }
6731 :
6732 27570582 : for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6733 13785291 : size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6734 13785291 : memcpy(buf + ofs,
6735 13785291 : msg->msg_iov[i].iov_base,
6736 : this_time);
6737 13785291 : ofs += this_time;
6738 13785291 : remain -= this_time;
6739 : }
6740 :
6741 13785291 : switch (si->type) {
6742 13722835 : case SOCK_STREAM:
6743 13722835 : if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6744 546 : swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6745 13722289 : } else if (ret == 0) { /* END OF FILE */
6746 91073 : swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6747 13631216 : } else if (ret > 0) {
6748 13630825 : swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6749 : }
6750 13722835 : break;
6751 :
6752 62456 : case SOCK_DGRAM:
6753 62456 : if (ret == -1) {
6754 0 : break;
6755 : }
6756 :
6757 62456 : if (un_addr != NULL) {
6758 42087 : swrap_pcap_dump_packet(si,
6759 42087 : msg->msg_name,
6760 : SWRAP_RECVFROM,
6761 : buf,
6762 : ret);
6763 : } else {
6764 20369 : swrap_pcap_dump_packet(si,
6765 20369 : msg->msg_name,
6766 : SWRAP_RECV,
6767 : buf,
6768 : ret);
6769 : }
6770 :
6771 62456 : break;
6772 : }
6773 :
6774 13785291 : rc = 0;
6775 13785295 : done:
6776 13785295 : free(buf);
6777 13785295 : errno = saved_errno;
6778 :
6779 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6780 13785295 : if (rc == 0 &&
6781 13785295 : msg->msg_controllen > 0 &&
6782 0 : msg->msg_control != NULL) {
6783 0 : rc = swrap_msghdr_add_socket_info(si, msg);
6784 0 : if (rc < 0) {
6785 0 : SWRAP_UNLOCK_SI(si);
6786 0 : return -1;
6787 : }
6788 : }
6789 : #endif
6790 :
6791 13785295 : SWRAP_UNLOCK_SI(si);
6792 13785295 : return rc;
6793 : }
6794 :
6795 : /****************************************************************************
6796 : * RECVFROM
6797 : ***************************************************************************/
6798 :
6799 45295 : static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6800 : struct sockaddr *from, socklen_t *fromlen)
6801 : {
6802 45295 : struct swrap_address from_addr = {
6803 : .sa_socklen = sizeof(struct sockaddr_un),
6804 : };
6805 : ssize_t ret;
6806 45295 : struct socket_info *si = find_socket_info(s);
6807 45295 : struct swrap_address saddr = {
6808 : .sa_socklen = sizeof(struct sockaddr_storage),
6809 : };
6810 : struct msghdr msg;
6811 : struct iovec tmp;
6812 : int tret;
6813 :
6814 45295 : if (!si) {
6815 0 : return libc_recvfrom(s,
6816 : buf,
6817 : len,
6818 : flags,
6819 : from,
6820 : fromlen);
6821 : }
6822 :
6823 45295 : tmp.iov_base = buf;
6824 45295 : tmp.iov_len = len;
6825 :
6826 45295 : ZERO_STRUCT(msg);
6827 45295 : if (from != NULL && fromlen != NULL) {
6828 45264 : msg.msg_name = from; /* optional address */
6829 45264 : msg.msg_namelen = *fromlen; /* size of address */
6830 : } else {
6831 31 : msg.msg_name = &saddr.sa.s; /* optional address */
6832 31 : msg.msg_namelen = saddr.sa_socklen; /* size of address */
6833 : }
6834 45295 : msg.msg_iov = &tmp; /* scatter/gather array */
6835 45295 : msg.msg_iovlen = 1; /* # elements in msg_iov */
6836 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6837 45295 : msg.msg_control = NULL; /* ancillary data, see below */
6838 45295 : msg.msg_controllen = 0; /* ancillary data buffer len */
6839 45295 : msg.msg_flags = 0; /* flags on received message */
6840 : #endif
6841 :
6842 45295 : tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6843 45295 : if (tret < 0) {
6844 0 : return -1;
6845 : }
6846 :
6847 45295 : buf = msg.msg_iov[0].iov_base;
6848 45295 : len = msg.msg_iov[0].iov_len;
6849 :
6850 45295 : ret = libc_recvfrom(s,
6851 : buf,
6852 : len,
6853 : flags,
6854 : &from_addr.sa.s,
6855 : &from_addr.sa_socklen);
6856 45295 : if (ret == -1) {
6857 3233 : return ret;
6858 : }
6859 :
6860 42062 : tret = swrap_recvmsg_after(s,
6861 : si,
6862 : &msg,
6863 : &from_addr.sa.un,
6864 : from_addr.sa_socklen,
6865 : ret);
6866 42062 : if (tret != 0) {
6867 0 : return tret;
6868 : }
6869 :
6870 42062 : if (from != NULL && fromlen != NULL) {
6871 42031 : *fromlen = msg.msg_namelen;
6872 : }
6873 :
6874 42062 : return ret;
6875 : }
6876 :
6877 : #ifdef HAVE_ACCEPT_PSOCKLEN_T
6878 : ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6879 : struct sockaddr *from, Psocklen_t fromlen)
6880 : #else
6881 : ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6882 : struct sockaddr *from, socklen_t *fromlen)
6883 : #endif
6884 : {
6885 45295 : return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6886 : }
6887 :
6888 : /****************************************************************************
6889 : * SENDTO
6890 : ***************************************************************************/
6891 :
6892 37345 : static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6893 : const struct sockaddr *to, socklen_t tolen)
6894 : {
6895 : struct msghdr msg;
6896 : struct iovec tmp;
6897 37345 : struct swrap_address un_addr = {
6898 : .sa_socklen = sizeof(struct sockaddr_un),
6899 : };
6900 37345 : const struct sockaddr_un *to_un = NULL;
6901 : ssize_t ret;
6902 : int rc;
6903 37345 : struct socket_info *si = find_socket_info(s);
6904 37345 : int bcast = 0;
6905 :
6906 37345 : if (!si) {
6907 0 : return libc_sendto(s, buf, len, flags, to, tolen);
6908 : }
6909 :
6910 37345 : tmp.iov_base = discard_const_p(char, buf);
6911 37345 : tmp.iov_len = len;
6912 :
6913 37345 : ZERO_STRUCT(msg);
6914 37345 : msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6915 37345 : msg.msg_namelen = tolen; /* size of address */
6916 37345 : msg.msg_iov = &tmp; /* scatter/gather array */
6917 37345 : msg.msg_iovlen = 1; /* # elements in msg_iov */
6918 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6919 37345 : msg.msg_control = NULL; /* ancillary data, see below */
6920 37345 : msg.msg_controllen = 0; /* ancillary data buffer len */
6921 37345 : msg.msg_flags = 0; /* flags on received message */
6922 : #endif
6923 :
6924 37345 : rc = swrap_sendmsg_before(s,
6925 : si,
6926 : &msg,
6927 : &tmp,
6928 : &un_addr.sa.un,
6929 : &to_un,
6930 : &to,
6931 : &bcast);
6932 37345 : if (rc < 0) {
6933 6556 : return -1;
6934 : }
6935 :
6936 30789 : buf = msg.msg_iov[0].iov_base;
6937 30789 : len = msg.msg_iov[0].iov_len;
6938 :
6939 30789 : if (bcast) {
6940 : struct stat st;
6941 : unsigned int iface;
6942 3012 : unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6943 : char type;
6944 3012 : char *swrap_dir = NULL;
6945 :
6946 3012 : type = SOCKET_TYPE_CHAR_UDP;
6947 :
6948 3012 : swrap_dir = socket_wrapper_dir();
6949 3012 : if (swrap_dir == NULL) {
6950 0 : return -1;
6951 : }
6952 :
6953 198792 : for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6954 195780 : swrap_un_path(&un_addr.sa.un,
6955 : swrap_dir,
6956 : type,
6957 : iface,
6958 : prt);
6959 195780 : if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6960 :
6961 : /* ignore the any errors in broadcast sends */
6962 11300 : libc_sendto(s,
6963 : buf,
6964 : len,
6965 : flags,
6966 : &un_addr.sa.s,
6967 : un_addr.sa_socklen);
6968 : }
6969 :
6970 3012 : SAFE_FREE(swrap_dir);
6971 :
6972 3012 : SWRAP_LOCK_SI(si);
6973 :
6974 3012 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6975 :
6976 3012 : SWRAP_UNLOCK_SI(si);
6977 :
6978 3012 : return len;
6979 : }
6980 :
6981 27777 : SWRAP_LOCK_SI(si);
6982 : /*
6983 : * If it is a dgram socket and we are connected, don't include the
6984 : * 'to' address.
6985 : */
6986 27777 : if (si->type == SOCK_DGRAM && si->connected) {
6987 2249 : ret = libc_sendto(s,
6988 : buf,
6989 : len,
6990 : flags,
6991 : NULL,
6992 : 0);
6993 : } else {
6994 25528 : ret = libc_sendto(s,
6995 : buf,
6996 : len,
6997 : flags,
6998 25528 : (struct sockaddr *)msg.msg_name,
6999 : msg.msg_namelen);
7000 : }
7001 :
7002 27777 : SWRAP_UNLOCK_SI(si);
7003 :
7004 27777 : swrap_sendmsg_after(s, si, &msg, to, ret);
7005 :
7006 27777 : return ret;
7007 : }
7008 :
7009 : ssize_t sendto(int s, const void *buf, size_t len, int flags,
7010 : const struct sockaddr *to, socklen_t tolen)
7011 : {
7012 37345 : return swrap_sendto(s, buf, len, flags, to, tolen);
7013 : }
7014 :
7015 : /****************************************************************************
7016 : * READV
7017 : ***************************************************************************/
7018 :
7019 4137725 : static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
7020 : {
7021 : struct socket_info *si;
7022 : struct msghdr msg;
7023 4137725 : struct swrap_address saddr = {
7024 : .sa_socklen = sizeof(struct sockaddr_storage),
7025 : };
7026 : struct iovec tmp;
7027 : ssize_t ret;
7028 : int tret;
7029 :
7030 4137725 : si = find_socket_info(s);
7031 4137725 : if (si == NULL) {
7032 163698 : return libc_recv(s, buf, len, flags);
7033 : }
7034 :
7035 3974027 : tmp.iov_base = buf;
7036 3974027 : tmp.iov_len = len;
7037 :
7038 3974027 : ZERO_STRUCT(msg);
7039 3974027 : msg.msg_name = &saddr.sa.s; /* optional address */
7040 3974027 : msg.msg_namelen = saddr.sa_socklen; /* size of address */
7041 3974027 : msg.msg_iov = &tmp; /* scatter/gather array */
7042 3974027 : msg.msg_iovlen = 1; /* # elements in msg_iov */
7043 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7044 3974027 : msg.msg_control = NULL; /* ancillary data, see below */
7045 3974027 : msg.msg_controllen = 0; /* ancillary data buffer len */
7046 3974027 : msg.msg_flags = 0; /* flags on received message */
7047 : #endif
7048 :
7049 3974027 : tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7050 3974027 : if (tret < 0) {
7051 0 : return -1;
7052 : }
7053 :
7054 3974027 : buf = msg.msg_iov[0].iov_base;
7055 3974027 : len = msg.msg_iov[0].iov_len;
7056 :
7057 3974027 : ret = libc_recv(s, buf, len, flags);
7058 :
7059 3974027 : tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7060 3974027 : if (tret != 0) {
7061 0 : return tret;
7062 : }
7063 :
7064 3974027 : return ret;
7065 : }
7066 :
7067 : ssize_t recv(int s, void *buf, size_t len, int flags)
7068 : {
7069 4137725 : return swrap_recv(s, buf, len, flags);
7070 : }
7071 :
7072 : /****************************************************************************
7073 : * READ
7074 : ***************************************************************************/
7075 :
7076 3062475 : static ssize_t swrap_read(int s, void *buf, size_t len)
7077 : {
7078 : struct socket_info *si;
7079 : struct msghdr msg;
7080 : struct iovec tmp;
7081 3062475 : struct swrap_address saddr = {
7082 : .sa_socklen = sizeof(struct sockaddr_storage),
7083 : };
7084 : ssize_t ret;
7085 : int tret;
7086 :
7087 3062475 : si = find_socket_info(s);
7088 3062475 : if (si == NULL) {
7089 2971950 : return libc_read(s, buf, len);
7090 : }
7091 :
7092 90525 : tmp.iov_base = buf;
7093 90525 : tmp.iov_len = len;
7094 :
7095 90525 : ZERO_STRUCT(msg);
7096 90525 : msg.msg_name = &saddr.sa.ss; /* optional address */
7097 90525 : msg.msg_namelen = saddr.sa_socklen; /* size of address */
7098 90525 : msg.msg_iov = &tmp; /* scatter/gather array */
7099 90525 : msg.msg_iovlen = 1; /* # elements in msg_iov */
7100 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7101 90525 : msg.msg_control = NULL; /* ancillary data, see below */
7102 90525 : msg.msg_controllen = 0; /* ancillary data buffer len */
7103 90525 : msg.msg_flags = 0; /* flags on received message */
7104 : #endif
7105 :
7106 90525 : tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7107 90525 : if (tret < 0) {
7108 0 : if (tret == -ENOTSOCK) {
7109 0 : return libc_read(s, buf, len);
7110 : }
7111 0 : return -1;
7112 : }
7113 :
7114 90525 : buf = msg.msg_iov[0].iov_base;
7115 90525 : len = msg.msg_iov[0].iov_len;
7116 :
7117 90525 : ret = libc_read(s, buf, len);
7118 :
7119 90525 : tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7120 90525 : if (tret != 0) {
7121 0 : return tret;
7122 : }
7123 :
7124 90525 : return ret;
7125 : }
7126 :
7127 : ssize_t read(int s, void *buf, size_t len)
7128 : {
7129 3062475 : return swrap_read(s, buf, len);
7130 : }
7131 :
7132 : /****************************************************************************
7133 : * WRITE
7134 : ***************************************************************************/
7135 :
7136 3331657 : static ssize_t swrap_write(int s, const void *buf, size_t len)
7137 : {
7138 : struct msghdr msg;
7139 : struct iovec tmp;
7140 : struct sockaddr_un un_addr;
7141 : ssize_t ret;
7142 : int rc;
7143 : struct socket_info *si;
7144 :
7145 3331657 : si = find_socket_info(s);
7146 3331657 : if (si == NULL) {
7147 3277556 : return libc_write(s, buf, len);
7148 : }
7149 :
7150 54101 : tmp.iov_base = discard_const_p(char, buf);
7151 54101 : tmp.iov_len = len;
7152 :
7153 54101 : ZERO_STRUCT(msg);
7154 54101 : msg.msg_name = NULL; /* optional address */
7155 54101 : msg.msg_namelen = 0; /* size of address */
7156 54101 : msg.msg_iov = &tmp; /* scatter/gather array */
7157 54101 : msg.msg_iovlen = 1; /* # elements in msg_iov */
7158 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7159 54101 : msg.msg_control = NULL; /* ancillary data, see below */
7160 54101 : msg.msg_controllen = 0; /* ancillary data buffer len */
7161 54101 : msg.msg_flags = 0; /* flags on received message */
7162 : #endif
7163 :
7164 54101 : rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7165 54101 : if (rc < 0) {
7166 0 : return -1;
7167 : }
7168 :
7169 54101 : buf = msg.msg_iov[0].iov_base;
7170 54101 : len = msg.msg_iov[0].iov_len;
7171 :
7172 54101 : ret = libc_write(s, buf, len);
7173 :
7174 54101 : swrap_sendmsg_after(s, si, &msg, NULL, ret);
7175 :
7176 54101 : return ret;
7177 : }
7178 :
7179 : ssize_t write(int s, const void *buf, size_t len)
7180 : {
7181 3331657 : return swrap_write(s, buf, len);
7182 : }
7183 :
7184 : /****************************************************************************
7185 : * SEND
7186 : ***************************************************************************/
7187 :
7188 14057297 : static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7189 : {
7190 : struct msghdr msg;
7191 : struct iovec tmp;
7192 : struct sockaddr_un un_addr;
7193 : ssize_t ret;
7194 : int rc;
7195 14057297 : struct socket_info *si = find_socket_info(s);
7196 :
7197 14057297 : if (!si) {
7198 3 : return libc_send(s, buf, len, flags);
7199 : }
7200 :
7201 14057294 : tmp.iov_base = discard_const_p(char, buf);
7202 14057294 : tmp.iov_len = len;
7203 :
7204 14057294 : ZERO_STRUCT(msg);
7205 14057294 : msg.msg_name = NULL; /* optional address */
7206 14057294 : msg.msg_namelen = 0; /* size of address */
7207 14057294 : msg.msg_iov = &tmp; /* scatter/gather array */
7208 14057294 : msg.msg_iovlen = 1; /* # elements in msg_iov */
7209 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7210 14057294 : msg.msg_control = NULL; /* ancillary data, see below */
7211 14057294 : msg.msg_controllen = 0; /* ancillary data buffer len */
7212 14057294 : msg.msg_flags = 0; /* flags on received message */
7213 : #endif
7214 :
7215 14057294 : rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7216 14057294 : if (rc < 0) {
7217 13076870 : return -1;
7218 : }
7219 :
7220 980424 : buf = msg.msg_iov[0].iov_base;
7221 980424 : len = msg.msg_iov[0].iov_len;
7222 :
7223 980424 : ret = libc_send(s, buf, len, flags);
7224 :
7225 980424 : swrap_sendmsg_after(s, si, &msg, NULL, ret);
7226 :
7227 980424 : return ret;
7228 : }
7229 :
7230 : ssize_t send(int s, const void *buf, size_t len, int flags)
7231 : {
7232 14057297 : return swrap_send(s, buf, len, flags);
7233 : }
7234 :
7235 : /****************************************************************************
7236 : * RECVMSG
7237 : ***************************************************************************/
7238 :
7239 424760 : static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7240 : {
7241 424760 : struct swrap_address from_addr = {
7242 : .sa_socklen = sizeof(struct sockaddr_un),
7243 : };
7244 424760 : struct swrap_address convert_addr = {
7245 : .sa_socklen = sizeof(struct sockaddr_storage),
7246 : };
7247 : struct socket_info *si;
7248 : struct msghdr msg;
7249 : struct iovec tmp;
7250 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7251 : size_t msg_ctrllen_filled;
7252 : size_t msg_ctrllen_left;
7253 : #endif
7254 :
7255 : ssize_t ret;
7256 : int rc;
7257 :
7258 424760 : si = find_socket_info(s);
7259 424760 : if (si == NULL) {
7260 17144 : uint8_t *tmp_control = NULL;
7261 17144 : rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7262 17144 : if (rc < 0) {
7263 0 : return rc;
7264 : }
7265 17144 : ret = libc_recvmsg(s, &msg, flags);
7266 17144 : return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7267 : }
7268 :
7269 407616 : tmp.iov_base = NULL;
7270 407616 : tmp.iov_len = 0;
7271 :
7272 407616 : ZERO_STRUCT(msg);
7273 407616 : msg.msg_name = &from_addr.sa; /* optional address */
7274 407616 : msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7275 407616 : msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7276 407616 : msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7277 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7278 407616 : msg_ctrllen_filled = 0;
7279 407616 : msg_ctrllen_left = omsg->msg_controllen;
7280 :
7281 407616 : msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7282 407616 : msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7283 407616 : msg.msg_flags = omsg->msg_flags; /* flags on received message */
7284 : #endif
7285 :
7286 407616 : rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7287 407616 : if (rc < 0) {
7288 0 : return -1;
7289 : }
7290 :
7291 407616 : ret = libc_recvmsg(s, &msg, flags);
7292 :
7293 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7294 407616 : msg_ctrllen_filled += msg.msg_controllen;
7295 407616 : msg_ctrllen_left -= msg.msg_controllen;
7296 :
7297 407616 : if (omsg->msg_control != NULL) {
7298 : uint8_t *p;
7299 :
7300 0 : p = omsg->msg_control;
7301 0 : p += msg_ctrllen_filled;
7302 :
7303 0 : msg.msg_control = p;
7304 0 : msg.msg_controllen = msg_ctrllen_left;
7305 : } else {
7306 407616 : msg.msg_control = NULL;
7307 407616 : msg.msg_controllen = 0;
7308 : }
7309 : #endif
7310 :
7311 : /*
7312 : * We convert the unix address to a IP address so we need a buffer
7313 : * which can store the address in case of SOCK_DGRAM, see below.
7314 : */
7315 407616 : msg.msg_name = &convert_addr.sa;
7316 407616 : msg.msg_namelen = convert_addr.sa_socklen;
7317 :
7318 407616 : rc = swrap_recvmsg_after(s,
7319 : si,
7320 : &msg,
7321 : &from_addr.sa.un,
7322 : from_addr.sa_socklen,
7323 : ret);
7324 407616 : if (rc != 0) {
7325 0 : return rc;
7326 : }
7327 :
7328 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7329 407616 : if (omsg->msg_control != NULL) {
7330 : /* msg.msg_controllen = space left */
7331 0 : msg_ctrllen_left = msg.msg_controllen;
7332 0 : msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7333 : }
7334 :
7335 : /* Update the original message length */
7336 407616 : omsg->msg_controllen = msg_ctrllen_filled;
7337 407616 : omsg->msg_flags = msg.msg_flags;
7338 : #endif
7339 407616 : omsg->msg_iovlen = msg.msg_iovlen;
7340 :
7341 407616 : SWRAP_LOCK_SI(si);
7342 :
7343 : /*
7344 : * From the manpage:
7345 : *
7346 : * The msg_name field points to a caller-allocated buffer that is
7347 : * used to return the source address if the socket is unconnected. The
7348 : * caller should set msg_namelen to the size of this buffer before this
7349 : * call; upon return from a successful call, msg_name will contain the
7350 : * length of the returned address. If the application does not need
7351 : * to know the source address, msg_name can be specified as NULL.
7352 : */
7353 407616 : if (si->type == SOCK_STREAM) {
7354 407587 : omsg->msg_namelen = 0;
7355 29 : } else if (omsg->msg_name != NULL &&
7356 29 : omsg->msg_namelen != 0 &&
7357 29 : omsg->msg_namelen >= msg.msg_namelen) {
7358 29 : memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7359 29 : omsg->msg_namelen = msg.msg_namelen;
7360 : }
7361 :
7362 407616 : SWRAP_UNLOCK_SI(si);
7363 :
7364 407616 : return ret;
7365 : }
7366 :
7367 : ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7368 : {
7369 424760 : return swrap_recvmsg(sockfd, msg, flags);
7370 : }
7371 :
7372 : /****************************************************************************
7373 : * RECVMMSG
7374 : ***************************************************************************/
7375 :
7376 : #ifdef HAVE_RECVMMSG
7377 : #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7378 : /* FreeBSD */
7379 : static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7380 : #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7381 : /* Linux legacy glibc < 2.21 */
7382 : static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7383 : #else
7384 : /* Linux glibc >= 2.21 */
7385 0 : static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7386 : #endif
7387 : {
7388 0 : struct socket_info *si = find_socket_info(s);
7389 : #define __SWRAP_RECVMMSG_MAX_VLEN 16
7390 0 : struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7391 : struct {
7392 : struct iovec iov;
7393 : struct swrap_address from_addr;
7394 : struct swrap_address convert_addr;
7395 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7396 : size_t msg_ctrllen_filled;
7397 : size_t msg_ctrllen_left;
7398 : #endif
7399 0 : } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7400 : int vlen;
7401 : int i;
7402 : int ret;
7403 : int rc;
7404 : int saved_errno;
7405 :
7406 0 : if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7407 0 : vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7408 : } else {
7409 0 : vlen = _vlen;
7410 : }
7411 :
7412 0 : if (si == NULL) {
7413 0 : uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7414 :
7415 0 : for (i = 0; i < vlen; i++) {
7416 0 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7417 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7418 :
7419 0 : rc = swrap_recvmsg_before_unix(omsg, msg,
7420 : &tmp_control[i]);
7421 0 : if (rc < 0) {
7422 0 : ret = rc;
7423 0 : goto fail_libc;
7424 : }
7425 : }
7426 :
7427 0 : ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7428 0 : if (ret < 0) {
7429 0 : goto fail_libc;
7430 : }
7431 :
7432 0 : for (i = 0; i < ret; i++) {
7433 0 : omsgvec[i].msg_len = msgvec[i].msg_len;
7434 : }
7435 :
7436 0 : fail_libc:
7437 0 : saved_errno = errno;
7438 0 : for (i = 0; i < vlen; i++) {
7439 0 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7440 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7441 :
7442 0 : if (i == 0 || i < ret) {
7443 0 : swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7444 : }
7445 0 : SAFE_FREE(tmp_control[i]);
7446 : }
7447 0 : errno = saved_errno;
7448 :
7449 0 : return ret;
7450 : }
7451 :
7452 0 : for (i = 0; i < vlen; i++) {
7453 0 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7454 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7455 :
7456 0 : tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7457 0 : tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7458 :
7459 0 : msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7460 0 : msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7461 0 : msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7462 0 : msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7463 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7464 0 : tmp[i].msg_ctrllen_filled = 0;
7465 0 : tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7466 :
7467 0 : msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7468 0 : msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7469 0 : msg->msg_flags = omsg->msg_flags; /* flags on received message */
7470 : #endif
7471 :
7472 0 : rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7473 0 : if (rc < 0) {
7474 0 : ret = rc;
7475 0 : goto fail_swrap;
7476 : }
7477 : }
7478 :
7479 0 : ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7480 0 : if (ret < 0) {
7481 0 : goto fail_swrap;
7482 : }
7483 :
7484 0 : for (i = 0; i < ret; i++) {
7485 0 : omsgvec[i].msg_len = msgvec[i].msg_len;
7486 : }
7487 :
7488 0 : fail_swrap:
7489 :
7490 0 : saved_errno = errno;
7491 0 : for (i = 0; i < vlen; i++) {
7492 0 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7493 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7494 :
7495 0 : if (!(i == 0 || i < ret)) {
7496 0 : break;
7497 : }
7498 :
7499 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7500 0 : tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7501 0 : tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7502 :
7503 0 : if (omsg->msg_control != NULL) {
7504 : uint8_t *p;
7505 :
7506 0 : p = omsg->msg_control;
7507 0 : p += tmp[i].msg_ctrllen_filled;
7508 :
7509 0 : msg->msg_control = p;
7510 0 : msg->msg_controllen = tmp[i].msg_ctrllen_left;
7511 : } else {
7512 0 : msg->msg_control = NULL;
7513 0 : msg->msg_controllen = 0;
7514 : }
7515 : #endif
7516 :
7517 : /*
7518 : * We convert the unix address to a IP address so we need a buffer
7519 : * which can store the address in case of SOCK_DGRAM, see below.
7520 : */
7521 0 : msg->msg_name = &tmp[i].convert_addr.sa;
7522 0 : msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7523 :
7524 0 : swrap_recvmsg_after(s, si, msg,
7525 0 : &tmp[i].from_addr.sa.un,
7526 : tmp[i].from_addr.sa_socklen,
7527 : ret);
7528 :
7529 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7530 0 : if (omsg->msg_control != NULL) {
7531 : /* msg->msg_controllen = space left */
7532 0 : tmp[i].msg_ctrllen_left = msg->msg_controllen;
7533 0 : tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7534 : }
7535 :
7536 : /* Update the original message length */
7537 0 : omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7538 0 : omsg->msg_flags = msg->msg_flags;
7539 : #endif
7540 0 : omsg->msg_iovlen = msg->msg_iovlen;
7541 :
7542 0 : SWRAP_LOCK_SI(si);
7543 :
7544 : /*
7545 : * From the manpage:
7546 : *
7547 : * The msg_name field points to a caller-allocated buffer that is
7548 : * used to return the source address if the socket is unconnected. The
7549 : * caller should set msg_namelen to the size of this buffer before this
7550 : * call; upon return from a successful call, msg_name will contain the
7551 : * length of the returned address. If the application does not need
7552 : * to know the source address, msg_name can be specified as NULL.
7553 : */
7554 0 : if (si->type == SOCK_STREAM) {
7555 0 : omsg->msg_namelen = 0;
7556 0 : } else if (omsg->msg_name != NULL &&
7557 0 : omsg->msg_namelen != 0 &&
7558 0 : omsg->msg_namelen >= msg->msg_namelen) {
7559 0 : memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7560 0 : omsg->msg_namelen = msg->msg_namelen;
7561 : }
7562 :
7563 0 : SWRAP_UNLOCK_SI(si);
7564 : }
7565 0 : errno = saved_errno;
7566 :
7567 0 : return ret;
7568 : }
7569 :
7570 : #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7571 : /* FreeBSD */
7572 : ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7573 : #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7574 : /* Linux legacy glibc < 2.21 */
7575 : int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7576 : #else
7577 : /* Linux glibc >= 2.21 */
7578 : int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7579 : #endif
7580 : {
7581 0 : return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7582 : }
7583 : #endif /* HAVE_RECVMMSG */
7584 :
7585 : /****************************************************************************
7586 : * SENDMSG
7587 : ***************************************************************************/
7588 :
7589 303606 : static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7590 : {
7591 : struct msghdr msg;
7592 : struct iovec tmp;
7593 : struct sockaddr_un un_addr;
7594 303606 : const struct sockaddr_un *to_un = NULL;
7595 303606 : const struct sockaddr *to = NULL;
7596 : ssize_t ret;
7597 : int rc;
7598 303606 : struct socket_info *si = find_socket_info(s);
7599 303606 : int bcast = 0;
7600 :
7601 303606 : if (!si) {
7602 20686 : int scm_rights_pipe_fd = -1;
7603 :
7604 20686 : rc = swrap_sendmsg_before_unix(omsg, &msg,
7605 : &scm_rights_pipe_fd);
7606 20686 : if (rc < 0) {
7607 0 : return rc;
7608 : }
7609 20686 : ret = libc_sendmsg(s, &msg, flags);
7610 20686 : return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7611 : }
7612 :
7613 282920 : ZERO_STRUCT(un_addr);
7614 :
7615 282920 : tmp.iov_base = NULL;
7616 282920 : tmp.iov_len = 0;
7617 :
7618 282920 : ZERO_STRUCT(msg);
7619 :
7620 282920 : SWRAP_LOCK_SI(si);
7621 :
7622 282920 : if (si->connected == 0) {
7623 0 : msg.msg_name = omsg->msg_name; /* optional address */
7624 0 : msg.msg_namelen = omsg->msg_namelen; /* size of address */
7625 : }
7626 282920 : msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7627 282920 : msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7628 :
7629 282920 : SWRAP_UNLOCK_SI(si);
7630 :
7631 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7632 282920 : if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7633 0 : uint8_t *cmbuf = NULL;
7634 0 : size_t cmlen = 0;
7635 :
7636 0 : rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7637 0 : if (rc < 0) {
7638 0 : return rc;
7639 : }
7640 :
7641 0 : if (cmlen == 0) {
7642 0 : msg.msg_controllen = 0;
7643 0 : msg.msg_control = NULL;
7644 : } else {
7645 0 : msg.msg_control = cmbuf;
7646 0 : msg.msg_controllen = cmlen;
7647 : }
7648 : }
7649 282920 : msg.msg_flags = omsg->msg_flags; /* flags on received message */
7650 : #endif
7651 282920 : rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7652 282920 : if (rc < 0) {
7653 0 : int saved_errno = errno;
7654 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7655 0 : SAFE_FREE(msg.msg_control);
7656 : #endif
7657 0 : errno = saved_errno;
7658 0 : return -1;
7659 : }
7660 :
7661 282920 : if (bcast) {
7662 : struct stat st;
7663 : unsigned int iface;
7664 0 : unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7665 : char type;
7666 0 : size_t i, len = 0;
7667 : uint8_t *buf;
7668 0 : off_t ofs = 0;
7669 0 : size_t avail = 0;
7670 : size_t remain;
7671 0 : char *swrap_dir = NULL;
7672 :
7673 0 : for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7674 0 : avail += msg.msg_iov[i].iov_len;
7675 : }
7676 :
7677 0 : len = avail;
7678 0 : remain = avail;
7679 :
7680 : /* we capture it as one single packet */
7681 0 : buf = (uint8_t *)malloc(remain);
7682 0 : if (!buf) {
7683 0 : int saved_errno = errno;
7684 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7685 0 : SAFE_FREE(msg.msg_control);
7686 : #endif
7687 0 : errno = saved_errno;
7688 0 : return -1;
7689 : }
7690 :
7691 0 : for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7692 0 : size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7693 0 : memcpy(buf + ofs,
7694 0 : msg.msg_iov[i].iov_base,
7695 : this_time);
7696 0 : ofs += this_time;
7697 0 : remain -= this_time;
7698 : }
7699 :
7700 0 : type = SOCKET_TYPE_CHAR_UDP;
7701 :
7702 0 : swrap_dir = socket_wrapper_dir();
7703 0 : if (swrap_dir == NULL) {
7704 0 : int saved_errno = errno;
7705 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7706 0 : SAFE_FREE(msg.msg_control);
7707 : #endif
7708 0 : SAFE_FREE(buf);
7709 0 : errno = saved_errno;
7710 0 : return -1;
7711 : }
7712 :
7713 0 : for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7714 0 : swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7715 0 : if (stat(un_addr.sun_path, &st) != 0) continue;
7716 :
7717 0 : msg.msg_name = &un_addr; /* optional address */
7718 0 : msg.msg_namelen = sizeof(un_addr); /* size of address */
7719 :
7720 : /* ignore the any errors in broadcast sends */
7721 0 : libc_sendmsg(s, &msg, flags);
7722 : }
7723 :
7724 0 : SAFE_FREE(swrap_dir);
7725 :
7726 0 : SWRAP_LOCK_SI(si);
7727 :
7728 0 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7729 0 : free(buf);
7730 :
7731 0 : SWRAP_UNLOCK_SI(si);
7732 :
7733 0 : return len;
7734 : }
7735 :
7736 282920 : ret = libc_sendmsg(s, &msg, flags);
7737 :
7738 282920 : swrap_sendmsg_after(s, si, &msg, to, ret);
7739 :
7740 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7741 : {
7742 282920 : int saved_errno = errno;
7743 282920 : SAFE_FREE(msg.msg_control);
7744 282920 : errno = saved_errno;
7745 : }
7746 : #endif
7747 :
7748 282920 : return ret;
7749 : }
7750 :
7751 : ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7752 : {
7753 303606 : return swrap_sendmsg(s, omsg, flags);
7754 : }
7755 :
7756 : /****************************************************************************
7757 : * SENDMMSG
7758 : ***************************************************************************/
7759 :
7760 : #ifdef HAVE_SENDMMSG
7761 : #if defined(HAVE_SENDMMSG_SSIZE_T)
7762 : /* FreeBSD */
7763 : static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7764 : #else
7765 : /* Linux */
7766 58 : static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7767 : #endif
7768 : {
7769 58 : struct socket_info *si = find_socket_info(s);
7770 : #define __SWRAP_SENDMMSG_MAX_VLEN 16
7771 58 : struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7772 : struct {
7773 : struct iovec iov;
7774 : struct sockaddr_un un_addr;
7775 : const struct sockaddr_un *to_un;
7776 : const struct sockaddr *to;
7777 : int bcast;
7778 58 : } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7779 : int vlen;
7780 : int i;
7781 58 : char *swrap_dir = NULL;
7782 58 : int connected = 0;
7783 58 : int found_bcast = 0;
7784 : int ret;
7785 : int rc;
7786 : int saved_errno;
7787 :
7788 58 : if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7789 0 : vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7790 : } else {
7791 58 : vlen = _vlen;
7792 : }
7793 :
7794 58 : if (!si) {
7795 : int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7796 :
7797 0 : for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7798 0 : scm_rights_pipe_fd[i] = -1;
7799 : }
7800 :
7801 0 : for (i = 0; i < vlen; i++) {
7802 0 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7803 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7804 :
7805 0 : rc = swrap_sendmsg_before_unix(omsg, msg,
7806 : &scm_rights_pipe_fd[i]);
7807 0 : if (rc < 0) {
7808 0 : ret = rc;
7809 0 : goto fail_libc;
7810 : }
7811 : }
7812 :
7813 0 : ret = libc_sendmmsg(s, msgvec, vlen, flags);
7814 0 : if (ret < 0) {
7815 0 : goto fail_libc;
7816 : }
7817 :
7818 0 : for (i = 0; i < ret; i++) {
7819 0 : omsgvec[i].msg_len = msgvec[i].msg_len;
7820 : }
7821 :
7822 0 : fail_libc:
7823 0 : saved_errno = errno;
7824 0 : for (i = 0; i < vlen; i++) {
7825 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7826 :
7827 0 : swrap_sendmsg_after_unix(msg, ret,
7828 : scm_rights_pipe_fd[i]);
7829 : }
7830 0 : errno = saved_errno;
7831 :
7832 0 : return ret;
7833 : }
7834 :
7835 58 : SWRAP_LOCK_SI(si);
7836 58 : connected = si->connected;
7837 58 : SWRAP_UNLOCK_SI(si);
7838 :
7839 87 : for (i = 0; i < vlen; i++) {
7840 29 : struct msghdr *omsg = &omsgvec[i].msg_hdr;
7841 29 : struct msghdr *msg = &msgvec[i].msg_hdr;
7842 :
7843 29 : if (connected == 0) {
7844 0 : msg->msg_name = omsg->msg_name; /* optional address */
7845 0 : msg->msg_namelen = omsg->msg_namelen; /* size of address */
7846 : }
7847 29 : msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7848 29 : msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7849 :
7850 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7851 29 : if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7852 0 : uint8_t *cmbuf = NULL;
7853 0 : size_t cmlen = 0;
7854 :
7855 0 : rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7856 0 : if (rc < 0) {
7857 0 : ret = rc;
7858 0 : goto fail_swrap;
7859 : }
7860 :
7861 0 : if (cmlen != 0) {
7862 0 : msg->msg_control = cmbuf;
7863 0 : msg->msg_controllen = cmlen;
7864 : }
7865 : }
7866 29 : msg->msg_flags = omsg->msg_flags; /* flags on received message */
7867 : #endif
7868 :
7869 29 : rc = swrap_sendmsg_before(s, si, msg,
7870 : &tmp[i].iov,
7871 : &tmp[i].un_addr,
7872 : &tmp[i].to_un,
7873 : &tmp[i].to,
7874 : &tmp[i].bcast);
7875 29 : if (rc < 0) {
7876 0 : ret = rc;
7877 0 : goto fail_swrap;
7878 : }
7879 :
7880 29 : if (tmp[i].bcast) {
7881 0 : found_bcast = 1;
7882 : }
7883 : }
7884 :
7885 58 : if (found_bcast) {
7886 :
7887 0 : swrap_dir = socket_wrapper_dir();
7888 0 : if (swrap_dir == NULL) {
7889 0 : ret = -1;
7890 0 : goto fail_swrap;
7891 : }
7892 :
7893 0 : for (i = 0; i < vlen; i++) {
7894 0 : struct msghdr *msg = &msgvec[i].msg_hdr;
7895 0 : struct sockaddr_un *un_addr = &tmp[i].un_addr;
7896 0 : const struct sockaddr *to = tmp[i].to;
7897 : struct stat st;
7898 : unsigned int iface;
7899 0 : unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7900 : char type;
7901 0 : size_t l, len = 0;
7902 : uint8_t *buf;
7903 0 : off_t ofs = 0;
7904 0 : size_t avail = 0;
7905 : size_t remain;
7906 :
7907 0 : for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7908 0 : avail += msg->msg_iov[l].iov_len;
7909 : }
7910 :
7911 0 : len = avail;
7912 0 : remain = avail;
7913 :
7914 : /* we capture it as one single packet */
7915 0 : buf = (uint8_t *)malloc(remain);
7916 0 : if (!buf) {
7917 0 : ret = -1;
7918 0 : goto fail_swrap;
7919 : }
7920 :
7921 0 : for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7922 0 : size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
7923 0 : memcpy(buf + ofs,
7924 0 : msg->msg_iov[l].iov_base,
7925 : this_time);
7926 0 : ofs += this_time;
7927 0 : remain -= this_time;
7928 : }
7929 :
7930 0 : type = SOCKET_TYPE_CHAR_UDP;
7931 :
7932 0 : for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7933 0 : swrap_un_path(un_addr, swrap_dir, type, iface, prt);
7934 0 : if (stat(un_addr->sun_path, &st) != 0) continue;
7935 :
7936 0 : msg->msg_name = un_addr; /* optional address */
7937 0 : msg->msg_namelen = sizeof(*un_addr); /* size of address */
7938 :
7939 : /*
7940 : * ignore the any errors in broadcast sends and
7941 : * do a single sendmsg instead of sendmmsg
7942 : */
7943 0 : libc_sendmsg(s, msg, flags);
7944 : }
7945 :
7946 0 : SWRAP_LOCK_SI(si);
7947 0 : swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7948 0 : SWRAP_UNLOCK_SI(si);
7949 :
7950 0 : SAFE_FREE(buf);
7951 :
7952 0 : msgvec[i].msg_len = len;
7953 : }
7954 :
7955 0 : ret = vlen;
7956 0 : goto bcast_done;
7957 : }
7958 :
7959 58 : ret = libc_sendmmsg(s, msgvec, vlen, flags);
7960 58 : if (ret < 0) {
7961 0 : goto fail_swrap;
7962 : }
7963 :
7964 58 : bcast_done:
7965 87 : for (i = 0; i < ret; i++) {
7966 29 : omsgvec[i].msg_len = msgvec[i].msg_len;
7967 : }
7968 :
7969 58 : fail_swrap:
7970 58 : saved_errno = errno;
7971 87 : for (i = 0; i < vlen; i++) {
7972 29 : struct msghdr *msg = &msgvec[i].msg_hdr;
7973 :
7974 29 : if (i == 0 || i < ret) {
7975 29 : swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
7976 : }
7977 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7978 29 : SAFE_FREE(msg->msg_control);
7979 : #endif
7980 : }
7981 58 : SAFE_FREE(swrap_dir);
7982 58 : errno = saved_errno;
7983 :
7984 58 : return ret;
7985 : }
7986 :
7987 : #if defined(HAVE_SENDMMSG_SSIZE_T)
7988 : /* FreeBSD */
7989 : ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
7990 : #else
7991 : /* Linux */
7992 : int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
7993 : #endif
7994 : {
7995 0 : return swrap_sendmmsg(s, msgvec, vlen, flags);
7996 : }
7997 : #endif /* HAVE_SENDMMSG */
7998 :
7999 : /****************************************************************************
8000 : * READV
8001 : ***************************************************************************/
8002 :
8003 9886742 : static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
8004 : {
8005 : struct socket_info *si;
8006 : struct msghdr msg;
8007 : struct iovec tmp;
8008 9886742 : struct swrap_address saddr = {
8009 : .sa_socklen = sizeof(struct sockaddr_storage)
8010 : };
8011 : ssize_t ret;
8012 : int rc;
8013 :
8014 9886742 : si = find_socket_info(s);
8015 9886742 : if (si == NULL) {
8016 615677 : return libc_readv(s, vector, count);
8017 : }
8018 :
8019 9271065 : tmp.iov_base = NULL;
8020 9271065 : tmp.iov_len = 0;
8021 :
8022 9271065 : ZERO_STRUCT(msg);
8023 9271065 : msg.msg_name = &saddr.sa.s; /* optional address */
8024 9271065 : msg.msg_namelen = saddr.sa_socklen; /* size of address */
8025 9271065 : msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8026 9271065 : msg.msg_iovlen = count; /* # elements in msg_iov */
8027 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8028 9271065 : msg.msg_control = NULL; /* ancillary data, see below */
8029 9271065 : msg.msg_controllen = 0; /* ancillary data buffer len */
8030 9271065 : msg.msg_flags = 0; /* flags on received message */
8031 : #endif
8032 :
8033 9271065 : rc = swrap_recvmsg_before(s, si, &msg, &tmp);
8034 9271065 : if (rc < 0) {
8035 0 : if (rc == -ENOTSOCK) {
8036 0 : return libc_readv(s, vector, count);
8037 : }
8038 0 : return -1;
8039 : }
8040 :
8041 9271065 : ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
8042 :
8043 9271065 : rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
8044 9271065 : if (rc != 0) {
8045 0 : return rc;
8046 : }
8047 :
8048 9271065 : return ret;
8049 : }
8050 :
8051 : ssize_t readv(int s, const struct iovec *vector, int count)
8052 : {
8053 9886742 : return swrap_readv(s, vector, count);
8054 : }
8055 :
8056 : /****************************************************************************
8057 : * WRITEV
8058 : ***************************************************************************/
8059 :
8060 7976089 : static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8061 : {
8062 : struct msghdr msg;
8063 : struct iovec tmp;
8064 : struct sockaddr_un un_addr;
8065 : ssize_t ret;
8066 : int rc;
8067 7976089 : struct socket_info *si = find_socket_info(s);
8068 :
8069 7976089 : if (!si) {
8070 578762 : return libc_writev(s, vector, count);
8071 : }
8072 :
8073 7397327 : tmp.iov_base = NULL;
8074 7397327 : tmp.iov_len = 0;
8075 :
8076 7397327 : ZERO_STRUCT(msg);
8077 7397327 : msg.msg_name = NULL; /* optional address */
8078 7397327 : msg.msg_namelen = 0; /* size of address */
8079 7397327 : msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8080 7397327 : msg.msg_iovlen = count; /* # elements in msg_iov */
8081 : #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8082 7397327 : msg.msg_control = NULL; /* ancillary data, see below */
8083 7397327 : msg.msg_controllen = 0; /* ancillary data buffer len */
8084 7397327 : msg.msg_flags = 0; /* flags on received message */
8085 : #endif
8086 :
8087 7397327 : rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8088 7397327 : if (rc < 0) {
8089 0 : if (rc == -ENOTSOCK) {
8090 0 : return libc_readv(s, vector, count);
8091 : }
8092 0 : return -1;
8093 : }
8094 :
8095 7397327 : ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8096 :
8097 7397327 : swrap_sendmsg_after(s, si, &msg, NULL, ret);
8098 :
8099 7397327 : return ret;
8100 : }
8101 :
8102 : ssize_t writev(int s, const struct iovec *vector, int count)
8103 : {
8104 7976089 : return swrap_writev(s, vector, count);
8105 : }
8106 :
8107 : /****************************
8108 : * CLOSE
8109 : ***************************/
8110 :
8111 42232391 : static int swrap_remove_wrapper(const char *__func_name,
8112 : int (*__close_fd_fn)(int fd),
8113 : int fd)
8114 : {
8115 42232391 : struct socket_info *si = NULL;
8116 : int si_index;
8117 42232391 : int ret_errno = errno;
8118 : int ret;
8119 :
8120 42232391 : swrap_mutex_lock(&socket_reset_mutex);
8121 :
8122 42232391 : si_index = find_socket_info_index(fd);
8123 42232391 : if (si_index == -1) {
8124 40988600 : swrap_mutex_unlock(&socket_reset_mutex);
8125 40988600 : return __close_fd_fn(fd);
8126 : }
8127 :
8128 1243791 : swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8129 1243791 : reset_socket_info_index(fd);
8130 :
8131 1243791 : si = swrap_get_socket_info(si_index);
8132 :
8133 1243791 : swrap_mutex_lock(&first_free_mutex);
8134 1243791 : SWRAP_LOCK_SI(si);
8135 :
8136 1243791 : ret = __close_fd_fn(fd);
8137 1243791 : if (ret == -1) {
8138 0 : ret_errno = errno;
8139 : }
8140 :
8141 1243791 : swrap_dec_refcount(si);
8142 :
8143 1243791 : if (swrap_get_refcount(si) > 0) {
8144 : /* there are still references left */
8145 15313 : goto out;
8146 : }
8147 :
8148 1228478 : if (si->fd_passed) {
8149 424 : goto set_next_free;
8150 : }
8151 :
8152 1228054 : if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8153 233818 : swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8154 : }
8155 :
8156 1228054 : if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8157 233818 : swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8158 233818 : swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8159 : }
8160 :
8161 1228054 : if (si->un_addr.sun_path[0] != '\0') {
8162 123530 : unlink(si->un_addr.sun_path);
8163 : }
8164 :
8165 1104524 : set_next_free:
8166 1228478 : swrap_set_next_free(si, first_free);
8167 1228478 : first_free = si_index;
8168 :
8169 1243791 : out:
8170 1243791 : SWRAP_UNLOCK_SI(si);
8171 1243791 : swrap_mutex_unlock(&first_free_mutex);
8172 1243791 : swrap_mutex_unlock(&socket_reset_mutex);
8173 :
8174 1243791 : errno = ret_errno;
8175 1243791 : return ret;
8176 : }
8177 :
8178 4516036 : static int swrap_noop_close(int fd)
8179 : {
8180 : (void)fd; /* unused */
8181 4516036 : return 0;
8182 : }
8183 :
8184 4516036 : static void swrap_remove_stale(int fd)
8185 : {
8186 4516036 : swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8187 4516036 : }
8188 :
8189 : /*
8190 : * This allows socket_wrapper aware applications to
8191 : * indicate that the given fd does not belong to
8192 : * an inet socket.
8193 : *
8194 : * We already overload a lot of unrelated functions
8195 : * like eventfd(), timerfd_create(), ... in order to
8196 : * call swrap_remove_stale() on the returned fd, but
8197 : * we'll never be able to handle all possible syscalls.
8198 : *
8199 : * socket_wrapper_indicate_no_inet_fd() gives them a way
8200 : * to do the same.
8201 : *
8202 : * We don't export swrap_remove_stale() in order to
8203 : * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8204 : * log files.
8205 : */
8206 0 : void socket_wrapper_indicate_no_inet_fd(int fd)
8207 : {
8208 0 : swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8209 0 : }
8210 :
8211 37716355 : static int swrap_close(int fd)
8212 : {
8213 37716355 : return swrap_remove_wrapper(__func__, libc_close, fd);
8214 : }
8215 :
8216 : int close(int fd)
8217 : {
8218 37715125 : return swrap_close(fd);
8219 : }
8220 :
8221 : #ifdef HAVE___CLOSE_NOCANCEL
8222 :
8223 0 : static int swrap___close_nocancel(int fd)
8224 : {
8225 0 : return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8226 : }
8227 :
8228 : int __close_nocancel(int fd);
8229 0 : int __close_nocancel(int fd)
8230 : {
8231 0 : return swrap___close_nocancel(fd);
8232 : }
8233 :
8234 : #endif /* HAVE___CLOSE_NOCANCEL */
8235 :
8236 : /****************************
8237 : * DUP
8238 : ***************************/
8239 :
8240 75434 : static int swrap_dup(int fd)
8241 : {
8242 : struct socket_info *si;
8243 : int dup_fd, idx;
8244 :
8245 75434 : idx = find_socket_info_index(fd);
8246 75434 : if (idx == -1) {
8247 60121 : return libc_dup(fd);
8248 : }
8249 :
8250 15313 : si = swrap_get_socket_info(idx);
8251 :
8252 15313 : dup_fd = libc_dup(fd);
8253 15313 : if (dup_fd == -1) {
8254 0 : int saved_errno = errno;
8255 0 : errno = saved_errno;
8256 0 : return -1;
8257 : }
8258 :
8259 15313 : if ((size_t)dup_fd >= socket_fds_max) {
8260 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
8261 : "The max socket index limit of %zu has been reached, "
8262 : "trying to add %d",
8263 : socket_fds_max,
8264 : dup_fd);
8265 0 : libc_close(dup_fd);
8266 0 : errno = EMFILE;
8267 0 : return -1;
8268 : }
8269 :
8270 15313 : SWRAP_LOCK_SI(si);
8271 :
8272 15313 : swrap_inc_refcount(si);
8273 :
8274 15313 : SWRAP_UNLOCK_SI(si);
8275 :
8276 : /* Make sure we don't have an entry for the fd */
8277 15313 : swrap_remove_stale(dup_fd);
8278 :
8279 15313 : set_socket_info_index(dup_fd, idx);
8280 :
8281 15313 : return dup_fd;
8282 : }
8283 :
8284 : int dup(int fd)
8285 : {
8286 75434 : return swrap_dup(fd);
8287 : }
8288 :
8289 : /****************************
8290 : * DUP2
8291 : ***************************/
8292 :
8293 68578 : static int swrap_dup2(int fd, int newfd)
8294 : {
8295 : struct socket_info *si;
8296 : int dup_fd, idx;
8297 :
8298 68578 : idx = find_socket_info_index(fd);
8299 68578 : if (idx == -1) {
8300 68578 : return libc_dup2(fd, newfd);
8301 : }
8302 :
8303 0 : si = swrap_get_socket_info(idx);
8304 :
8305 0 : if (fd == newfd) {
8306 : /*
8307 : * According to the manpage:
8308 : *
8309 : * "If oldfd is a valid file descriptor, and newfd has the same
8310 : * value as oldfd, then dup2() does nothing, and returns newfd."
8311 : */
8312 0 : return newfd;
8313 : }
8314 :
8315 0 : if ((size_t)newfd >= socket_fds_max) {
8316 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
8317 : "The max socket index limit of %zu has been reached, "
8318 : "trying to add %d",
8319 : socket_fds_max,
8320 : newfd);
8321 0 : errno = EMFILE;
8322 0 : return -1;
8323 : }
8324 :
8325 0 : if (find_socket_info(newfd)) {
8326 : /* dup2() does an implicit close of newfd, which we
8327 : * need to emulate */
8328 0 : swrap_close(newfd);
8329 : }
8330 :
8331 0 : dup_fd = libc_dup2(fd, newfd);
8332 0 : if (dup_fd == -1) {
8333 0 : int saved_errno = errno;
8334 0 : errno = saved_errno;
8335 0 : return -1;
8336 : }
8337 :
8338 0 : SWRAP_LOCK_SI(si);
8339 :
8340 0 : swrap_inc_refcount(si);
8341 :
8342 0 : SWRAP_UNLOCK_SI(si);
8343 :
8344 : /* Make sure we don't have an entry for the fd */
8345 0 : swrap_remove_stale(dup_fd);
8346 :
8347 0 : set_socket_info_index(dup_fd, idx);
8348 :
8349 0 : return dup_fd;
8350 : }
8351 :
8352 : int dup2(int fd, int newfd)
8353 : {
8354 68578 : return swrap_dup2(fd, newfd);
8355 : }
8356 :
8357 : /****************************
8358 : * FCNTL
8359 : ***************************/
8360 :
8361 211837504 : static int swrap_vfcntl(int fd, int cmd, va_list va)
8362 : {
8363 : struct socket_info *si;
8364 : int rc, dup_fd, idx;
8365 :
8366 211837504 : idx = find_socket_info_index(fd);
8367 211837504 : if (idx == -1) {
8368 210168197 : return libc_vfcntl(fd, cmd, va);
8369 : }
8370 :
8371 1669307 : si = swrap_get_socket_info(idx);
8372 :
8373 1669307 : switch (cmd) {
8374 0 : case F_DUPFD:
8375 0 : dup_fd = libc_vfcntl(fd, cmd, va);
8376 0 : if (dup_fd == -1) {
8377 0 : int saved_errno = errno;
8378 0 : errno = saved_errno;
8379 0 : return -1;
8380 : }
8381 :
8382 : /* Make sure we don't have an entry for the fd */
8383 0 : swrap_remove_stale(dup_fd);
8384 :
8385 0 : if ((size_t)dup_fd >= socket_fds_max) {
8386 0 : SWRAP_LOG(SWRAP_LOG_ERROR,
8387 : "The max socket index limit of %zu has been reached, "
8388 : "trying to add %d",
8389 : socket_fds_max,
8390 : dup_fd);
8391 0 : libc_close(dup_fd);
8392 0 : errno = EMFILE;
8393 0 : return -1;
8394 : }
8395 :
8396 0 : SWRAP_LOCK_SI(si);
8397 :
8398 0 : swrap_inc_refcount(si);
8399 :
8400 0 : SWRAP_UNLOCK_SI(si);
8401 :
8402 :
8403 0 : set_socket_info_index(dup_fd, idx);
8404 :
8405 0 : rc = dup_fd;
8406 0 : break;
8407 1669307 : default:
8408 1669307 : rc = libc_vfcntl(fd, cmd, va);
8409 1669307 : break;
8410 : }
8411 :
8412 1669307 : return rc;
8413 : }
8414 :
8415 : int fcntl(int fd, int cmd, ...)
8416 : {
8417 : va_list va;
8418 : int rc;
8419 :
8420 211837504 : va_start(va, cmd);
8421 :
8422 211837504 : rc = swrap_vfcntl(fd, cmd, va);
8423 :
8424 211837504 : va_end(va);
8425 :
8426 211837504 : return rc;
8427 : }
8428 :
8429 : /****************************
8430 : * EVENTFD
8431 : ***************************/
8432 :
8433 : #ifdef HAVE_EVENTFD
8434 21614 : static int swrap_eventfd(int count, int flags)
8435 : {
8436 : int fd;
8437 :
8438 21614 : fd = libc_eventfd(count, flags);
8439 21614 : if (fd != -1) {
8440 21614 : swrap_remove_stale(fd);
8441 : }
8442 :
8443 21614 : return fd;
8444 : }
8445 :
8446 : #ifdef HAVE_EVENTFD_UNSIGNED_INT
8447 : int eventfd(unsigned int count, int flags)
8448 : #else
8449 : int eventfd(int count, int flags)
8450 : #endif
8451 : {
8452 21614 : return swrap_eventfd(count, flags);
8453 : }
8454 : #endif
8455 :
8456 : #ifdef HAVE_PLEDGE
8457 : int pledge(const char *promises, const char *paths[])
8458 : {
8459 : (void)promises; /* unused */
8460 : (void)paths; /* unused */
8461 :
8462 : return 0;
8463 : }
8464 : #endif /* HAVE_PLEDGE */
8465 :
8466 : #ifdef HAVE_SYSCALL
8467 6559603 : static bool swrap_is_swrap_related_syscall(long int sysno)
8468 : {
8469 6559603 : switch (sysno) {
8470 : #ifdef SYS_close
8471 218 : case SYS_close:
8472 218 : return true;
8473 : #endif /* SYS_close */
8474 :
8475 : #ifdef SYS_recvmmsg
8476 0 : case SYS_recvmmsg:
8477 0 : return true;
8478 : #endif /* SYS_recvmmsg */
8479 :
8480 : #ifdef SYS_sendmmsg
8481 58 : case SYS_sendmmsg:
8482 58 : return true;
8483 : #endif /* SYS_sendmmsg */
8484 :
8485 6559327 : default:
8486 6559327 : return false;
8487 : }
8488 : }
8489 :
8490 276 : static long int swrap_syscall(long int sysno, va_list vp)
8491 : {
8492 : long int rc;
8493 :
8494 276 : switch (sysno) {
8495 : #ifdef SYS_close
8496 218 : case SYS_close:
8497 : {
8498 218 : int fd = (int)va_arg(vp, int);
8499 :
8500 218 : SWRAP_LOG(SWRAP_LOG_TRACE,
8501 : "calling swrap_close syscall %lu",
8502 : sysno);
8503 218 : rc = swrap_close(fd);
8504 : }
8505 218 : break;
8506 : #endif /* SYS_close */
8507 :
8508 : #ifdef SYS_recvmmsg
8509 0 : case SYS_recvmmsg:
8510 : {
8511 0 : int fd = (int)va_arg(vp, int);
8512 0 : struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8513 0 : unsigned int vlen = va_arg(vp, unsigned int);
8514 0 : int flags = va_arg(vp, int);
8515 0 : struct timespec *timeout = va_arg(vp, struct timespec *);
8516 :
8517 0 : SWRAP_LOG(SWRAP_LOG_TRACE,
8518 : "calling swrap_recvmmsg syscall %lu",
8519 : sysno);
8520 0 : rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8521 : }
8522 0 : break;
8523 : #endif /* SYS_recvmmsg */
8524 :
8525 : #ifdef SYS_sendmmsg
8526 58 : case SYS_sendmmsg:
8527 : {
8528 58 : int fd = (int)va_arg(vp, int);
8529 58 : struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8530 58 : unsigned int vlen = va_arg(vp, unsigned int);
8531 58 : int flags = va_arg(vp, int);
8532 :
8533 58 : SWRAP_LOG(SWRAP_LOG_TRACE,
8534 : "calling swrap_sendmmsg syscall %lu",
8535 : sysno);
8536 58 : rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8537 : }
8538 58 : break;
8539 : #endif /* SYS_sendmmsg */
8540 :
8541 0 : default:
8542 0 : rc = -1;
8543 0 : errno = ENOSYS;
8544 0 : break;
8545 : }
8546 :
8547 276 : return rc;
8548 : }
8549 :
8550 : #ifdef HAVE_SYSCALL_INT
8551 : int syscall(int sysno, ...)
8552 : #else
8553 : long int syscall(long int sysno, ...)
8554 : #endif
8555 : {
8556 : #ifdef HAVE_SYSCALL_INT
8557 : int rc;
8558 : #else
8559 : long int rc;
8560 : #endif
8561 : va_list va;
8562 :
8563 6559603 : va_start(va, sysno);
8564 :
8565 : /*
8566 : * We should only handle the syscall numbers
8567 : * we care about...
8568 : */
8569 6559603 : if (!swrap_is_swrap_related_syscall(sysno)) {
8570 : /*
8571 : * We need to give socket_wrapper a
8572 : * chance to take over...
8573 : */
8574 6559327 : if (swrap_uwrap_syscall_valid(sysno)) {
8575 6245940 : rc = swrap_uwrap_syscall_va(sysno, va);
8576 6245940 : va_end(va);
8577 6245940 : return rc;
8578 : }
8579 :
8580 313387 : rc = libc_vsyscall(sysno, va);
8581 313387 : va_end(va);
8582 313387 : return rc;
8583 : }
8584 :
8585 276 : if (!socket_wrapper_enabled()) {
8586 0 : rc = libc_vsyscall(sysno, va);
8587 0 : va_end(va);
8588 0 : return rc;
8589 : }
8590 :
8591 276 : rc = swrap_syscall(sysno, va);
8592 276 : va_end(va);
8593 :
8594 276 : return rc;
8595 : }
8596 :
8597 : /* used by uid_wrapper */
8598 : bool socket_wrapper_syscall_valid(long int sysno);
8599 0 : bool socket_wrapper_syscall_valid(long int sysno)
8600 : {
8601 0 : if (!swrap_is_swrap_related_syscall(sysno)) {
8602 0 : return false;
8603 : }
8604 :
8605 0 : if (!socket_wrapper_enabled()) {
8606 0 : return false;
8607 : }
8608 :
8609 0 : return true;
8610 : }
8611 :
8612 : /* used by uid_wrapper */
8613 : long int socket_wrapper_syscall_va(long int sysno, va_list va);
8614 0 : long int socket_wrapper_syscall_va(long int sysno, va_list va)
8615 : {
8616 0 : if (!swrap_is_swrap_related_syscall(sysno)) {
8617 0 : errno = ENOSYS;
8618 0 : return -1;
8619 : }
8620 :
8621 0 : if (!socket_wrapper_enabled()) {
8622 0 : return libc_vsyscall(sysno, va);
8623 : }
8624 :
8625 0 : return swrap_syscall(sysno, va);
8626 : }
8627 : #endif /* HAVE_SYSCALL */
8628 :
8629 404903 : static void swrap_thread_prepare(void)
8630 : {
8631 : /*
8632 : * This function should only be called here!!
8633 : *
8634 : * We bind all symobls to avoid deadlocks of the fork is
8635 : * interrupted by a signal handler using a symbol of this
8636 : * library.
8637 : */
8638 404903 : swrap_bind_symbol_all();
8639 :
8640 404903 : SWRAP_LOCK_ALL;
8641 404903 : }
8642 :
8643 401262 : static void swrap_thread_parent(void)
8644 : {
8645 401262 : SWRAP_UNLOCK_ALL;
8646 401262 : }
8647 :
8648 3641 : static void swrap_thread_child(void)
8649 : {
8650 3641 : SWRAP_REINIT_ALL;
8651 3641 : }
8652 :
8653 : /****************************
8654 : * CONSTRUCTOR
8655 : ***************************/
8656 58681 : void swrap_constructor(void)
8657 : {
8658 : if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8659 : SWRAP_LOG(SWRAP_LOG_ERROR,
8660 : "PIPE_BUF=%zu < "
8661 : "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8662 : "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8663 : "sizeof(struct socket_info)=%zu",
8664 : (size_t)PIPE_BUF,
8665 : sizeof(struct swrap_unix_scm_rights),
8666 : sizeof(struct swrap_unix_scm_rights_payload),
8667 : sizeof(struct socket_info));
8668 : exit(-1);
8669 : }
8670 :
8671 58681 : SWRAP_REINIT_ALL;
8672 :
8673 : /*
8674 : * If we hold a lock and the application forks, then the child
8675 : * is not able to unlock the mutex and we are in a deadlock.
8676 : * This should prevent such deadlocks.
8677 : */
8678 58681 : pthread_atfork(&swrap_thread_prepare,
8679 : &swrap_thread_parent,
8680 : &swrap_thread_child);
8681 58681 : }
8682 :
8683 : /****************************
8684 : * DESTRUCTOR
8685 : ***************************/
8686 :
8687 : /*
8688 : * This function is called when the library is unloaded and makes sure that
8689 : * sockets get closed and the unix file for the socket are unlinked.
8690 : */
8691 80040 : void swrap_destructor(void)
8692 : {
8693 : size_t i;
8694 :
8695 80040 : if (socket_fds_idx != NULL) {
8696 9117788262 : for (i = 0; i < socket_fds_max; ++i) {
8697 9117753480 : if (socket_fds_idx[i] != -1) {
8698 1012 : swrap_close(i);
8699 : }
8700 : }
8701 34782 : SAFE_FREE(socket_fds_idx);
8702 : }
8703 :
8704 80040 : SAFE_FREE(sockets);
8705 :
8706 80040 : if (swrap.libc.handle != NULL
8707 : #ifdef RTLD_NEXT
8708 80040 : && swrap.libc.handle != RTLD_NEXT
8709 : #endif
8710 : ) {
8711 80040 : dlclose(swrap.libc.handle);
8712 : }
8713 80040 : if (swrap.libc.socket_handle
8714 : #ifdef RTLD_NEXT
8715 0 : && swrap.libc.socket_handle != RTLD_NEXT
8716 : #endif
8717 : ) {
8718 0 : dlclose(swrap.libc.socket_handle);
8719 : }
8720 80040 : }
8721 :
8722 : #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8723 : /*
8724 : * On FreeBSD 12 (and maybe other platforms)
8725 : * system libraries like libresolv prefix there
8726 : * syscalls with '_' in order to always use
8727 : * the symbols from libc.
8728 : *
8729 : * In the interaction with resolv_wrapper,
8730 : * we need to inject socket wrapper into libresolv,
8731 : * which means we need to private all socket
8732 : * related syscalls also with the '_' prefix.
8733 : *
8734 : * This is tested in Samba's 'make test',
8735 : * there we noticed that providing '_read',
8736 : * '_open' and '_close' would cause errors, which
8737 : * means we skip '_read', '_write' and
8738 : * all non socket related calls without
8739 : * further analyzing the problem.
8740 : */
8741 : #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8742 : extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8743 :
8744 : #ifdef HAVE_ACCEPT4
8745 : SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8746 : #endif
8747 : SWRAP_SYMBOL_ALIAS(accept, _accept);
8748 : SWRAP_SYMBOL_ALIAS(bind, _bind);
8749 : SWRAP_SYMBOL_ALIAS(connect, _connect);
8750 : SWRAP_SYMBOL_ALIAS(dup, _dup);
8751 : SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8752 : SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8753 : SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8754 : SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8755 : SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8756 : SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8757 : SWRAP_SYMBOL_ALIAS(listen, _listen);
8758 : SWRAP_SYMBOL_ALIAS(readv, _readv);
8759 : SWRAP_SYMBOL_ALIAS(recv, _recv);
8760 : SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8761 : SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8762 : SWRAP_SYMBOL_ALIAS(send, _send);
8763 : SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8764 : SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8765 : SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8766 : SWRAP_SYMBOL_ALIAS(socket, _socket);
8767 : SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8768 : SWRAP_SYMBOL_ALIAS(writev, _writev);
8769 :
8770 : #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */
|