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