2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
44 #define SOCKET_WRAPPER_NOT_REPLACE
46 #include "system/network.h"
47 #include "system/filesys.h"
48 #include "system/time.h"
50 #else /* _SAMBA_BUILD_ */
52 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/ioctl.h>
57 #include <sys/filio.h>
60 #include <netinet/in.h>
61 #include <netinet/tcp.h>
75 #define SWRAP_DLIST_ADD(list,item) do { \
77 (item)->prev = NULL; \
78 (item)->next = NULL; \
81 (item)->prev = NULL; \
82 (item)->next = (list); \
83 (list)->prev = (item); \
88 #define SWRAP_DLIST_REMOVE(list,item) do { \
89 if ((list) == (item)) { \
90 (list) = (item)->next; \
92 (list)->prev = NULL; \
96 (item)->prev->next = (item)->next; \
99 (item)->next->prev = (item)->prev; \
102 (item)->prev = NULL; \
103 (item)->next = NULL; \
106 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
108 #define REWRITE_CALLS
111 #define real_accept accept
112 #define real_connect connect
113 #define real_bind bind
114 #define real_listen listen
115 #define real_getpeername getpeername
116 #define real_getsockname getsockname
117 #define real_getsockopt getsockopt
118 #define real_setsockopt setsockopt
119 #define real_recvfrom recvfrom
120 #define real_sendto sendto
121 #define real_sendmsg sendmsg
122 #define real_ioctl ioctl
123 #define real_recv recv
124 #define real_read read
125 #define real_send send
126 #define real_readv readv
127 #define real_writev writev
128 #define real_socket socket
129 #define real_close close
131 #define real_dup2 dup2
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
140 /* we need to use a very terse format here as IRIX 6.4 silently
141 truncates names to 16 chars, so if we use a longer name then we
142 can't tell which port a packet came from with recvfrom()
144 with this format we have 8 chars left for the directory name
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
149 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
150 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
152 /* This limit is to avoid broadcast sendto() needing to stat too many
153 * files. It may be raised (with a performance cost) to up to 254
154 * without changing the format above */
155 #define MAX_WRAPPED_INTERFACES 32
161 static const struct in6_addr *swrap_ipv6(void)
163 static struct in6_addr v;
164 static int initialized;
172 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
181 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
183 struct sockaddr *ret = (struct sockaddr *)malloc(len);
184 memcpy(ret, data, len);
188 static void set_port(int family, int prt, struct sockaddr *addr)
192 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
196 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
202 static size_t socket_length(int family)
206 return sizeof(struct sockaddr_in);
209 return sizeof(struct sockaddr_in6);
215 struct socket_info_fd {
216 struct socket_info_fd *prev, *next;
222 struct socket_info_fd *fds;
235 struct sockaddr *myname;
236 socklen_t myname_len;
238 struct sockaddr *peername;
239 socklen_t peername_len;
242 unsigned long pck_snd;
243 unsigned long pck_rcv;
246 struct socket_info *prev, *next;
249 static struct socket_info *sockets;
251 const char *socket_wrapper_dir(void)
253 const char *s = getenv("SOCKET_WRAPPER_DIR");
257 if (strncmp(s, "./", 2) == 0) {
263 unsigned int socket_wrapper_default_iface(void)
265 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
268 if (sscanf(s, "%u", &iface) == 1) {
269 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
275 return 1;/* 127.0.0.1 */
278 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
285 p = strrchr(un->sun_path, '/');
286 if (p) p++; else p = un->sun_path;
288 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
293 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
304 case SOCKET_TYPE_CHAR_TCP:
305 case SOCKET_TYPE_CHAR_UDP: {
306 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
308 if ((*len) < sizeof(*in2)) {
313 memset(in2, 0, sizeof(*in2));
314 in2->sin_family = AF_INET;
315 in2->sin_addr.s_addr = htonl((127<<24) | iface);
316 in2->sin_port = htons(prt);
322 case SOCKET_TYPE_CHAR_TCP_V6:
323 case SOCKET_TYPE_CHAR_UDP_V6: {
324 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
326 if ((*len) < sizeof(*in2)) {
331 memset(in2, 0, sizeof(*in2));
332 in2->sin6_family = AF_INET6;
333 in2->sin6_addr = *swrap_ipv6();
334 in2->sin6_addr.s6_addr[15] = iface;
335 in2->sin6_port = htons(prt);
349 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
357 if (bcast) *bcast = 0;
359 switch (inaddr->sa_family) {
361 const struct sockaddr_in *in =
362 (const struct sockaddr_in *)(const void *)inaddr;
363 unsigned int addr = ntohl(in->sin_addr.s_addr);
370 u_type = SOCKET_TYPE_CHAR_TCP;
373 u_type = SOCKET_TYPE_CHAR_UDP;
374 a_type = SOCKET_TYPE_CHAR_UDP;
375 b_type = SOCKET_TYPE_CHAR_UDP;
379 prt = ntohs(in->sin_port);
380 if (a_type && addr == 0xFFFFFFFF) {
381 /* 255.255.255.255 only udp */
384 iface = socket_wrapper_default_iface();
385 } else if (b_type && addr == 0x7FFFFFFF) {
386 /* 127.255.255.255 only udp */
389 iface = socket_wrapper_default_iface();
390 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
394 iface = (addr & 0x000000FF);
399 if (bcast) *bcast = is_bcast;
404 const struct sockaddr_in6 *in =
405 (const struct sockaddr_in6 *)(const void *)inaddr;
406 struct in6_addr cmp1, cmp2;
410 type = SOCKET_TYPE_CHAR_TCP_V6;
413 type = SOCKET_TYPE_CHAR_UDP_V6;
417 /* XXX no multicast/broadcast */
419 prt = ntohs(in->sin6_port);
421 cmp1 = *swrap_ipv6();
422 cmp2 = in->sin6_addr;
423 cmp2.s6_addr[15] = 0;
424 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
425 iface = in->sin6_addr.s6_addr[15];
445 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
446 socket_wrapper_dir());
447 /* the caller need to do more processing */
451 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
452 socket_wrapper_dir(), type, iface, prt);
457 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
466 if (bcast) *bcast = 0;
468 switch (si->family) {
470 const struct sockaddr_in *in =
471 (const struct sockaddr_in *)(const void *)inaddr;
472 unsigned int addr = ntohl(in->sin_addr.s_addr);
478 prt = ntohs(in->sin_port);
482 u_type = SOCKET_TYPE_CHAR_TCP;
483 d_type = SOCKET_TYPE_CHAR_TCP;
486 u_type = SOCKET_TYPE_CHAR_UDP;
487 d_type = SOCKET_TYPE_CHAR_UDP;
488 a_type = SOCKET_TYPE_CHAR_UDP;
489 b_type = SOCKET_TYPE_CHAR_UDP;
497 iface = socket_wrapper_default_iface();
498 } else if (a_type && addr == 0xFFFFFFFF) {
499 /* 255.255.255.255 only udp */
502 iface = socket_wrapper_default_iface();
503 } else if (b_type && addr == 0x7FFFFFFF) {
504 /* 127.255.255.255 only udp */
507 iface = socket_wrapper_default_iface();
508 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
512 iface = (addr & 0x000000FF);
514 errno = EADDRNOTAVAIL;
521 const struct sockaddr_in6 *in =
522 (const struct sockaddr_in6 *)(const void *)inaddr;
523 struct in6_addr cmp1, cmp2;
527 type = SOCKET_TYPE_CHAR_TCP_V6;
530 type = SOCKET_TYPE_CHAR_UDP_V6;
534 /* XXX no multicast/broadcast */
536 prt = ntohs(in->sin6_port);
538 cmp1 = *swrap_ipv6();
539 cmp2 = in->sin6_addr;
540 cmp2.s6_addr[15] = 0;
541 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
542 iface = socket_wrapper_default_iface();
543 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
544 iface = in->sin6_addr.s6_addr[15];
546 errno = EADDRNOTAVAIL;
554 errno = EADDRNOTAVAIL;
559 if (bcast) *bcast = is_bcast;
561 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
567 /* handle auto-allocation of ephemeral ports */
568 for (prt = 5001; prt < 10000; prt++) {
569 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
570 socket_wrapper_dir(), type, iface, prt);
571 if (stat(un->sun_path, &st) == 0) continue;
573 set_port(si->family, prt, si->myname);
582 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
583 socket_wrapper_dir(), type, iface, prt);
587 static struct socket_info *find_socket_info(int fd)
589 struct socket_info *i;
590 for (i = sockets; i; i = i->next) {
591 struct socket_info_fd *f;
592 for (f = i->fds; f; f = f->next) {
602 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
603 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
605 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
609 out->sa_family = AF_UNIX;
610 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
611 out->sa_len = sizeof(*out_addr);
614 switch (in_addr->sa_family) {
624 errno = ESOCKTNOSUPPORT;
628 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
630 return convert_in_un_remote(si, in_addr, out_addr, bcast);
636 errno = EAFNOSUPPORT;
640 static int sockaddr_convert_from_un(const struct socket_info *si,
641 const struct sockaddr_un *in_addr,
642 socklen_t un_addrlen,
644 struct sockaddr *out_addr,
645 socklen_t *out_addrlen)
649 if (out_addr == NULL || out_addrlen == NULL)
652 if (un_addrlen == 0) {
667 errno = ESOCKTNOSUPPORT;
670 ret = convert_un_in(in_addr, out_addr, out_addrlen);
671 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
672 out_addr->sa_len = *out_addrlen;
679 errno = EAFNOSUPPORT;
683 enum swrap_packet_type {
685 SWRAP_CONNECT_UNREACH,
693 SWRAP_SENDTO_UNREACH,
704 struct swrap_file_hdr {
706 uint16_t version_major;
707 uint16_t version_minor;
710 uint32_t frame_max_len;
711 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
714 #define SWRAP_FILE_HDR_SIZE 24
716 struct swrap_packet_frame {
718 uint32_t micro_seconds;
719 uint32_t recorded_length;
720 uint32_t full_length;
722 #define SWRAP_PACKET_FRAME_SIZE 16
724 union swrap_packet_ip {
728 uint16_t packet_length;
729 uint16_t identification;
734 uint16_t hdr_checksum;
738 #define SWRAP_PACKET_IP_V4_SIZE 20
741 uint8_t flow_label_high;
742 uint16_t flow_label_low;
743 uint16_t payload_length;
746 uint8_t src_addr[16];
747 uint8_t dest_addr[16];
749 #define SWRAP_PACKET_IP_V6_SIZE 40
751 #define SWRAP_PACKET_IP_SIZE 40
753 union swrap_packet_payload {
755 uint16_t source_port;
765 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
767 uint16_t source_port;
772 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
779 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
786 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
788 #define SWRAP_PACKET_PAYLOAD_SIZE 20
790 #define SWRAP_PACKET_MIN_ALLOC \
791 (SWRAP_PACKET_FRAME_SIZE + \
792 SWRAP_PACKET_IP_SIZE + \
793 SWRAP_PACKET_PAYLOAD_SIZE)
795 static const char *socket_wrapper_pcap_file(void)
797 static int initialized = 0;
798 static const char *s = NULL;
799 static const struct swrap_file_hdr h;
800 static const struct swrap_packet_frame f;
801 static const union swrap_packet_ip i;
802 static const union swrap_packet_payload p;
804 if (initialized == 1) {
810 * TODO: don't use the structs use plain buffer offsets
811 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
813 * for now make sure we disable PCAP support
814 * if the struct has alignment!
816 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
819 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
822 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
825 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
828 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
831 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
834 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
837 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
840 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
843 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
847 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
851 if (strncmp(s, "./", 2) == 0) {
857 static uint8_t *swrap_packet_init(struct timeval *tval,
858 const struct sockaddr *src,
859 const struct sockaddr *dest,
861 const uint8_t *payload,
863 unsigned long tcp_seqno,
864 unsigned long tcp_ack,
865 unsigned char tcp_ctl,
871 struct swrap_packet_frame *frame;
872 union swrap_packet_ip *ip;
873 union swrap_packet_payload *pay;
876 size_t nonwire_len = sizeof(*frame);
877 size_t wire_hdr_len = 0;
879 size_t ip_hdr_len = 0;
880 size_t icmp_hdr_len = 0;
881 size_t icmp_truncate_len = 0;
882 uint8_t protocol = 0, icmp_protocol = 0;
883 const struct sockaddr_in *src_in = NULL;
884 const struct sockaddr_in *dest_in = NULL;
886 const struct sockaddr_in6 *src_in6 = NULL;
887 const struct sockaddr_in6 *dest_in6 = NULL;
892 switch (src->sa_family) {
894 src_in = (const struct sockaddr_in *)src;
895 dest_in = (const struct sockaddr_in *)dest;
896 src_port = src_in->sin_port;
897 dest_port = dest_in->sin_port;
898 ip_hdr_len = sizeof(ip->v4);
902 src_in6 = (const struct sockaddr_in6 *)src;
903 dest_in6 = (const struct sockaddr_in6 *)dest;
904 src_port = src_in6->sin6_port;
905 dest_port = dest_in6->sin6_port;
906 ip_hdr_len = sizeof(ip->v6);
913 switch (socket_type) {
915 protocol = 0x06; /* TCP */
916 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
917 wire_len = wire_hdr_len + payload_len;
921 protocol = 0x11; /* UDP */
922 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
923 wire_len = wire_hdr_len + payload_len;
931 icmp_protocol = protocol;
932 switch (src->sa_family) {
934 protocol = 0x01; /* ICMPv4 */
935 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
939 protocol = 0x3A; /* ICMPv6 */
940 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
944 if (wire_len > 64 ) {
945 icmp_truncate_len = wire_len - 64;
947 wire_hdr_len += icmp_hdr_len;
948 wire_len += icmp_hdr_len;
951 packet_len = nonwire_len + wire_len;
952 alloc_len = packet_len;
953 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
954 alloc_len = SWRAP_PACKET_MIN_ALLOC;
957 base = (uint8_t *)malloc(alloc_len);
958 if (!base) return NULL;
962 frame = (struct swrap_packet_frame *)buf;
963 frame->seconds = tval->tv_sec;
964 frame->micro_seconds = tval->tv_usec;
965 frame->recorded_length = wire_len - icmp_truncate_len;
966 frame->full_length = wire_len - icmp_truncate_len;
967 buf += SWRAP_PACKET_FRAME_SIZE;
969 ip = (union swrap_packet_ip *)buf;
970 switch (src->sa_family) {
972 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
974 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
975 ip->v4.identification = htons(0xFFFF);
976 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
977 ip->v4.fragment = htons(0x0000);
979 ip->v4.protocol = protocol;
980 ip->v4.hdr_checksum = htons(0x0000);
981 ip->v4.src_addr = src_in->sin_addr.s_addr;
982 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
983 buf += SWRAP_PACKET_IP_V4_SIZE;
987 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
988 ip->v6.flow_label_high = 0x00;
989 ip->v6.flow_label_low = 0x0000;
990 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
991 ip->v6.next_header = protocol;
992 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
993 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
994 buf += SWRAP_PACKET_IP_V6_SIZE;
1000 pay = (union swrap_packet_payload *)buf;
1001 switch (src->sa_family) {
1003 pay->icmp4.type = 0x03; /* destination unreachable */
1004 pay->icmp4.code = 0x01; /* host unreachable */
1005 pay->icmp4.checksum = htons(0x0000);
1006 pay->icmp4.unused = htonl(0x00000000);
1007 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1009 /* set the ip header in the ICMP payload */
1010 ip = (union swrap_packet_ip *)buf;
1011 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1013 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1014 ip->v4.identification = htons(0xFFFF);
1015 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1016 ip->v4.fragment = htons(0x0000);
1018 ip->v4.protocol = icmp_protocol;
1019 ip->v4.hdr_checksum = htons(0x0000);
1020 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1021 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1022 buf += SWRAP_PACKET_IP_V4_SIZE;
1024 src_port = dest_in->sin_port;
1025 dest_port = src_in->sin_port;
1029 pay->icmp6.type = 0x01; /* destination unreachable */
1030 pay->icmp6.code = 0x03; /* address unreachable */
1031 pay->icmp6.checksum = htons(0x0000);
1032 pay->icmp6.unused = htonl(0x00000000);
1033 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1035 /* set the ip header in the ICMP payload */
1036 ip = (union swrap_packet_ip *)buf;
1037 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1038 ip->v6.flow_label_high = 0x00;
1039 ip->v6.flow_label_low = 0x0000;
1040 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1041 ip->v6.next_header = protocol;
1042 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1043 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1044 buf += SWRAP_PACKET_IP_V6_SIZE;
1046 src_port = dest_in6->sin6_port;
1047 dest_port = src_in6->sin6_port;
1053 pay = (union swrap_packet_payload *)buf;
1055 switch (socket_type) {
1057 pay->tcp.source_port = src_port;
1058 pay->tcp.dest_port = dest_port;
1059 pay->tcp.seq_num = htonl(tcp_seqno);
1060 pay->tcp.ack_num = htonl(tcp_ack);
1061 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1062 pay->tcp.control = tcp_ctl;
1063 pay->tcp.window = htons(0x7FFF);
1064 pay->tcp.checksum = htons(0x0000);
1065 pay->tcp.urg = htons(0x0000);
1066 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1071 pay->udp.source_port = src_port;
1072 pay->udp.dest_port = dest_port;
1073 pay->udp.length = htons(8 + payload_len);
1074 pay->udp.checksum = htons(0x0000);
1075 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1080 if (payload && payload_len > 0) {
1081 memcpy(buf, payload, payload_len);
1084 *_packet_len = packet_len - icmp_truncate_len;
1088 static int swrap_get_pcap_fd(const char *fname)
1092 if (fd != -1) return fd;
1094 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1096 struct swrap_file_hdr file_hdr;
1097 file_hdr.magic = 0xA1B2C3D4;
1098 file_hdr.version_major = 0x0002;
1099 file_hdr.version_minor = 0x0004;
1100 file_hdr.timezone = 0x00000000;
1101 file_hdr.sigfigs = 0x00000000;
1102 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1103 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1105 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1112 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1117 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1118 const struct sockaddr *addr,
1119 enum swrap_packet_type type,
1120 const void *buf, size_t len,
1123 const struct sockaddr *src_addr;
1124 const struct sockaddr *dest_addr;
1125 unsigned long tcp_seqno = 0;
1126 unsigned long tcp_ack = 0;
1127 unsigned char tcp_ctl = 0;
1128 int unreachable = 0;
1132 switch (si->family) {
1144 case SWRAP_CONNECT_SEND:
1145 if (si->type != SOCK_STREAM) return NULL;
1147 src_addr = si->myname;
1150 tcp_seqno = si->io.pck_snd;
1151 tcp_ack = si->io.pck_rcv;
1152 tcp_ctl = 0x02; /* SYN */
1154 si->io.pck_snd += 1;
1158 case SWRAP_CONNECT_RECV:
1159 if (si->type != SOCK_STREAM) return NULL;
1161 dest_addr = si->myname;
1164 tcp_seqno = si->io.pck_rcv;
1165 tcp_ack = si->io.pck_snd;
1166 tcp_ctl = 0x12; /** SYN,ACK */
1168 si->io.pck_rcv += 1;
1172 case SWRAP_CONNECT_UNREACH:
1173 if (si->type != SOCK_STREAM) return NULL;
1175 dest_addr = si->myname;
1178 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1179 tcp_seqno = si->io.pck_snd - 1;
1180 tcp_ack = si->io.pck_rcv;
1181 tcp_ctl = 0x02; /* SYN */
1186 case SWRAP_CONNECT_ACK:
1187 if (si->type != SOCK_STREAM) return NULL;
1189 src_addr = si->myname;
1192 tcp_seqno = si->io.pck_snd;
1193 tcp_ack = si->io.pck_rcv;
1194 tcp_ctl = 0x10; /* ACK */
1198 case SWRAP_ACCEPT_SEND:
1199 if (si->type != SOCK_STREAM) return NULL;
1201 dest_addr = si->myname;
1204 tcp_seqno = si->io.pck_rcv;
1205 tcp_ack = si->io.pck_snd;
1206 tcp_ctl = 0x02; /* SYN */
1208 si->io.pck_rcv += 1;
1212 case SWRAP_ACCEPT_RECV:
1213 if (si->type != SOCK_STREAM) return NULL;
1215 src_addr = si->myname;
1218 tcp_seqno = si->io.pck_snd;
1219 tcp_ack = si->io.pck_rcv;
1220 tcp_ctl = 0x12; /* SYN,ACK */
1222 si->io.pck_snd += 1;
1226 case SWRAP_ACCEPT_ACK:
1227 if (si->type != SOCK_STREAM) return NULL;
1229 dest_addr = si->myname;
1232 tcp_seqno = si->io.pck_rcv;
1233 tcp_ack = si->io.pck_snd;
1234 tcp_ctl = 0x10; /* ACK */
1239 src_addr = si->myname;
1240 dest_addr = si->peername;
1242 tcp_seqno = si->io.pck_snd;
1243 tcp_ack = si->io.pck_rcv;
1244 tcp_ctl = 0x18; /* PSH,ACK */
1246 si->io.pck_snd += len;
1250 case SWRAP_SEND_RST:
1251 dest_addr = si->myname;
1252 src_addr = si->peername;
1254 if (si->type == SOCK_DGRAM) {
1255 return swrap_marshall_packet(si, si->peername,
1256 SWRAP_SENDTO_UNREACH,
1257 buf, len, packet_len);
1260 tcp_seqno = si->io.pck_rcv;
1261 tcp_ack = si->io.pck_snd;
1262 tcp_ctl = 0x14; /** RST,ACK */
1266 case SWRAP_PENDING_RST:
1267 dest_addr = si->myname;
1268 src_addr = si->peername;
1270 if (si->type == SOCK_DGRAM) {
1274 tcp_seqno = si->io.pck_rcv;
1275 tcp_ack = si->io.pck_snd;
1276 tcp_ctl = 0x14; /* RST,ACK */
1281 dest_addr = si->myname;
1282 src_addr = si->peername;
1284 tcp_seqno = si->io.pck_rcv;
1285 tcp_ack = si->io.pck_snd;
1286 tcp_ctl = 0x18; /* PSH,ACK */
1288 si->io.pck_rcv += len;
1292 case SWRAP_RECV_RST:
1293 dest_addr = si->myname;
1294 src_addr = si->peername;
1296 if (si->type == SOCK_DGRAM) {
1300 tcp_seqno = si->io.pck_rcv;
1301 tcp_ack = si->io.pck_snd;
1302 tcp_ctl = 0x14; /* RST,ACK */
1307 src_addr = si->myname;
1310 si->io.pck_snd += len;
1314 case SWRAP_SENDTO_UNREACH:
1315 dest_addr = si->myname;
1322 case SWRAP_RECVFROM:
1323 dest_addr = si->myname;
1326 si->io.pck_rcv += len;
1330 case SWRAP_CLOSE_SEND:
1331 if (si->type != SOCK_STREAM) return NULL;
1333 src_addr = si->myname;
1334 dest_addr = si->peername;
1336 tcp_seqno = si->io.pck_snd;
1337 tcp_ack = si->io.pck_rcv;
1338 tcp_ctl = 0x11; /* FIN, ACK */
1340 si->io.pck_snd += 1;
1344 case SWRAP_CLOSE_RECV:
1345 if (si->type != SOCK_STREAM) return NULL;
1347 dest_addr = si->myname;
1348 src_addr = si->peername;
1350 tcp_seqno = si->io.pck_rcv;
1351 tcp_ack = si->io.pck_snd;
1352 tcp_ctl = 0x11; /* FIN,ACK */
1354 si->io.pck_rcv += 1;
1358 case SWRAP_CLOSE_ACK:
1359 if (si->type != SOCK_STREAM) return NULL;
1361 src_addr = si->myname;
1362 dest_addr = si->peername;
1364 tcp_seqno = si->io.pck_snd;
1365 tcp_ack = si->io.pck_rcv;
1366 tcp_ctl = 0x10; /* ACK */
1373 swrapGetTimeOfDay(&tv);
1375 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1376 (const uint8_t *)buf, len,
1377 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1381 static void swrap_dump_packet(struct socket_info *si,
1382 const struct sockaddr *addr,
1383 enum swrap_packet_type type,
1384 const void *buf, size_t len)
1386 const char *file_name;
1388 size_t packet_len = 0;
1391 file_name = socket_wrapper_pcap_file();
1396 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1401 fd = swrap_get_pcap_fd(file_name);
1403 if (write(fd, packet, packet_len) != packet_len) {
1412 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1414 struct socket_info *si;
1415 struct socket_info_fd *fi;
1417 int real_type = type;
1419 real_type &= ~SOCK_CLOEXEC;
1421 #ifdef SOCK_NONBLOCK
1422 real_type &= ~SOCK_NONBLOCK;
1425 if (!socket_wrapper_dir()) {
1426 return real_socket(family, type, protocol);
1436 return real_socket(family, type, protocol);
1438 errno = EAFNOSUPPORT;
1442 switch (real_type) {
1448 errno = EPROTONOSUPPORT;
1456 if (real_type == SOCK_STREAM) {
1461 if (real_type == SOCK_DGRAM) {
1466 errno = EPROTONOSUPPORT;
1470 /* We must call real_socket with type, from the caller, not the version we removed
1471 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1472 fd = real_socket(AF_UNIX, type, 0);
1474 if (fd == -1) return -1;
1476 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1482 si->family = family;
1484 /* however, the rest of the socket_wrapper code expects just
1485 * the type, not the flags */
1486 si->type = real_type;
1487 si->protocol = protocol;
1489 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
1498 SWRAP_DLIST_ADD(si->fds, fi);
1499 SWRAP_DLIST_ADD(sockets, si);
1504 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1506 struct socket_info *parent_si, *child_si;
1507 struct socket_info_fd *child_fi;
1509 struct sockaddr_un un_addr;
1510 socklen_t un_addrlen = sizeof(un_addr);
1511 struct sockaddr_un un_my_addr;
1512 socklen_t un_my_addrlen = sizeof(un_my_addr);
1513 struct sockaddr *my_addr;
1514 socklen_t my_addrlen, len;
1517 parent_si = find_socket_info(s);
1519 return real_accept(s, addr, addrlen);
1523 * assume out sockaddr have the same size as the in parent
1526 my_addrlen = socket_length(parent_si->family);
1527 if (my_addrlen <= 0) {
1532 my_addr = (struct sockaddr *)malloc(my_addrlen);
1533 if (my_addr == NULL) {
1537 memset(&un_addr, 0, sizeof(un_addr));
1538 memset(&un_my_addr, 0, sizeof(un_my_addr));
1540 ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
1549 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1550 parent_si->family, my_addr, &len);
1557 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1558 memset(child_si, 0, sizeof(*child_si));
1560 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
1561 if (child_fi == NULL) {
1571 SWRAP_DLIST_ADD(child_si->fds, child_fi);
1573 child_si->family = parent_si->family;
1574 child_si->type = parent_si->type;
1575 child_si->protocol = parent_si->protocol;
1576 child_si->bound = 1;
1577 child_si->is_server = 1;
1578 child_si->connected = 1;
1580 child_si->peername_len = len;
1581 child_si->peername = sockaddr_dup(my_addr, len);
1583 if (addr != NULL && addrlen != NULL) {
1584 size_t copy_len = MIN(*addrlen, len);
1586 memcpy(addr, my_addr, copy_len);
1591 ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr,
1601 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1602 child_si->family, my_addr, &len);
1611 child_si->myname_len = len;
1612 child_si->myname = sockaddr_dup(my_addr, len);
1615 SWRAP_DLIST_ADD(sockets, child_si);
1617 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1618 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1619 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1624 static int autobind_start_init;
1625 static int autobind_start;
1627 /* using sendto() or connect() on an unbound socket would give the
1628 recipient no way to reply, as unlike UDP and TCP, a unix domain
1629 socket can't auto-assign emphemeral port numbers, so we need to
1631 Note: this might change the family from ipv6 to ipv4
1633 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
1635 struct sockaddr_un un_addr;
1642 if (autobind_start_init != 1) {
1643 autobind_start_init = 1;
1644 autobind_start = getpid();
1645 autobind_start %= 50000;
1646 autobind_start += 10000;
1649 un_addr.sun_family = AF_UNIX;
1653 struct sockaddr_in in;
1657 type = SOCKET_TYPE_CHAR_TCP;
1660 type = SOCKET_TYPE_CHAR_UDP;
1663 errno = ESOCKTNOSUPPORT;
1667 memset(&in, 0, sizeof(in));
1668 in.sin_family = AF_INET;
1669 in.sin_addr.s_addr = htonl(127<<24 |
1670 socket_wrapper_default_iface());
1672 si->myname_len = sizeof(in);
1673 si->myname = sockaddr_dup(&in, si->myname_len);
1678 struct sockaddr_in6 in6;
1680 if (si->family != family) {
1681 errno = ENETUNREACH;
1687 type = SOCKET_TYPE_CHAR_TCP_V6;
1690 type = SOCKET_TYPE_CHAR_UDP_V6;
1693 errno = ESOCKTNOSUPPORT;
1697 memset(&in6, 0, sizeof(in6));
1698 in6.sin6_family = AF_INET6;
1699 in6.sin6_addr = *swrap_ipv6();
1700 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1701 si->myname_len = sizeof(in6);
1702 si->myname = sockaddr_dup(&in6, si->myname_len);
1707 errno = ESOCKTNOSUPPORT;
1711 if (autobind_start > 60000) {
1712 autobind_start = 10000;
1715 for (i=0;i<1000;i++) {
1716 port = autobind_start + i;
1717 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1718 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1719 type, socket_wrapper_default_iface(), port);
1720 if (stat(un_addr.sun_path, &st) == 0) continue;
1722 ret = real_bind(fd, (struct sockaddr *)(void *)&un_addr,
1724 if (ret == -1) return ret;
1726 si->tmp_path = strdup(un_addr.sun_path);
1728 autobind_start = port + 1;
1736 si->family = family;
1737 set_port(si->family, port, si->myname);
1743 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1746 struct sockaddr_un un_addr;
1747 struct socket_info *si = find_socket_info(s);
1751 return real_connect(s, serv_addr, addrlen);
1754 if (si->bound == 0) {
1755 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
1756 if (ret == -1) return -1;
1759 if (si->family != serv_addr->sa_family) {
1764 ret = sockaddr_convert_to_un(si, serv_addr,
1765 addrlen, &un_addr, 0, &bcast);
1766 if (ret == -1) return -1;
1769 errno = ENETUNREACH;
1773 if (si->type == SOCK_DGRAM) {
1774 si->defer_connect = 1;
1777 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1779 ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
1780 sizeof(struct sockaddr_un));
1783 /* to give better errors */
1784 if (ret == -1 && errno == ENOENT) {
1785 errno = EHOSTUNREACH;
1789 si->peername_len = addrlen;
1790 si->peername = sockaddr_dup(serv_addr, addrlen);
1793 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1794 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1796 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1802 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1805 struct sockaddr_un un_addr;
1806 struct socket_info *si = find_socket_info(s);
1809 return real_bind(s, myaddr, addrlen);
1812 si->myname_len = addrlen;
1813 si->myname = sockaddr_dup(myaddr, addrlen);
1815 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
1816 if (ret == -1) return -1;
1818 unlink(un_addr.sun_path);
1820 ret = real_bind(s, (struct sockaddr *)(void *)&un_addr,
1821 sizeof(struct sockaddr_un));
1830 _PUBLIC_ int swrap_listen(int s, int backlog)
1833 struct socket_info *si = find_socket_info(s);
1836 return real_listen(s, backlog);
1839 ret = real_listen(s, backlog);
1844 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1846 struct socket_info *si = find_socket_info(s);
1849 return real_getpeername(s, name, addrlen);
1858 memcpy(name, si->peername, si->peername_len);
1859 *addrlen = si->peername_len;
1864 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1866 struct socket_info *si = find_socket_info(s);
1869 return real_getsockname(s, name, addrlen);
1872 memcpy(name, si->myname, si->myname_len);
1873 *addrlen = si->myname_len;
1878 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1880 struct socket_info *si = find_socket_info(s);
1883 return real_getsockopt(s, level, optname, optval, optlen);
1886 if (level == SOL_SOCKET) {
1887 return real_getsockopt(s, level, optname, optval, optlen);
1890 errno = ENOPROTOOPT;
1894 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1896 struct socket_info *si = find_socket_info(s);
1899 return real_setsockopt(s, level, optname, optval, optlen);
1902 if (level == SOL_SOCKET) {
1903 return real_setsockopt(s, level, optname, optval, optlen);
1906 switch (si->family) {
1914 errno = ENOPROTOOPT;
1919 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1922 struct socket_info *si = find_socket_info(s);
1926 return real_ioctl(s, r, p);
1929 ret = real_ioctl(s, r, p);
1933 value = *((int *)p);
1934 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1935 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1936 } else if (value == 0) { /* END OF FILE */
1937 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1945 static ssize_t swrap_sendmsg_before(int fd,
1946 struct socket_info *si,
1948 struct iovec *tmp_iov,
1949 struct sockaddr_un *tmp_un,
1950 const struct sockaddr_un **to_un,
1951 const struct sockaddr **to,
1969 if (!si->connected) {
1974 if (msg->msg_iovlen == 0) {
1979 * cut down to 1500 byte packets for stream sockets,
1980 * which makes it easier to format PCAP capture files
1981 * (as the caller will simply continue from here)
1984 for (i=0; i < msg->msg_iovlen; i++) {
1986 nlen = len + msg->msg_iov[i].iov_len;
1991 msg->msg_iovlen = i;
1992 if (msg->msg_iovlen == 0) {
1993 *tmp_iov = msg->msg_iov[0];
1994 tmp_iov->iov_len = MIN(tmp_iov->iov_len, 1500);
1995 msg->msg_iov = tmp_iov;
1996 msg->msg_iovlen = 1;
2001 if (si->connected) {
2002 if (msg->msg_name) {
2007 const struct sockaddr *msg_name;
2008 msg_name = (const struct sockaddr *)msg->msg_name;
2010 if (msg_name == NULL) {
2016 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
2018 if (ret == -1) return -1;
2026 msg->msg_name = tmp_un;
2027 msg->msg_namelen = sizeof(*tmp_un);
2030 if (si->bound == 0) {
2031 ret = swrap_auto_bind(fd, si, si->family);
2032 if (ret == -1) return -1;
2035 if (!si->defer_connect) {
2039 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2041 if (ret == -1) return -1;
2043 ret = real_connect(fd, (struct sockaddr *)(void *)tmp_un,
2046 /* to give better errors */
2047 if (ret == -1 && errno == ENOENT) {
2048 errno = EHOSTUNREACH;
2055 si->defer_connect = 0;
2058 errno = EHOSTUNREACH;
2065 static void swrap_sendmsg_after(struct socket_info *si,
2067 const struct sockaddr *to,
2070 int saved_errno = errno;
2077 /* to give better errors */
2078 if (ret == -1 && saved_errno == ENOENT) {
2079 saved_errno = EHOSTUNREACH;
2082 for (i=0; i < msg->msg_iovlen; i++) {
2083 avail += msg->msg_iov[i].iov_len;
2087 remain = MIN(80, avail);
2092 /* we capture it as one single packet */
2093 buf = (uint8_t *)malloc(remain);
2095 /* we just not capture the packet */
2096 errno = saved_errno;
2100 for (i=0; i < msg->msg_iovlen; i++) {
2101 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2103 msg->msg_iov[i].iov_base,
2106 remain -= this_time;
2113 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2114 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2116 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2121 if (si->connected) {
2125 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2126 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
2128 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2134 errno = saved_errno;
2137 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
2139 struct sockaddr_un un_addr;
2140 socklen_t un_addrlen = sizeof(un_addr);
2142 struct socket_info *si = find_socket_info(s);
2143 struct sockaddr_storage ss;
2144 socklen_t ss_len = sizeof(ss);
2147 return real_recvfrom(s, buf, len, flags, from, fromlen);
2151 from = (struct sockaddr *)(void *)&ss;
2155 if (si->type == SOCK_STREAM) {
2156 /* cut down to 1500 byte packets for stream sockets,
2157 * which makes it easier to format PCAP capture files
2158 * (as the caller will simply continue from here) */
2159 len = MIN(len, 1500);
2162 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2163 memset(&un_addr, 0, sizeof(un_addr));
2164 ret = real_recvfrom(s, buf, len, flags,
2165 (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2169 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
2170 si->family, from, fromlen) == -1) {
2174 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
2180 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
2184 struct sockaddr_un un_addr;
2185 const struct sockaddr_un *to_un = NULL;
2187 struct socket_info *si = find_socket_info(s);
2191 return real_sendto(s, buf, len, flags, to, tolen);
2194 tmp.iov_base = discard_const_p(char, buf);
2198 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
2199 msg.msg_namelen = tolen; /* size of address */
2200 msg.msg_iov = &tmp; /* scatter/gather array */
2201 msg.msg_iovlen = 1; /* # elements in msg_iov */
2202 #if 0 /* not available on solaris */
2203 msg.msg_control = NULL; /* ancillary data, see below */
2204 msg.msg_controllen = 0; /* ancillary data buffer len */
2205 msg.msg_flags = 0; /* flags on received message */
2208 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2209 if (ret == -1) return -1;
2211 buf = msg.msg_iov[0].iov_base;
2212 len = msg.msg_iov[0].iov_len;
2217 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2220 type = SOCKET_TYPE_CHAR_UDP;
2222 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2223 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2224 socket_wrapper_dir(), type, iface, prt);
2225 if (stat(un_addr.sun_path, &st) != 0) continue;
2227 /* ignore the any errors in broadcast sends */
2228 real_sendto(s, buf, len, flags,
2229 (struct sockaddr *)(void *)&un_addr,
2233 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2238 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)msg.msg_name,
2241 swrap_sendmsg_after(si, &msg, to, ret);
2246 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
2249 struct socket_info *si = find_socket_info(s);
2252 return real_recv(s, buf, len, flags);
2255 if (si->type == SOCK_STREAM) {
2256 /* cut down to 1500 byte packets for stream sockets,
2257 * which makes it easier to format PCAP capture files
2258 * (as the caller will simply continue from here) */
2259 len = MIN(len, 1500);
2262 ret = real_recv(s, buf, len, flags);
2263 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2264 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2265 } else if (ret == 0) { /* END OF FILE */
2266 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2267 } else if (ret > 0) {
2268 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2274 _PUBLIC_ ssize_t swrap_read(int s, void *buf, size_t len)
2277 struct socket_info *si = find_socket_info(s);
2280 return real_read(s, buf, len);
2283 if (si->type == SOCK_STREAM) {
2284 /* cut down to 1500 byte packets for stream sockets,
2285 * which makes it easier to format PCAP capture files
2286 * (as the caller will simply continue from here) */
2287 len = MIN(len, 1500);
2290 ret = real_read(s, buf, len);
2291 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2292 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2293 } else if (ret == 0) { /* END OF FILE */
2294 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2295 } else if (ret > 0) {
2296 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2303 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2307 struct sockaddr_un un_addr;
2309 struct socket_info *si = find_socket_info(s);
2312 return real_send(s, buf, len, flags);
2315 tmp.iov_base = discard_const_p(char, buf);
2319 msg.msg_name = NULL; /* optional address */
2320 msg.msg_namelen = 0; /* size of address */
2321 msg.msg_iov = &tmp; /* scatter/gather array */
2322 msg.msg_iovlen = 1; /* # elements in msg_iov */
2323 #if 0 /* not available on solaris */
2324 msg.msg_control = NULL; /* ancillary data, see below */
2325 msg.msg_controllen = 0; /* ancillary data buffer len */
2326 msg.msg_flags = 0; /* flags on received message */
2329 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2330 if (ret == -1) return -1;
2332 buf = msg.msg_iov[0].iov_base;
2333 len = msg.msg_iov[0].iov_len;
2335 ret = real_send(s, buf, len, flags);
2337 swrap_sendmsg_after(si, &msg, NULL, ret);
2342 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
2346 struct sockaddr_un un_addr;
2347 const struct sockaddr_un *to_un = NULL;
2348 const struct sockaddr *to = NULL;
2350 struct socket_info *si = find_socket_info(s);
2354 return real_sendmsg(s, omsg, flags);
2357 tmp.iov_base = NULL;
2362 msg.msg_name = omsg->msg_name; /* optional address */
2363 msg.msg_namelen = omsg->msg_namelen; /* size of address */
2364 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
2365 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
2366 /* the following is not available on solaris */
2367 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
2368 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
2369 msg.msg_flags = omsg->msg_flags; /* flags on received message */
2372 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2373 if (ret == -1) return -1;
2378 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2386 for (i=0; i < msg.msg_iovlen; i++) {
2387 avail += msg.msg_iov[i].iov_len;
2393 /* we capture it as one single packet */
2394 buf = (uint8_t *)malloc(remain);
2399 for (i=0; i < msg.msg_iovlen; i++) {
2400 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
2402 msg.msg_iov[i].iov_base,
2405 remain -= this_time;
2408 type = SOCKET_TYPE_CHAR_UDP;
2410 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2411 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2412 socket_wrapper_dir(), type, iface, prt);
2413 if (stat(un_addr.sun_path, &st) != 0) continue;
2415 msg.msg_name = &un_addr; /* optional address */
2416 msg.msg_namelen = sizeof(un_addr); /* size of address */
2418 /* ignore the any errors in broadcast sends */
2419 real_sendmsg(s, &msg, flags);
2422 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2428 ret = real_sendmsg(s, &msg, flags);
2430 swrap_sendmsg_after(si, &msg, to, ret);
2435 int swrap_readv(int s, const struct iovec *vector, size_t count)
2438 struct socket_info *si = find_socket_info(s);
2442 return real_readv(s, vector, count);
2445 if (!si->connected) {
2450 if (si->type == SOCK_STREAM && count > 0) {
2451 /* cut down to 1500 byte packets for stream sockets,
2452 * which makes it easier to format PCAP capture files
2453 * (as the caller will simply continue from here) */
2456 for (i=0; i < count; i++) {
2458 nlen = len + vector[i].iov_len;
2466 v.iov_len = MIN(v.iov_len, 1500);
2472 ret = real_readv(s, vector, count);
2473 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2474 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2475 } else if (ret == 0) { /* END OF FILE */
2476 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2477 } else if (ret > 0) {
2481 size_t remain = ret;
2483 /* we capture it as one single packet */
2484 buf = (uint8_t *)malloc(ret);
2486 /* we just not capture the packet */
2491 for (i=0; i < count; i++) {
2492 size_t this_time = MIN(remain, vector[i].iov_len);
2497 remain -= this_time;
2500 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2507 int swrap_writev(int s, const struct iovec *vector, size_t count)
2511 struct sockaddr_un un_addr;
2513 struct socket_info *si = find_socket_info(s);
2516 return real_writev(s, vector, count);
2519 tmp.iov_base = NULL;
2523 msg.msg_name = NULL; /* optional address */
2524 msg.msg_namelen = 0; /* size of address */
2525 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
2526 msg.msg_iovlen = count; /* # elements in msg_iov */
2527 #if 0 /* not available on solaris */
2528 msg.msg_control = NULL; /* ancillary data, see below */
2529 msg.msg_controllen = 0; /* ancillary data buffer len */
2530 msg.msg_flags = 0; /* flags on received message */
2533 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2534 if (ret == -1) return -1;
2536 ret = real_writev(s, msg.msg_iov, msg.msg_iovlen);
2538 swrap_sendmsg_after(si, &msg, NULL, ret);
2543 _PUBLIC_ int swrap_close(int fd)
2545 struct socket_info *si = find_socket_info(fd);
2546 struct socket_info_fd *fi;
2550 return real_close(fd);
2553 for (fi = si->fds; fi; fi = fi->next) {
2555 SWRAP_DLIST_REMOVE(si->fds, fi);
2562 /* there are still references left */
2563 return real_close(fd);
2566 SWRAP_DLIST_REMOVE(sockets, si);
2568 if (si->myname && si->peername) {
2569 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2572 ret = real_close(fd);
2574 if (si->myname && si->peername) {
2575 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2576 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2579 if (si->myname) free(si->myname);
2580 if (si->peername) free(si->peername);
2582 unlink(si->tmp_path);
2590 _PUBLIC_ int swrap_dup(int fd)
2592 struct socket_info *si;
2593 struct socket_info_fd *fi;
2595 si = find_socket_info(fd);
2598 return real_dup(fd);
2601 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2607 fi->fd = real_dup(fd);
2609 int saved_errno = errno;
2611 errno = saved_errno;
2615 SWRAP_DLIST_ADD(si->fds, fi);
2619 _PUBLIC_ int swrap_dup2(int fd, int newfd)
2621 struct socket_info *si;
2622 struct socket_info_fd *fi;
2624 si = find_socket_info(fd);
2627 return real_dup2(fd, newfd);
2630 if (find_socket_info(newfd)) {
2631 /* dup2() does an implicit close of newfd, which we
2632 * need to emulate */
2636 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2642 fi->fd = real_dup2(fd, newfd);
2644 int saved_errno = errno;
2646 errno = saved_errno;
2650 SWRAP_DLIST_ADD(si->fds, fi);