docs: insert meta data into dns forwarder parameter
[Samba/wip.git] / lib / socket_wrapper / socket_wrapper.c
bloba8369ad49dcb82abf6e9f4cf2776e160ab809f9c
1 /*
2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the author nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
39 is set.
42 #include "config.h"
44 #ifdef HAVE_LIBREPLACE
46 #define SOCKET_WRAPPER_NOT_REPLACE
47 #include "replace.h"
48 #include "system/network.h"
49 #include "system/filesys.h"
50 #include "system/time.h"
52 #else /* HAVE_LIBREPLACE */
54 #include <sys/types.h>
55 #include <sys/time.h>
56 #include <sys/stat.h>
57 #include <sys/socket.h>
58 #include <sys/ioctl.h>
59 #ifdef HAVE_SYS_FILIO_H
60 #include <sys/filio.h>
61 #endif
62 #include <errno.h>
63 #include <sys/un.h>
64 #include <netinet/in.h>
65 #include <netinet/tcp.h>
66 #include <fcntl.h>
67 #include <stdlib.h>
68 #include <unistd.h>
69 #include <string.h>
70 #include <stdio.h>
71 #include <stdint.h>
72 #include <arpa/inet.h>
74 #ifndef MIN
75 #define MIN(a,b) ((a)<(b)?(a):(b))
76 #endif
78 #ifndef discard_const_p
79 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
80 #endif
82 /**
83 * zero a structure
85 #ifndef ZERO_STRUCT
86 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
87 #endif
89 #endif /* HAVE_LIBREPLACE */
91 #include "socket_wrapper.h"
93 #ifndef _PUBLIC_
94 #define _PUBLIC_
95 #endif
97 #define SWRAP_DLIST_ADD(list,item) do { \
98 if (!(list)) { \
99 (item)->prev = NULL; \
100 (item)->next = NULL; \
101 (list) = (item); \
102 } else { \
103 (item)->prev = NULL; \
104 (item)->next = (list); \
105 (list)->prev = (item); \
106 (list) = (item); \
108 } while (0)
110 #define SWRAP_DLIST_REMOVE(list,item) do { \
111 if ((list) == (item)) { \
112 (list) = (item)->next; \
113 if (list) { \
114 (list)->prev = NULL; \
116 } else { \
117 if ((item)->prev) { \
118 (item)->prev->next = (item)->next; \
120 if ((item)->next) { \
121 (item)->next->prev = (item)->prev; \
124 (item)->prev = NULL; \
125 (item)->next = NULL; \
126 } while (0)
128 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
129 * for now */
130 #define REWRITE_CALLS
132 #ifdef REWRITE_CALLS
133 #define real_accept accept
134 #define real_connect connect
135 #define real_bind bind
136 #define real_listen listen
137 #define real_getpeername getpeername
138 #define real_getsockname getsockname
139 #define real_getsockopt getsockopt
140 #define real_setsockopt setsockopt
141 #define real_recvfrom recvfrom
142 #define real_sendto sendto
143 #define real_sendmsg sendmsg
144 #define real_ioctl ioctl
145 #define real_recv recv
146 #define real_read read
147 #define real_send send
148 #define real_readv readv
149 #define real_writev writev
150 #define real_socket socket
151 #define real_close close
152 #define real_dup dup
153 #define real_dup2 dup2
154 #endif
156 #ifdef HAVE_GETTIMEOFDAY_TZ
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
158 #else
159 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
160 #endif
162 /* we need to use a very terse format here as IRIX 6.4 silently
163 truncates names to 16 chars, so if we use a longer name then we
164 can't tell which port a packet came from with recvfrom()
166 with this format we have 8 chars left for the directory name
168 #define SOCKET_FORMAT "%c%02X%04X"
169 #define SOCKET_TYPE_CHAR_TCP 'T'
170 #define SOCKET_TYPE_CHAR_UDP 'U'
171 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
172 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
174 /* This limit is to avoid broadcast sendto() needing to stat too many
175 * files. It may be raised (with a performance cost) to up to 254
176 * without changing the format above */
177 #define MAX_WRAPPED_INTERFACES 40
179 #ifdef HAVE_IPV6
181 * FD00::5357:5FXX
183 static const struct in6_addr *swrap_ipv6(void)
185 static struct in6_addr v;
186 static int initialized;
187 int ret;
189 if (initialized) {
190 return &v;
192 initialized = 1;
194 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
195 if (ret <= 0) {
196 abort();
199 return &v;
201 #endif
203 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
205 struct sockaddr *ret = (struct sockaddr *)malloc(len);
206 memcpy(ret, data, len);
207 return ret;
210 static void set_port(int family, int prt, struct sockaddr *addr)
212 switch (family) {
213 case AF_INET:
214 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
215 break;
216 #ifdef HAVE_IPV6
217 case AF_INET6:
218 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
219 break;
220 #endif
224 static size_t socket_length(int family)
226 switch (family) {
227 case AF_INET:
228 return sizeof(struct sockaddr_in);
229 #ifdef HAVE_IPV6
230 case AF_INET6:
231 return sizeof(struct sockaddr_in6);
232 #endif
234 return 0;
237 struct socket_info_fd {
238 struct socket_info_fd *prev, *next;
239 int fd;
242 struct socket_info
244 struct socket_info_fd *fds;
246 int family;
247 int type;
248 int protocol;
249 int bound;
250 int bcast;
251 int is_server;
252 int connected;
253 int defer_connect;
255 char *tmp_path;
257 struct sockaddr *myname;
258 socklen_t myname_len;
260 struct sockaddr *peername;
261 socklen_t peername_len;
263 struct {
264 unsigned long pck_snd;
265 unsigned long pck_rcv;
266 } io;
268 struct socket_info *prev, *next;
271 static struct socket_info *sockets;
273 const char *socket_wrapper_dir(void)
275 const char *s = getenv("SOCKET_WRAPPER_DIR");
276 if (s == NULL) {
277 return NULL;
279 if (strncmp(s, "./", 2) == 0) {
280 s += 2;
282 return s;
285 unsigned int socket_wrapper_default_iface(void)
287 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
288 if (s) {
289 unsigned int iface;
290 if (sscanf(s, "%u", &iface) == 1) {
291 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
292 return iface;
297 return 1;/* 127.0.0.1 */
300 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
302 unsigned int iface;
303 unsigned int prt;
304 const char *p;
305 char type;
307 p = strrchr(un->sun_path, '/');
308 if (p) p++; else p = un->sun_path;
310 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
311 errno = EINVAL;
312 return -1;
315 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
316 errno = EINVAL;
317 return -1;
320 if (prt > 0xFFFF) {
321 errno = EINVAL;
322 return -1;
325 switch(type) {
326 case SOCKET_TYPE_CHAR_TCP:
327 case SOCKET_TYPE_CHAR_UDP: {
328 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
330 if ((*len) < sizeof(*in2)) {
331 errno = EINVAL;
332 return -1;
335 memset(in2, 0, sizeof(*in2));
336 in2->sin_family = AF_INET;
337 in2->sin_addr.s_addr = htonl((127<<24) | iface);
338 in2->sin_port = htons(prt);
340 *len = sizeof(*in2);
341 break;
343 #ifdef HAVE_IPV6
344 case SOCKET_TYPE_CHAR_TCP_V6:
345 case SOCKET_TYPE_CHAR_UDP_V6: {
346 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
348 if ((*len) < sizeof(*in2)) {
349 errno = EINVAL;
350 return -1;
353 memset(in2, 0, sizeof(*in2));
354 in2->sin6_family = AF_INET6;
355 in2->sin6_addr = *swrap_ipv6();
356 in2->sin6_addr.s6_addr[15] = iface;
357 in2->sin6_port = htons(prt);
359 *len = sizeof(*in2);
360 break;
362 #endif
363 default:
364 errno = EINVAL;
365 return -1;
368 return 0;
371 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
372 int *bcast)
374 char type = '\0';
375 unsigned int prt;
376 unsigned int iface;
377 int is_bcast = 0;
379 if (bcast) *bcast = 0;
381 switch (inaddr->sa_family) {
382 case AF_INET: {
383 const struct sockaddr_in *in =
384 (const struct sockaddr_in *)(const void *)inaddr;
385 unsigned int addr = ntohl(in->sin_addr.s_addr);
386 char u_type = '\0';
387 char b_type = '\0';
388 char a_type = '\0';
390 switch (si->type) {
391 case SOCK_STREAM:
392 u_type = SOCKET_TYPE_CHAR_TCP;
393 break;
394 case SOCK_DGRAM:
395 u_type = SOCKET_TYPE_CHAR_UDP;
396 a_type = SOCKET_TYPE_CHAR_UDP;
397 b_type = SOCKET_TYPE_CHAR_UDP;
398 break;
401 prt = ntohs(in->sin_port);
402 if (a_type && addr == 0xFFFFFFFF) {
403 /* 255.255.255.255 only udp */
404 is_bcast = 2;
405 type = a_type;
406 iface = socket_wrapper_default_iface();
407 } else if (b_type && addr == 0x7FFFFFFF) {
408 /* 127.255.255.255 only udp */
409 is_bcast = 1;
410 type = b_type;
411 iface = socket_wrapper_default_iface();
412 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
413 /* 127.0.0.X */
414 is_bcast = 0;
415 type = u_type;
416 iface = (addr & 0x000000FF);
417 } else {
418 errno = ENETUNREACH;
419 return -1;
421 if (bcast) *bcast = is_bcast;
422 break;
424 #ifdef HAVE_IPV6
425 case AF_INET6: {
426 const struct sockaddr_in6 *in =
427 (const struct sockaddr_in6 *)(const void *)inaddr;
428 struct in6_addr cmp1, cmp2;
430 switch (si->type) {
431 case SOCK_STREAM:
432 type = SOCKET_TYPE_CHAR_TCP_V6;
433 break;
434 case SOCK_DGRAM:
435 type = SOCKET_TYPE_CHAR_UDP_V6;
436 break;
439 /* XXX no multicast/broadcast */
441 prt = ntohs(in->sin6_port);
443 cmp1 = *swrap_ipv6();
444 cmp2 = in->sin6_addr;
445 cmp2.s6_addr[15] = 0;
446 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
447 iface = in->sin6_addr.s6_addr[15];
448 } else {
449 errno = ENETUNREACH;
450 return -1;
453 break;
455 #endif
456 default:
457 errno = ENETUNREACH;
458 return -1;
461 if (prt == 0) {
462 errno = EINVAL;
463 return -1;
466 if (is_bcast) {
467 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
468 socket_wrapper_dir());
469 /* the caller need to do more processing */
470 return 0;
473 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
474 socket_wrapper_dir(), type, iface, prt);
476 return 0;
479 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
480 int *bcast)
482 char type = '\0';
483 unsigned int prt;
484 unsigned int iface;
485 struct stat st;
486 int is_bcast = 0;
488 if (bcast) *bcast = 0;
490 switch (si->family) {
491 case AF_INET: {
492 const struct sockaddr_in *in =
493 (const struct sockaddr_in *)(const void *)inaddr;
494 unsigned int addr = ntohl(in->sin_addr.s_addr);
495 char u_type = '\0';
496 char d_type = '\0';
497 char b_type = '\0';
498 char a_type = '\0';
500 prt = ntohs(in->sin_port);
502 switch (si->type) {
503 case SOCK_STREAM:
504 u_type = SOCKET_TYPE_CHAR_TCP;
505 d_type = SOCKET_TYPE_CHAR_TCP;
506 break;
507 case SOCK_DGRAM:
508 u_type = SOCKET_TYPE_CHAR_UDP;
509 d_type = SOCKET_TYPE_CHAR_UDP;
510 a_type = SOCKET_TYPE_CHAR_UDP;
511 b_type = SOCKET_TYPE_CHAR_UDP;
512 break;
515 if (addr == 0) {
516 /* 0.0.0.0 */
517 is_bcast = 0;
518 type = d_type;
519 iface = socket_wrapper_default_iface();
520 } else if (a_type && addr == 0xFFFFFFFF) {
521 /* 255.255.255.255 only udp */
522 is_bcast = 2;
523 type = a_type;
524 iface = socket_wrapper_default_iface();
525 } else if (b_type && addr == 0x7FFFFFFF) {
526 /* 127.255.255.255 only udp */
527 is_bcast = 1;
528 type = b_type;
529 iface = socket_wrapper_default_iface();
530 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
531 /* 127.0.0.X */
532 is_bcast = 0;
533 type = u_type;
534 iface = (addr & 0x000000FF);
535 } else {
536 errno = EADDRNOTAVAIL;
537 return -1;
539 break;
541 #ifdef HAVE_IPV6
542 case AF_INET6: {
543 const struct sockaddr_in6 *in =
544 (const struct sockaddr_in6 *)(const void *)inaddr;
545 struct in6_addr cmp1, cmp2;
547 switch (si->type) {
548 case SOCK_STREAM:
549 type = SOCKET_TYPE_CHAR_TCP_V6;
550 break;
551 case SOCK_DGRAM:
552 type = SOCKET_TYPE_CHAR_UDP_V6;
553 break;
556 /* XXX no multicast/broadcast */
558 prt = ntohs(in->sin6_port);
560 cmp1 = *swrap_ipv6();
561 cmp2 = in->sin6_addr;
562 cmp2.s6_addr[15] = 0;
563 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
564 iface = socket_wrapper_default_iface();
565 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
566 iface = in->sin6_addr.s6_addr[15];
567 } else {
568 errno = EADDRNOTAVAIL;
569 return -1;
572 break;
574 #endif
575 default:
576 errno = EADDRNOTAVAIL;
577 return -1;
581 if (bcast) *bcast = is_bcast;
583 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
584 errno = EINVAL;
585 return -1;
588 if (prt == 0) {
589 /* handle auto-allocation of ephemeral ports */
590 for (prt = 5001; prt < 10000; prt++) {
591 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
592 socket_wrapper_dir(), type, iface, prt);
593 if (stat(un->sun_path, &st) == 0) continue;
595 set_port(si->family, prt, si->myname);
596 break;
598 if (prt == 10000) {
599 errno = ENFILE;
600 return -1;
604 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
605 socket_wrapper_dir(), type, iface, prt);
606 return 0;
609 static struct socket_info *find_socket_info(int fd)
611 struct socket_info *i;
612 for (i = sockets; i; i = i->next) {
613 struct socket_info_fd *f;
614 for (f = i->fds; f; f = f->next) {
615 if (f->fd == fd) {
616 return i;
621 return NULL;
624 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
625 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
627 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
628 if (!out_addr)
629 return 0;
631 out->sa_family = AF_UNIX;
632 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
633 out->sa_len = sizeof(*out_addr);
634 #endif
636 switch (in_addr->sa_family) {
637 case AF_INET:
638 #ifdef HAVE_IPV6
639 case AF_INET6:
640 #endif
641 switch (si->type) {
642 case SOCK_STREAM:
643 case SOCK_DGRAM:
644 break;
645 default:
646 errno = ESOCKTNOSUPPORT;
647 return -1;
649 if (alloc_sock) {
650 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
651 } else {
652 return convert_in_un_remote(si, in_addr, out_addr, bcast);
654 default:
655 break;
658 errno = EAFNOSUPPORT;
659 return -1;
662 static int sockaddr_convert_from_un(const struct socket_info *si,
663 const struct sockaddr_un *in_addr,
664 socklen_t un_addrlen,
665 int family,
666 struct sockaddr *out_addr,
667 socklen_t *out_addrlen)
669 int ret;
671 if (out_addr == NULL || out_addrlen == NULL)
672 return 0;
674 if (un_addrlen == 0) {
675 *out_addrlen = 0;
676 return 0;
679 switch (family) {
680 case AF_INET:
681 #ifdef HAVE_IPV6
682 case AF_INET6:
683 #endif
684 switch (si->type) {
685 case SOCK_STREAM:
686 case SOCK_DGRAM:
687 break;
688 default:
689 errno = ESOCKTNOSUPPORT;
690 return -1;
692 ret = convert_un_in(in_addr, out_addr, out_addrlen);
693 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
694 out_addr->sa_len = *out_addrlen;
695 #endif
696 return ret;
697 default:
698 break;
701 errno = EAFNOSUPPORT;
702 return -1;
705 enum swrap_packet_type {
706 SWRAP_CONNECT_SEND,
707 SWRAP_CONNECT_UNREACH,
708 SWRAP_CONNECT_RECV,
709 SWRAP_CONNECT_ACK,
710 SWRAP_ACCEPT_SEND,
711 SWRAP_ACCEPT_RECV,
712 SWRAP_ACCEPT_ACK,
713 SWRAP_RECVFROM,
714 SWRAP_SENDTO,
715 SWRAP_SENDTO_UNREACH,
716 SWRAP_PENDING_RST,
717 SWRAP_RECV,
718 SWRAP_RECV_RST,
719 SWRAP_SEND,
720 SWRAP_SEND_RST,
721 SWRAP_CLOSE_SEND,
722 SWRAP_CLOSE_RECV,
723 SWRAP_CLOSE_ACK,
726 struct swrap_file_hdr {
727 uint32_t magic;
728 uint16_t version_major;
729 uint16_t version_minor;
730 int32_t timezone;
731 uint32_t sigfigs;
732 uint32_t frame_max_len;
733 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
734 uint32_t link_type;
736 #define SWRAP_FILE_HDR_SIZE 24
738 struct swrap_packet_frame {
739 uint32_t seconds;
740 uint32_t micro_seconds;
741 uint32_t recorded_length;
742 uint32_t full_length;
744 #define SWRAP_PACKET_FRAME_SIZE 16
746 union swrap_packet_ip {
747 struct {
748 uint8_t ver_hdrlen;
749 uint8_t tos;
750 uint16_t packet_length;
751 uint16_t identification;
752 uint8_t flags;
753 uint8_t fragment;
754 uint8_t ttl;
755 uint8_t protocol;
756 uint16_t hdr_checksum;
757 uint32_t src_addr;
758 uint32_t dest_addr;
759 } v4;
760 #define SWRAP_PACKET_IP_V4_SIZE 20
761 struct {
762 uint8_t ver_prio;
763 uint8_t flow_label_high;
764 uint16_t flow_label_low;
765 uint16_t payload_length;
766 uint8_t next_header;
767 uint8_t hop_limit;
768 uint8_t src_addr[16];
769 uint8_t dest_addr[16];
770 } v6;
771 #define SWRAP_PACKET_IP_V6_SIZE 40
773 #define SWRAP_PACKET_IP_SIZE 40
775 union swrap_packet_payload {
776 struct {
777 uint16_t source_port;
778 uint16_t dest_port;
779 uint32_t seq_num;
780 uint32_t ack_num;
781 uint8_t hdr_length;
782 uint8_t control;
783 uint16_t window;
784 uint16_t checksum;
785 uint16_t urg;
786 } tcp;
787 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
788 struct {
789 uint16_t source_port;
790 uint16_t dest_port;
791 uint16_t length;
792 uint16_t checksum;
793 } udp;
794 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
795 struct {
796 uint8_t type;
797 uint8_t code;
798 uint16_t checksum;
799 uint32_t unused;
800 } icmp4;
801 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
802 struct {
803 uint8_t type;
804 uint8_t code;
805 uint16_t checksum;
806 uint32_t unused;
807 } icmp6;
808 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
810 #define SWRAP_PACKET_PAYLOAD_SIZE 20
812 #define SWRAP_PACKET_MIN_ALLOC \
813 (SWRAP_PACKET_FRAME_SIZE + \
814 SWRAP_PACKET_IP_SIZE + \
815 SWRAP_PACKET_PAYLOAD_SIZE)
817 static const char *socket_wrapper_pcap_file(void)
819 static int initialized = 0;
820 static const char *s = NULL;
821 static const struct swrap_file_hdr h;
822 static const struct swrap_packet_frame f;
823 static const union swrap_packet_ip i;
824 static const union swrap_packet_payload p;
826 if (initialized == 1) {
827 return s;
829 initialized = 1;
832 * TODO: don't use the structs use plain buffer offsets
833 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
835 * for now make sure we disable PCAP support
836 * if the struct has alignment!
838 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
839 return NULL;
841 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
842 return NULL;
844 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
845 return NULL;
847 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
848 return NULL;
850 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
851 return NULL;
853 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
854 return NULL;
856 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
857 return NULL;
859 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
860 return NULL;
862 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
863 return NULL;
865 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
866 return NULL;
869 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
870 if (s == NULL) {
871 return NULL;
873 if (strncmp(s, "./", 2) == 0) {
874 s += 2;
876 return s;
879 static uint8_t *swrap_packet_init(struct timeval *tval,
880 const struct sockaddr *src,
881 const struct sockaddr *dest,
882 int socket_type,
883 const uint8_t *payload,
884 size_t payload_len,
885 unsigned long tcp_seqno,
886 unsigned long tcp_ack,
887 unsigned char tcp_ctl,
888 int unreachable,
889 size_t *_packet_len)
891 uint8_t *base;
892 uint8_t *buf;
893 struct swrap_packet_frame *frame;
894 union swrap_packet_ip *ip;
895 union swrap_packet_payload *pay;
896 size_t packet_len;
897 size_t alloc_len;
898 size_t nonwire_len = sizeof(*frame);
899 size_t wire_hdr_len = 0;
900 size_t wire_len = 0;
901 size_t ip_hdr_len = 0;
902 size_t icmp_hdr_len = 0;
903 size_t icmp_truncate_len = 0;
904 uint8_t protocol = 0, icmp_protocol = 0;
905 const struct sockaddr_in *src_in = NULL;
906 const struct sockaddr_in *dest_in = NULL;
907 #ifdef HAVE_IPV6
908 const struct sockaddr_in6 *src_in6 = NULL;
909 const struct sockaddr_in6 *dest_in6 = NULL;
910 #endif
911 uint16_t src_port;
912 uint16_t dest_port;
914 switch (src->sa_family) {
915 case AF_INET:
916 src_in = (const struct sockaddr_in *)src;
917 dest_in = (const struct sockaddr_in *)dest;
918 src_port = src_in->sin_port;
919 dest_port = dest_in->sin_port;
920 ip_hdr_len = sizeof(ip->v4);
921 break;
922 #ifdef HAVE_IPV6
923 case AF_INET6:
924 src_in6 = (const struct sockaddr_in6 *)src;
925 dest_in6 = (const struct sockaddr_in6 *)dest;
926 src_port = src_in6->sin6_port;
927 dest_port = dest_in6->sin6_port;
928 ip_hdr_len = sizeof(ip->v6);
929 break;
930 #endif
931 default:
932 return NULL;
935 switch (socket_type) {
936 case SOCK_STREAM:
937 protocol = 0x06; /* TCP */
938 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
939 wire_len = wire_hdr_len + payload_len;
940 break;
942 case SOCK_DGRAM:
943 protocol = 0x11; /* UDP */
944 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
945 wire_len = wire_hdr_len + payload_len;
946 break;
948 default:
949 return NULL;
952 if (unreachable) {
953 icmp_protocol = protocol;
954 switch (src->sa_family) {
955 case AF_INET:
956 protocol = 0x01; /* ICMPv4 */
957 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
958 break;
959 #ifdef HAVE_IPV6
960 case AF_INET6:
961 protocol = 0x3A; /* ICMPv6 */
962 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
963 break;
964 #endif
966 if (wire_len > 64 ) {
967 icmp_truncate_len = wire_len - 64;
969 wire_hdr_len += icmp_hdr_len;
970 wire_len += icmp_hdr_len;
973 packet_len = nonwire_len + wire_len;
974 alloc_len = packet_len;
975 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
976 alloc_len = SWRAP_PACKET_MIN_ALLOC;
979 base = (uint8_t *)malloc(alloc_len);
980 if (!base) return NULL;
982 buf = base;
984 frame = (struct swrap_packet_frame *)buf;
985 frame->seconds = tval->tv_sec;
986 frame->micro_seconds = tval->tv_usec;
987 frame->recorded_length = wire_len - icmp_truncate_len;
988 frame->full_length = wire_len - icmp_truncate_len;
989 buf += SWRAP_PACKET_FRAME_SIZE;
991 ip = (union swrap_packet_ip *)buf;
992 switch (src->sa_family) {
993 case AF_INET:
994 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
995 ip->v4.tos = 0x00;
996 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
997 ip->v4.identification = htons(0xFFFF);
998 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
999 ip->v4.fragment = htons(0x0000);
1000 ip->v4.ttl = 0xFF;
1001 ip->v4.protocol = protocol;
1002 ip->v4.hdr_checksum = htons(0x0000);
1003 ip->v4.src_addr = src_in->sin_addr.s_addr;
1004 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1005 buf += SWRAP_PACKET_IP_V4_SIZE;
1006 break;
1007 #ifdef HAVE_IPV6
1008 case AF_INET6:
1009 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1010 ip->v6.flow_label_high = 0x00;
1011 ip->v6.flow_label_low = 0x0000;
1012 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1013 ip->v6.next_header = protocol;
1014 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1015 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1016 buf += SWRAP_PACKET_IP_V6_SIZE;
1017 break;
1018 #endif
1021 if (unreachable) {
1022 pay = (union swrap_packet_payload *)buf;
1023 switch (src->sa_family) {
1024 case AF_INET:
1025 pay->icmp4.type = 0x03; /* destination unreachable */
1026 pay->icmp4.code = 0x01; /* host unreachable */
1027 pay->icmp4.checksum = htons(0x0000);
1028 pay->icmp4.unused = htonl(0x00000000);
1029 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1031 /* set the ip header in the ICMP payload */
1032 ip = (union swrap_packet_ip *)buf;
1033 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1034 ip->v4.tos = 0x00;
1035 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1036 ip->v4.identification = htons(0xFFFF);
1037 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1038 ip->v4.fragment = htons(0x0000);
1039 ip->v4.ttl = 0xFF;
1040 ip->v4.protocol = icmp_protocol;
1041 ip->v4.hdr_checksum = htons(0x0000);
1042 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1043 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1044 buf += SWRAP_PACKET_IP_V4_SIZE;
1046 src_port = dest_in->sin_port;
1047 dest_port = src_in->sin_port;
1048 break;
1049 #ifdef HAVE_IPV6
1050 case AF_INET6:
1051 pay->icmp6.type = 0x01; /* destination unreachable */
1052 pay->icmp6.code = 0x03; /* address unreachable */
1053 pay->icmp6.checksum = htons(0x0000);
1054 pay->icmp6.unused = htonl(0x00000000);
1055 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1057 /* set the ip header in the ICMP payload */
1058 ip = (union swrap_packet_ip *)buf;
1059 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1060 ip->v6.flow_label_high = 0x00;
1061 ip->v6.flow_label_low = 0x0000;
1062 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1063 ip->v6.next_header = protocol;
1064 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1065 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1066 buf += SWRAP_PACKET_IP_V6_SIZE;
1068 src_port = dest_in6->sin6_port;
1069 dest_port = src_in6->sin6_port;
1070 break;
1071 #endif
1075 pay = (union swrap_packet_payload *)buf;
1077 switch (socket_type) {
1078 case SOCK_STREAM:
1079 pay->tcp.source_port = src_port;
1080 pay->tcp.dest_port = dest_port;
1081 pay->tcp.seq_num = htonl(tcp_seqno);
1082 pay->tcp.ack_num = htonl(tcp_ack);
1083 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1084 pay->tcp.control = tcp_ctl;
1085 pay->tcp.window = htons(0x7FFF);
1086 pay->tcp.checksum = htons(0x0000);
1087 pay->tcp.urg = htons(0x0000);
1088 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1090 break;
1092 case SOCK_DGRAM:
1093 pay->udp.source_port = src_port;
1094 pay->udp.dest_port = dest_port;
1095 pay->udp.length = htons(8 + payload_len);
1096 pay->udp.checksum = htons(0x0000);
1097 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1099 break;
1102 if (payload && payload_len > 0) {
1103 memcpy(buf, payload, payload_len);
1106 *_packet_len = packet_len - icmp_truncate_len;
1107 return base;
1110 static int swrap_get_pcap_fd(const char *fname)
1112 static int fd = -1;
1114 if (fd != -1) return fd;
1116 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1117 if (fd != -1) {
1118 struct swrap_file_hdr file_hdr;
1119 file_hdr.magic = 0xA1B2C3D4;
1120 file_hdr.version_major = 0x0002;
1121 file_hdr.version_minor = 0x0004;
1122 file_hdr.timezone = 0x00000000;
1123 file_hdr.sigfigs = 0x00000000;
1124 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1125 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1127 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1128 close(fd);
1129 fd = -1;
1131 return fd;
1134 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1136 return fd;
1139 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1140 const struct sockaddr *addr,
1141 enum swrap_packet_type type,
1142 const void *buf, size_t len,
1143 size_t *packet_len)
1145 const struct sockaddr *src_addr;
1146 const struct sockaddr *dest_addr;
1147 unsigned long tcp_seqno = 0;
1148 unsigned long tcp_ack = 0;
1149 unsigned char tcp_ctl = 0;
1150 int unreachable = 0;
1152 struct timeval tv;
1154 switch (si->family) {
1155 case AF_INET:
1156 break;
1157 #ifdef HAVE_IPV6
1158 case AF_INET6:
1159 break;
1160 #endif
1161 default:
1162 return NULL;
1165 switch (type) {
1166 case SWRAP_CONNECT_SEND:
1167 if (si->type != SOCK_STREAM) return NULL;
1169 src_addr = si->myname;
1170 dest_addr = addr;
1172 tcp_seqno = si->io.pck_snd;
1173 tcp_ack = si->io.pck_rcv;
1174 tcp_ctl = 0x02; /* SYN */
1176 si->io.pck_snd += 1;
1178 break;
1180 case SWRAP_CONNECT_RECV:
1181 if (si->type != SOCK_STREAM) return NULL;
1183 dest_addr = si->myname;
1184 src_addr = addr;
1186 tcp_seqno = si->io.pck_rcv;
1187 tcp_ack = si->io.pck_snd;
1188 tcp_ctl = 0x12; /** SYN,ACK */
1190 si->io.pck_rcv += 1;
1192 break;
1194 case SWRAP_CONNECT_UNREACH:
1195 if (si->type != SOCK_STREAM) return NULL;
1197 dest_addr = si->myname;
1198 src_addr = addr;
1200 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1201 tcp_seqno = si->io.pck_snd - 1;
1202 tcp_ack = si->io.pck_rcv;
1203 tcp_ctl = 0x02; /* SYN */
1204 unreachable = 1;
1206 break;
1208 case SWRAP_CONNECT_ACK:
1209 if (si->type != SOCK_STREAM) return NULL;
1211 src_addr = si->myname;
1212 dest_addr = addr;
1214 tcp_seqno = si->io.pck_snd;
1215 tcp_ack = si->io.pck_rcv;
1216 tcp_ctl = 0x10; /* ACK */
1218 break;
1220 case SWRAP_ACCEPT_SEND:
1221 if (si->type != SOCK_STREAM) return NULL;
1223 dest_addr = si->myname;
1224 src_addr = addr;
1226 tcp_seqno = si->io.pck_rcv;
1227 tcp_ack = si->io.pck_snd;
1228 tcp_ctl = 0x02; /* SYN */
1230 si->io.pck_rcv += 1;
1232 break;
1234 case SWRAP_ACCEPT_RECV:
1235 if (si->type != SOCK_STREAM) return NULL;
1237 src_addr = si->myname;
1238 dest_addr = addr;
1240 tcp_seqno = si->io.pck_snd;
1241 tcp_ack = si->io.pck_rcv;
1242 tcp_ctl = 0x12; /* SYN,ACK */
1244 si->io.pck_snd += 1;
1246 break;
1248 case SWRAP_ACCEPT_ACK:
1249 if (si->type != SOCK_STREAM) return NULL;
1251 dest_addr = si->myname;
1252 src_addr = addr;
1254 tcp_seqno = si->io.pck_rcv;
1255 tcp_ack = si->io.pck_snd;
1256 tcp_ctl = 0x10; /* ACK */
1258 break;
1260 case SWRAP_SEND:
1261 src_addr = si->myname;
1262 dest_addr = si->peername;
1264 tcp_seqno = si->io.pck_snd;
1265 tcp_ack = si->io.pck_rcv;
1266 tcp_ctl = 0x18; /* PSH,ACK */
1268 si->io.pck_snd += len;
1270 break;
1272 case SWRAP_SEND_RST:
1273 dest_addr = si->myname;
1274 src_addr = si->peername;
1276 if (si->type == SOCK_DGRAM) {
1277 return swrap_marshall_packet(si, si->peername,
1278 SWRAP_SENDTO_UNREACH,
1279 buf, len, packet_len);
1282 tcp_seqno = si->io.pck_rcv;
1283 tcp_ack = si->io.pck_snd;
1284 tcp_ctl = 0x14; /** RST,ACK */
1286 break;
1288 case SWRAP_PENDING_RST:
1289 dest_addr = si->myname;
1290 src_addr = si->peername;
1292 if (si->type == SOCK_DGRAM) {
1293 return NULL;
1296 tcp_seqno = si->io.pck_rcv;
1297 tcp_ack = si->io.pck_snd;
1298 tcp_ctl = 0x14; /* RST,ACK */
1300 break;
1302 case SWRAP_RECV:
1303 dest_addr = si->myname;
1304 src_addr = si->peername;
1306 tcp_seqno = si->io.pck_rcv;
1307 tcp_ack = si->io.pck_snd;
1308 tcp_ctl = 0x18; /* PSH,ACK */
1310 si->io.pck_rcv += len;
1312 break;
1314 case SWRAP_RECV_RST:
1315 dest_addr = si->myname;
1316 src_addr = si->peername;
1318 if (si->type == SOCK_DGRAM) {
1319 return NULL;
1322 tcp_seqno = si->io.pck_rcv;
1323 tcp_ack = si->io.pck_snd;
1324 tcp_ctl = 0x14; /* RST,ACK */
1326 break;
1328 case SWRAP_SENDTO:
1329 src_addr = si->myname;
1330 dest_addr = addr;
1332 si->io.pck_snd += len;
1334 break;
1336 case SWRAP_SENDTO_UNREACH:
1337 dest_addr = si->myname;
1338 src_addr = addr;
1340 unreachable = 1;
1342 break;
1344 case SWRAP_RECVFROM:
1345 dest_addr = si->myname;
1346 src_addr = addr;
1348 si->io.pck_rcv += len;
1350 break;
1352 case SWRAP_CLOSE_SEND:
1353 if (si->type != SOCK_STREAM) return NULL;
1355 src_addr = si->myname;
1356 dest_addr = si->peername;
1358 tcp_seqno = si->io.pck_snd;
1359 tcp_ack = si->io.pck_rcv;
1360 tcp_ctl = 0x11; /* FIN, ACK */
1362 si->io.pck_snd += 1;
1364 break;
1366 case SWRAP_CLOSE_RECV:
1367 if (si->type != SOCK_STREAM) return NULL;
1369 dest_addr = si->myname;
1370 src_addr = si->peername;
1372 tcp_seqno = si->io.pck_rcv;
1373 tcp_ack = si->io.pck_snd;
1374 tcp_ctl = 0x11; /* FIN,ACK */
1376 si->io.pck_rcv += 1;
1378 break;
1380 case SWRAP_CLOSE_ACK:
1381 if (si->type != SOCK_STREAM) return NULL;
1383 src_addr = si->myname;
1384 dest_addr = si->peername;
1386 tcp_seqno = si->io.pck_snd;
1387 tcp_ack = si->io.pck_rcv;
1388 tcp_ctl = 0x10; /* ACK */
1390 break;
1391 default:
1392 return NULL;
1395 swrapGetTimeOfDay(&tv);
1397 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1398 (const uint8_t *)buf, len,
1399 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1400 packet_len);
1403 static void swrap_dump_packet(struct socket_info *si,
1404 const struct sockaddr *addr,
1405 enum swrap_packet_type type,
1406 const void *buf, size_t len)
1408 const char *file_name;
1409 uint8_t *packet;
1410 size_t packet_len = 0;
1411 int fd;
1413 file_name = socket_wrapper_pcap_file();
1414 if (!file_name) {
1415 return;
1418 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1419 if (!packet) {
1420 return;
1423 fd = swrap_get_pcap_fd(file_name);
1424 if (fd != -1) {
1425 if (write(fd, packet, packet_len) != packet_len) {
1426 free(packet);
1427 return;
1431 free(packet);
1434 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1436 struct socket_info *si;
1437 struct socket_info_fd *fi;
1438 int fd;
1439 int real_type = type;
1440 #ifdef SOCK_CLOEXEC
1441 real_type &= ~SOCK_CLOEXEC;
1442 #endif
1443 #ifdef SOCK_NONBLOCK
1444 real_type &= ~SOCK_NONBLOCK;
1445 #endif
1447 if (!socket_wrapper_dir()) {
1448 return real_socket(family, type, protocol);
1451 switch (family) {
1452 case AF_INET:
1453 #ifdef HAVE_IPV6
1454 case AF_INET6:
1455 #endif
1456 break;
1457 case AF_UNIX:
1458 return real_socket(family, type, protocol);
1459 default:
1460 errno = EAFNOSUPPORT;
1461 return -1;
1464 switch (real_type) {
1465 case SOCK_STREAM:
1466 break;
1467 case SOCK_DGRAM:
1468 break;
1469 default:
1470 errno = EPROTONOSUPPORT;
1471 return -1;
1474 switch (protocol) {
1475 case 0:
1476 break;
1477 case 6:
1478 if (real_type == SOCK_STREAM) {
1479 break;
1481 /*fall through*/
1482 case 17:
1483 if (real_type == SOCK_DGRAM) {
1484 break;
1486 /*fall through*/
1487 default:
1488 errno = EPROTONOSUPPORT;
1489 return -1;
1492 /* We must call real_socket with type, from the caller, not the version we removed
1493 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1494 fd = real_socket(AF_UNIX, type, 0);
1496 if (fd == -1) return -1;
1498 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1499 if (si == NULL) {
1500 errno = ENOMEM;
1501 return -1;
1504 si->family = family;
1506 /* however, the rest of the socket_wrapper code expects just
1507 * the type, not the flags */
1508 si->type = real_type;
1509 si->protocol = protocol;
1511 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
1512 if (fi == NULL) {
1513 free(si);
1514 errno = ENOMEM;
1515 return -1;
1518 fi->fd = fd;
1520 SWRAP_DLIST_ADD(si->fds, fi);
1521 SWRAP_DLIST_ADD(sockets, si);
1523 return fd;
1526 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1528 struct socket_info *parent_si, *child_si;
1529 struct socket_info_fd *child_fi;
1530 int fd;
1531 struct sockaddr_un un_addr;
1532 socklen_t un_addrlen = sizeof(un_addr);
1533 struct sockaddr_un un_my_addr;
1534 socklen_t un_my_addrlen = sizeof(un_my_addr);
1535 struct sockaddr *my_addr;
1536 socklen_t my_addrlen, len;
1537 int ret;
1539 parent_si = find_socket_info(s);
1540 if (!parent_si) {
1541 return real_accept(s, addr, addrlen);
1545 * assume out sockaddr have the same size as the in parent
1546 * socket family
1548 my_addrlen = socket_length(parent_si->family);
1549 if (my_addrlen <= 0) {
1550 errno = EINVAL;
1551 return -1;
1554 my_addr = (struct sockaddr *)malloc(my_addrlen);
1555 if (my_addr == NULL) {
1556 return -1;
1559 memset(&un_addr, 0, sizeof(un_addr));
1560 memset(&un_my_addr, 0, sizeof(un_my_addr));
1562 ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
1563 if (ret == -1) {
1564 free(my_addr);
1565 return ret;
1568 fd = ret;
1570 len = my_addrlen;
1571 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1572 parent_si->family, my_addr, &len);
1573 if (ret == -1) {
1574 free(my_addr);
1575 close(fd);
1576 return ret;
1579 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1580 memset(child_si, 0, sizeof(*child_si));
1582 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
1583 if (child_fi == NULL) {
1584 free(child_si);
1585 free(my_addr);
1586 close(fd);
1587 errno = ENOMEM;
1588 return -1;
1591 child_fi->fd = fd;
1593 SWRAP_DLIST_ADD(child_si->fds, child_fi);
1595 child_si->family = parent_si->family;
1596 child_si->type = parent_si->type;
1597 child_si->protocol = parent_si->protocol;
1598 child_si->bound = 1;
1599 child_si->is_server = 1;
1600 child_si->connected = 1;
1602 child_si->peername_len = len;
1603 child_si->peername = sockaddr_dup(my_addr, len);
1605 if (addr != NULL && addrlen != NULL) {
1606 size_t copy_len = MIN(*addrlen, len);
1607 if (copy_len > 0) {
1608 memcpy(addr, my_addr, copy_len);
1610 *addrlen = len;
1613 ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr,
1614 &un_my_addrlen);
1615 if (ret == -1) {
1616 free(child_fi);
1617 free(child_si);
1618 close(fd);
1619 return ret;
1622 len = my_addrlen;
1623 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1624 child_si->family, my_addr, &len);
1625 if (ret == -1) {
1626 free(child_fi);
1627 free(child_si);
1628 free(my_addr);
1629 close(fd);
1630 return ret;
1633 child_si->myname_len = len;
1634 child_si->myname = sockaddr_dup(my_addr, len);
1635 free(my_addr);
1637 SWRAP_DLIST_ADD(sockets, child_si);
1639 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1640 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1641 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1643 return fd;
1646 static int autobind_start_init;
1647 static int autobind_start;
1649 /* using sendto() or connect() on an unbound socket would give the
1650 recipient no way to reply, as unlike UDP and TCP, a unix domain
1651 socket can't auto-assign emphemeral port numbers, so we need to
1652 assign it here.
1653 Note: this might change the family from ipv6 to ipv4
1655 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
1657 struct sockaddr_un un_addr;
1658 int i;
1659 char type;
1660 int ret;
1661 int port;
1662 struct stat st;
1664 if (autobind_start_init != 1) {
1665 autobind_start_init = 1;
1666 autobind_start = getpid();
1667 autobind_start %= 50000;
1668 autobind_start += 10000;
1671 un_addr.sun_family = AF_UNIX;
1673 switch (family) {
1674 case AF_INET: {
1675 struct sockaddr_in in;
1677 switch (si->type) {
1678 case SOCK_STREAM:
1679 type = SOCKET_TYPE_CHAR_TCP;
1680 break;
1681 case SOCK_DGRAM:
1682 type = SOCKET_TYPE_CHAR_UDP;
1683 break;
1684 default:
1685 errno = ESOCKTNOSUPPORT;
1686 return -1;
1689 memset(&in, 0, sizeof(in));
1690 in.sin_family = AF_INET;
1691 in.sin_addr.s_addr = htonl(127<<24 |
1692 socket_wrapper_default_iface());
1694 si->myname_len = sizeof(in);
1695 si->myname = sockaddr_dup(&in, si->myname_len);
1696 break;
1698 #ifdef HAVE_IPV6
1699 case AF_INET6: {
1700 struct sockaddr_in6 in6;
1702 if (si->family != family) {
1703 errno = ENETUNREACH;
1704 return -1;
1707 switch (si->type) {
1708 case SOCK_STREAM:
1709 type = SOCKET_TYPE_CHAR_TCP_V6;
1710 break;
1711 case SOCK_DGRAM:
1712 type = SOCKET_TYPE_CHAR_UDP_V6;
1713 break;
1714 default:
1715 errno = ESOCKTNOSUPPORT;
1716 return -1;
1719 memset(&in6, 0, sizeof(in6));
1720 in6.sin6_family = AF_INET6;
1721 in6.sin6_addr = *swrap_ipv6();
1722 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1723 si->myname_len = sizeof(in6);
1724 si->myname = sockaddr_dup(&in6, si->myname_len);
1725 break;
1727 #endif
1728 default:
1729 errno = ESOCKTNOSUPPORT;
1730 return -1;
1733 if (autobind_start > 60000) {
1734 autobind_start = 10000;
1737 for (i=0;i<1000;i++) {
1738 port = autobind_start + i;
1739 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1740 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1741 type, socket_wrapper_default_iface(), port);
1742 if (stat(un_addr.sun_path, &st) == 0) continue;
1744 ret = real_bind(fd, (struct sockaddr *)(void *)&un_addr,
1745 sizeof(un_addr));
1746 if (ret == -1) return ret;
1748 si->tmp_path = strdup(un_addr.sun_path);
1749 si->bound = 1;
1750 autobind_start = port + 1;
1751 break;
1753 if (i == 1000) {
1754 errno = ENFILE;
1755 return -1;
1758 si->family = family;
1759 set_port(si->family, port, si->myname);
1761 return 0;
1765 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1767 int ret;
1768 struct sockaddr_un un_addr;
1769 struct socket_info *si = find_socket_info(s);
1770 int bcast = 0;
1772 if (!si) {
1773 return real_connect(s, serv_addr, addrlen);
1776 if (si->bound == 0) {
1777 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
1778 if (ret == -1) return -1;
1781 if (si->family != serv_addr->sa_family) {
1782 errno = EINVAL;
1783 return -1;
1786 ret = sockaddr_convert_to_un(si, serv_addr,
1787 addrlen, &un_addr, 0, &bcast);
1788 if (ret == -1) return -1;
1790 if (bcast) {
1791 errno = ENETUNREACH;
1792 return -1;
1795 if (si->type == SOCK_DGRAM) {
1796 si->defer_connect = 1;
1797 ret = 0;
1798 } else {
1799 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1801 ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
1802 sizeof(struct sockaddr_un));
1805 /* to give better errors */
1806 if (ret == -1 && errno == ENOENT) {
1807 errno = EHOSTUNREACH;
1810 if (ret == 0) {
1811 si->peername_len = addrlen;
1812 si->peername = sockaddr_dup(serv_addr, addrlen);
1813 si->connected = 1;
1815 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1816 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1817 } else {
1818 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1821 return ret;
1824 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1826 int ret;
1827 struct sockaddr_un un_addr;
1828 struct socket_info *si = find_socket_info(s);
1830 if (!si) {
1831 return real_bind(s, myaddr, addrlen);
1834 si->myname_len = addrlen;
1835 si->myname = sockaddr_dup(myaddr, addrlen);
1837 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
1838 if (ret == -1) return -1;
1840 unlink(un_addr.sun_path);
1842 ret = real_bind(s, (struct sockaddr *)(void *)&un_addr,
1843 sizeof(struct sockaddr_un));
1845 if (ret == 0) {
1846 si->bound = 1;
1849 return ret;
1852 _PUBLIC_ int swrap_listen(int s, int backlog)
1854 int ret;
1855 struct socket_info *si = find_socket_info(s);
1857 if (!si) {
1858 return real_listen(s, backlog);
1861 ret = real_listen(s, backlog);
1863 return ret;
1866 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1868 struct socket_info *si = find_socket_info(s);
1870 if (!si) {
1871 return real_getpeername(s, name, addrlen);
1874 if (!si->peername)
1876 errno = ENOTCONN;
1877 return -1;
1880 memcpy(name, si->peername, si->peername_len);
1881 *addrlen = si->peername_len;
1883 return 0;
1886 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1888 struct socket_info *si = find_socket_info(s);
1890 if (!si) {
1891 return real_getsockname(s, name, addrlen);
1894 memcpy(name, si->myname, si->myname_len);
1895 *addrlen = si->myname_len;
1897 return 0;
1900 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1902 struct socket_info *si = find_socket_info(s);
1904 if (!si) {
1905 return real_getsockopt(s, level, optname, optval, optlen);
1908 if (level == SOL_SOCKET) {
1909 return real_getsockopt(s, level, optname, optval, optlen);
1912 errno = ENOPROTOOPT;
1913 return -1;
1916 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1918 struct socket_info *si = find_socket_info(s);
1920 if (!si) {
1921 return real_setsockopt(s, level, optname, optval, optlen);
1924 if (level == SOL_SOCKET) {
1925 return real_setsockopt(s, level, optname, optval, optlen);
1928 switch (si->family) {
1929 case AF_INET:
1930 return 0;
1931 #ifdef HAVE_IPV6
1932 case AF_INET6:
1933 return 0;
1934 #endif
1935 default:
1936 errno = ENOPROTOOPT;
1937 return -1;
1941 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1943 int ret;
1944 struct socket_info *si = find_socket_info(s);
1945 int value;
1947 if (!si) {
1948 return real_ioctl(s, r, p);
1951 ret = real_ioctl(s, r, p);
1953 switch (r) {
1954 case FIONREAD:
1955 value = *((int *)p);
1956 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1957 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1958 } else if (value == 0) { /* END OF FILE */
1959 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1961 break;
1964 return ret;
1967 static ssize_t swrap_sendmsg_before(int fd,
1968 struct socket_info *si,
1969 struct msghdr *msg,
1970 struct iovec *tmp_iov,
1971 struct sockaddr_un *tmp_un,
1972 const struct sockaddr_un **to_un,
1973 const struct sockaddr **to,
1974 int *bcast)
1976 size_t i, len = 0;
1977 ssize_t ret;
1979 if (to_un) {
1980 *to_un = NULL;
1982 if (to) {
1983 *to = NULL;
1985 if (bcast) {
1986 *bcast = 0;
1989 switch (si->type) {
1990 case SOCK_STREAM:
1991 if (!si->connected) {
1992 errno = ENOTCONN;
1993 return -1;
1996 if (msg->msg_iovlen == 0) {
1997 break;
2001 * cut down to 1500 byte packets for stream sockets,
2002 * which makes it easier to format PCAP capture files
2003 * (as the caller will simply continue from here)
2006 for (i=0; i < msg->msg_iovlen; i++) {
2007 size_t nlen;
2008 nlen = len + msg->msg_iov[i].iov_len;
2009 if (nlen > 1500) {
2010 break;
2013 msg->msg_iovlen = i;
2014 if (msg->msg_iovlen == 0) {
2015 *tmp_iov = msg->msg_iov[0];
2016 tmp_iov->iov_len = MIN(tmp_iov->iov_len, 1500);
2017 msg->msg_iov = tmp_iov;
2018 msg->msg_iovlen = 1;
2020 break;
2022 case SOCK_DGRAM:
2023 if (si->connected) {
2024 if (msg->msg_name) {
2025 errno = EISCONN;
2026 return -1;
2028 } else {
2029 const struct sockaddr *msg_name;
2030 msg_name = (const struct sockaddr *)msg->msg_name;
2032 if (msg_name == NULL) {
2033 errno = ENOTCONN;
2034 return -1;
2038 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
2039 tmp_un, 0, bcast);
2040 if (ret == -1) return -1;
2042 if (to_un) {
2043 *to_un = tmp_un;
2045 if (to) {
2046 *to = msg_name;
2048 msg->msg_name = tmp_un;
2049 msg->msg_namelen = sizeof(*tmp_un);
2052 if (si->bound == 0) {
2053 ret = swrap_auto_bind(fd, si, si->family);
2054 if (ret == -1) return -1;
2057 if (!si->defer_connect) {
2058 break;
2061 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2062 tmp_un, 0, NULL);
2063 if (ret == -1) return -1;
2065 ret = real_connect(fd, (struct sockaddr *)(void *)tmp_un,
2066 sizeof(*tmp_un));
2068 /* to give better errors */
2069 if (ret == -1 && errno == ENOENT) {
2070 errno = EHOSTUNREACH;
2073 if (ret == -1) {
2074 return ret;
2077 si->defer_connect = 0;
2078 break;
2079 default:
2080 errno = EHOSTUNREACH;
2081 return -1;
2084 return 0;
2087 static void swrap_sendmsg_after(struct socket_info *si,
2088 struct msghdr *msg,
2089 const struct sockaddr *to,
2090 ssize_t ret)
2092 int saved_errno = errno;
2093 size_t i, len = 0;
2094 uint8_t *buf;
2095 off_t ofs = 0;
2096 size_t avail = 0;
2097 size_t remain;
2099 /* to give better errors */
2100 if (ret == -1 && saved_errno == ENOENT) {
2101 saved_errno = EHOSTUNREACH;
2104 for (i=0; i < msg->msg_iovlen; i++) {
2105 avail += msg->msg_iov[i].iov_len;
2108 if (ret == -1) {
2109 remain = MIN(80, avail);
2110 } else {
2111 remain = ret;
2114 /* we capture it as one single packet */
2115 buf = (uint8_t *)malloc(remain);
2116 if (!buf) {
2117 /* we just not capture the packet */
2118 errno = saved_errno;
2119 return;
2122 for (i=0; i < msg->msg_iovlen; i++) {
2123 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2124 memcpy(buf + ofs,
2125 msg->msg_iov[i].iov_base,
2126 this_time);
2127 ofs += this_time;
2128 remain -= this_time;
2130 len = ofs;
2132 switch (si->type) {
2133 case SOCK_STREAM:
2134 if (ret == -1) {
2135 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2136 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2137 } else {
2138 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2140 break;
2142 case SOCK_DGRAM:
2143 if (si->connected) {
2144 to = si->peername;
2146 if (ret == -1) {
2147 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2148 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
2149 } else {
2150 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2152 break;
2155 free(buf);
2156 errno = saved_errno;
2159 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
2161 struct sockaddr_un un_addr;
2162 socklen_t un_addrlen = sizeof(un_addr);
2163 int ret;
2164 struct socket_info *si = find_socket_info(s);
2165 struct sockaddr_storage ss;
2166 socklen_t ss_len = sizeof(ss);
2168 if (!si) {
2169 return real_recvfrom(s, buf, len, flags, from, fromlen);
2172 if (!from) {
2173 from = (struct sockaddr *)(void *)&ss;
2174 fromlen = &ss_len;
2177 if (si->type == SOCK_STREAM) {
2178 /* cut down to 1500 byte packets for stream sockets,
2179 * which makes it easier to format PCAP capture files
2180 * (as the caller will simply continue from here) */
2181 len = MIN(len, 1500);
2184 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2185 memset(&un_addr, 0, sizeof(un_addr));
2186 ret = real_recvfrom(s, buf, len, flags,
2187 (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2188 if (ret == -1)
2189 return ret;
2191 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
2192 si->family, from, fromlen) == -1) {
2193 return -1;
2196 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
2198 return ret;
2202 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
2204 struct msghdr msg;
2205 struct iovec tmp;
2206 struct sockaddr_un un_addr;
2207 const struct sockaddr_un *to_un = NULL;
2208 ssize_t ret;
2209 struct socket_info *si = find_socket_info(s);
2210 int bcast = 0;
2212 if (!si) {
2213 return real_sendto(s, buf, len, flags, to, tolen);
2216 tmp.iov_base = discard_const_p(char, buf);
2217 tmp.iov_len = len;
2219 ZERO_STRUCT(msg);
2220 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
2221 msg.msg_namelen = tolen; /* size of address */
2222 msg.msg_iov = &tmp; /* scatter/gather array */
2223 msg.msg_iovlen = 1; /* # elements in msg_iov */
2224 #if 0 /* not available on solaris */
2225 msg.msg_control = NULL; /* ancillary data, see below */
2226 msg.msg_controllen = 0; /* ancillary data buffer len */
2227 msg.msg_flags = 0; /* flags on received message */
2228 #endif
2230 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2231 if (ret == -1) return -1;
2233 buf = msg.msg_iov[0].iov_base;
2234 len = msg.msg_iov[0].iov_len;
2236 if (bcast) {
2237 struct stat st;
2238 unsigned int iface;
2239 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2240 char type;
2242 type = SOCKET_TYPE_CHAR_UDP;
2244 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2245 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2246 socket_wrapper_dir(), type, iface, prt);
2247 if (stat(un_addr.sun_path, &st) != 0) continue;
2249 /* ignore the any errors in broadcast sends */
2250 real_sendto(s, buf, len, flags,
2251 (struct sockaddr *)(void *)&un_addr,
2252 sizeof(un_addr));
2255 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2257 return len;
2260 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)msg.msg_name,
2261 msg.msg_namelen);
2263 swrap_sendmsg_after(si, &msg, to, ret);
2265 return ret;
2268 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
2270 int ret;
2271 struct socket_info *si = find_socket_info(s);
2273 if (!si) {
2274 return real_recv(s, buf, len, flags);
2277 if (si->type == SOCK_STREAM) {
2278 /* cut down to 1500 byte packets for stream sockets,
2279 * which makes it easier to format PCAP capture files
2280 * (as the caller will simply continue from here) */
2281 len = MIN(len, 1500);
2284 ret = real_recv(s, buf, len, flags);
2285 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2286 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2287 } else if (ret == 0) { /* END OF FILE */
2288 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2289 } else if (ret > 0) {
2290 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2293 return ret;
2296 _PUBLIC_ ssize_t swrap_read(int s, void *buf, size_t len)
2298 int ret;
2299 struct socket_info *si = find_socket_info(s);
2301 if (!si) {
2302 return real_read(s, buf, len);
2305 if (si->type == SOCK_STREAM) {
2306 /* cut down to 1500 byte packets for stream sockets,
2307 * which makes it easier to format PCAP capture files
2308 * (as the caller will simply continue from here) */
2309 len = MIN(len, 1500);
2312 ret = real_read(s, buf, len);
2313 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2314 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2315 } else if (ret == 0) { /* END OF FILE */
2316 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2317 } else if (ret > 0) {
2318 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2321 return ret;
2325 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2327 struct msghdr msg;
2328 struct iovec tmp;
2329 struct sockaddr_un un_addr;
2330 ssize_t ret;
2331 struct socket_info *si = find_socket_info(s);
2333 if (!si) {
2334 return real_send(s, buf, len, flags);
2337 tmp.iov_base = discard_const_p(char, buf);
2338 tmp.iov_len = len;
2340 ZERO_STRUCT(msg);
2341 msg.msg_name = NULL; /* optional address */
2342 msg.msg_namelen = 0; /* size of address */
2343 msg.msg_iov = &tmp; /* scatter/gather array */
2344 msg.msg_iovlen = 1; /* # elements in msg_iov */
2345 #if 0 /* not available on solaris */
2346 msg.msg_control = NULL; /* ancillary data, see below */
2347 msg.msg_controllen = 0; /* ancillary data buffer len */
2348 msg.msg_flags = 0; /* flags on received message */
2349 #endif
2351 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2352 if (ret == -1) return -1;
2354 buf = msg.msg_iov[0].iov_base;
2355 len = msg.msg_iov[0].iov_len;
2357 ret = real_send(s, buf, len, flags);
2359 swrap_sendmsg_after(si, &msg, NULL, ret);
2361 return ret;
2364 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
2366 struct msghdr msg;
2367 struct iovec tmp;
2368 struct sockaddr_un un_addr;
2369 const struct sockaddr_un *to_un = NULL;
2370 const struct sockaddr *to = NULL;
2371 ssize_t ret;
2372 struct socket_info *si = find_socket_info(s);
2373 int bcast = 0;
2375 if (!si) {
2376 return real_sendmsg(s, omsg, flags);
2379 tmp.iov_base = NULL;
2380 tmp.iov_len = 0;
2382 msg = *omsg;
2383 #if 0
2384 msg.msg_name = omsg->msg_name; /* optional address */
2385 msg.msg_namelen = omsg->msg_namelen; /* size of address */
2386 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
2387 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
2388 /* the following is not available on solaris */
2389 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
2390 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
2391 msg.msg_flags = omsg->msg_flags; /* flags on received message */
2392 #endif
2394 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2395 if (ret == -1) return -1;
2397 if (bcast) {
2398 struct stat st;
2399 unsigned int iface;
2400 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2401 char type;
2402 size_t i, len = 0;
2403 uint8_t *buf;
2404 off_t ofs = 0;
2405 size_t avail = 0;
2406 size_t remain;
2408 for (i=0; i < msg.msg_iovlen; i++) {
2409 avail += msg.msg_iov[i].iov_len;
2412 len = avail;
2413 remain = avail;
2415 /* we capture it as one single packet */
2416 buf = (uint8_t *)malloc(remain);
2417 if (!buf) {
2418 return -1;
2421 for (i=0; i < msg.msg_iovlen; i++) {
2422 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
2423 memcpy(buf + ofs,
2424 msg.msg_iov[i].iov_base,
2425 this_time);
2426 ofs += this_time;
2427 remain -= this_time;
2430 type = SOCKET_TYPE_CHAR_UDP;
2432 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2433 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2434 socket_wrapper_dir(), type, iface, prt);
2435 if (stat(un_addr.sun_path, &st) != 0) continue;
2437 msg.msg_name = &un_addr; /* optional address */
2438 msg.msg_namelen = sizeof(un_addr); /* size of address */
2440 /* ignore the any errors in broadcast sends */
2441 real_sendmsg(s, &msg, flags);
2444 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2445 free(buf);
2447 return len;
2450 ret = real_sendmsg(s, &msg, flags);
2452 swrap_sendmsg_after(si, &msg, to, ret);
2454 return ret;
2457 int swrap_readv(int s, const struct iovec *vector, size_t count)
2459 int ret;
2460 struct socket_info *si = find_socket_info(s);
2461 struct iovec v;
2463 if (!si) {
2464 return real_readv(s, vector, count);
2467 if (!si->connected) {
2468 errno = ENOTCONN;
2469 return -1;
2472 if (si->type == SOCK_STREAM && count > 0) {
2473 /* cut down to 1500 byte packets for stream sockets,
2474 * which makes it easier to format PCAP capture files
2475 * (as the caller will simply continue from here) */
2476 size_t i, len = 0;
2478 for (i=0; i < count; i++) {
2479 size_t nlen;
2480 nlen = len + vector[i].iov_len;
2481 if (nlen > 1500) {
2482 break;
2485 count = i;
2486 if (count == 0) {
2487 v = vector[0];
2488 v.iov_len = MIN(v.iov_len, 1500);
2489 vector = &v;
2490 count = 1;
2494 ret = real_readv(s, vector, count);
2495 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2496 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2497 } else if (ret == 0) { /* END OF FILE */
2498 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2499 } else if (ret > 0) {
2500 uint8_t *buf;
2501 off_t ofs = 0;
2502 size_t i;
2503 size_t remain = ret;
2505 /* we capture it as one single packet */
2506 buf = (uint8_t *)malloc(ret);
2507 if (!buf) {
2508 /* we just not capture the packet */
2509 errno = 0;
2510 return ret;
2513 for (i=0; i < count; i++) {
2514 size_t this_time = MIN(remain, vector[i].iov_len);
2515 memcpy(buf + ofs,
2516 vector[i].iov_base,
2517 this_time);
2518 ofs += this_time;
2519 remain -= this_time;
2522 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2523 free(buf);
2526 return ret;
2529 ssize_t swrap_writev(int s, const struct iovec *vector, size_t count)
2531 struct msghdr msg;
2532 struct iovec tmp;
2533 struct sockaddr_un un_addr;
2534 ssize_t ret;
2535 struct socket_info *si = find_socket_info(s);
2537 if (!si) {
2538 return real_writev(s, vector, count);
2541 tmp.iov_base = NULL;
2542 tmp.iov_len = 0;
2544 ZERO_STRUCT(msg);
2545 msg.msg_name = NULL; /* optional address */
2546 msg.msg_namelen = 0; /* size of address */
2547 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
2548 msg.msg_iovlen = count; /* # elements in msg_iov */
2549 #if 0 /* not available on solaris */
2550 msg.msg_control = NULL; /* ancillary data, see below */
2551 msg.msg_controllen = 0; /* ancillary data buffer len */
2552 msg.msg_flags = 0; /* flags on received message */
2553 #endif
2555 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2556 if (ret == -1) return -1;
2558 ret = real_writev(s, msg.msg_iov, msg.msg_iovlen);
2560 swrap_sendmsg_after(si, &msg, NULL, ret);
2562 return ret;
2565 _PUBLIC_ int swrap_close(int fd)
2567 struct socket_info *si = find_socket_info(fd);
2568 struct socket_info_fd *fi;
2569 int ret;
2571 if (!si) {
2572 return real_close(fd);
2575 for (fi = si->fds; fi; fi = fi->next) {
2576 if (fi->fd == fd) {
2577 SWRAP_DLIST_REMOVE(si->fds, fi);
2578 free(fi);
2579 break;
2583 if (si->fds) {
2584 /* there are still references left */
2585 return real_close(fd);
2588 SWRAP_DLIST_REMOVE(sockets, si);
2590 if (si->myname && si->peername) {
2591 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2594 ret = real_close(fd);
2596 if (si->myname && si->peername) {
2597 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2598 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2601 if (si->myname) free(si->myname);
2602 if (si->peername) free(si->peername);
2603 if (si->tmp_path) {
2604 unlink(si->tmp_path);
2605 free(si->tmp_path);
2607 free(si);
2609 return ret;
2612 _PUBLIC_ int swrap_dup(int fd)
2614 struct socket_info *si;
2615 struct socket_info_fd *fi;
2617 si = find_socket_info(fd);
2619 if (!si) {
2620 return real_dup(fd);
2623 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2624 if (fi == NULL) {
2625 errno = ENOMEM;
2626 return -1;
2629 fi->fd = real_dup(fd);
2630 if (fi->fd == -1) {
2631 int saved_errno = errno;
2632 free(fi);
2633 errno = saved_errno;
2634 return -1;
2637 SWRAP_DLIST_ADD(si->fds, fi);
2638 return fi->fd;
2641 _PUBLIC_ int swrap_dup2(int fd, int newfd)
2643 struct socket_info *si;
2644 struct socket_info_fd *fi;
2646 si = find_socket_info(fd);
2648 if (!si) {
2649 return real_dup2(fd, newfd);
2652 if (find_socket_info(newfd)) {
2653 /* dup2() does an implicit close of newfd, which we
2654 * need to emulate */
2655 swrap_close(newfd);
2658 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2659 if (fi == NULL) {
2660 errno = ENOMEM;
2661 return -1;
2664 fi->fd = real_dup2(fd, newfd);
2665 if (fi->fd == -1) {
2666 int saved_errno = errno;
2667 free(fi);
2668 errno = saved_errno;
2669 return -1;
2672 SWRAP_DLIST_ADD(si->fds, fi);
2673 return fi->fd;