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