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
45 #include "../replace/replace.h"
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);
232 struct sockaddr *myname;
233 socklen_t myname_len;
235 struct sockaddr *peername;
236 socklen_t peername_len;
239 unsigned long pck_snd;
240 unsigned long pck_rcv;
243 struct socket_info *prev, *next;
246 static struct socket_info *sockets;
248 const char *socket_wrapper_dir(void)
250 const char *s = getenv("SOCKET_WRAPPER_DIR");
254 if (strncmp(s, "./", 2) == 0) {
260 unsigned int socket_wrapper_default_iface(void)
262 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
265 if (sscanf(s, "%u", &iface) == 1) {
266 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
272 return 1;/* 127.0.0.1 */
275 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
282 p = strrchr(un->sun_path, '/');
283 if (p) p++; else p = un->sun_path;
285 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
290 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
301 case SOCKET_TYPE_CHAR_TCP:
302 case SOCKET_TYPE_CHAR_UDP: {
303 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
305 if ((*len) < sizeof(*in2)) {
310 memset(in2, 0, sizeof(*in2));
311 in2->sin_family = AF_INET;
312 in2->sin_addr.s_addr = htonl((127<<24) | iface);
313 in2->sin_port = htons(prt);
319 case SOCKET_TYPE_CHAR_TCP_V6:
320 case SOCKET_TYPE_CHAR_UDP_V6: {
321 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
323 if ((*len) < sizeof(*in2)) {
328 memset(in2, 0, sizeof(*in2));
329 in2->sin6_family = AF_INET6;
330 in2->sin6_addr = *swrap_ipv6();
331 in2->sin6_addr.s6_addr[15] = iface;
332 in2->sin6_port = htons(prt);
346 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
354 if (bcast) *bcast = 0;
356 switch (inaddr->sa_family) {
358 const struct sockaddr_in *in =
359 (const struct sockaddr_in *)(const void *)inaddr;
360 unsigned int addr = ntohl(in->sin_addr.s_addr);
367 u_type = SOCKET_TYPE_CHAR_TCP;
370 u_type = SOCKET_TYPE_CHAR_UDP;
371 a_type = SOCKET_TYPE_CHAR_UDP;
372 b_type = SOCKET_TYPE_CHAR_UDP;
376 prt = ntohs(in->sin_port);
377 if (a_type && addr == 0xFFFFFFFF) {
378 /* 255.255.255.255 only udp */
381 iface = socket_wrapper_default_iface();
382 } else if (b_type && addr == 0x7FFFFFFF) {
383 /* 127.255.255.255 only udp */
386 iface = socket_wrapper_default_iface();
387 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
391 iface = (addr & 0x000000FF);
396 if (bcast) *bcast = is_bcast;
401 const struct sockaddr_in6 *in =
402 (const struct sockaddr_in6 *)(const void *)inaddr;
403 struct in6_addr cmp1, cmp2;
407 type = SOCKET_TYPE_CHAR_TCP_V6;
410 type = SOCKET_TYPE_CHAR_UDP_V6;
414 /* XXX no multicast/broadcast */
416 prt = ntohs(in->sin6_port);
418 cmp1 = *swrap_ipv6();
419 cmp2 = in->sin6_addr;
420 cmp2.s6_addr[15] = 0;
421 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
422 iface = in->sin6_addr.s6_addr[15];
442 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
443 socket_wrapper_dir());
444 /* the caller need to do more processing */
448 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
449 socket_wrapper_dir(), type, iface, prt);
454 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
463 if (bcast) *bcast = 0;
465 switch (si->family) {
467 const struct sockaddr_in *in =
468 (const struct sockaddr_in *)(const void *)inaddr;
469 unsigned int addr = ntohl(in->sin_addr.s_addr);
475 prt = ntohs(in->sin_port);
479 u_type = SOCKET_TYPE_CHAR_TCP;
480 d_type = SOCKET_TYPE_CHAR_TCP;
483 u_type = SOCKET_TYPE_CHAR_UDP;
484 d_type = SOCKET_TYPE_CHAR_UDP;
485 a_type = SOCKET_TYPE_CHAR_UDP;
486 b_type = SOCKET_TYPE_CHAR_UDP;
494 iface = socket_wrapper_default_iface();
495 } else if (a_type && addr == 0xFFFFFFFF) {
496 /* 255.255.255.255 only udp */
499 iface = socket_wrapper_default_iface();
500 } else if (b_type && addr == 0x7FFFFFFF) {
501 /* 127.255.255.255 only udp */
504 iface = socket_wrapper_default_iface();
505 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
509 iface = (addr & 0x000000FF);
511 errno = EADDRNOTAVAIL;
518 const struct sockaddr_in6 *in =
519 (const struct sockaddr_in6 *)(const void *)inaddr;
520 struct in6_addr cmp1, cmp2;
524 type = SOCKET_TYPE_CHAR_TCP_V6;
527 type = SOCKET_TYPE_CHAR_UDP_V6;
531 /* XXX no multicast/broadcast */
533 prt = ntohs(in->sin6_port);
535 cmp1 = *swrap_ipv6();
536 cmp2 = in->sin6_addr;
537 cmp2.s6_addr[15] = 0;
538 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
539 iface = socket_wrapper_default_iface();
540 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
541 iface = in->sin6_addr.s6_addr[15];
543 errno = EADDRNOTAVAIL;
551 errno = EADDRNOTAVAIL;
556 if (bcast) *bcast = is_bcast;
558 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
564 /* handle auto-allocation of ephemeral ports */
565 for (prt = 5001; prt < 10000; prt++) {
566 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
567 socket_wrapper_dir(), type, iface, prt);
568 if (stat(un->sun_path, &st) == 0) continue;
570 set_port(si->family, prt, si->myname);
579 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
580 socket_wrapper_dir(), type, iface, prt);
584 static struct socket_info *find_socket_info(int fd)
586 struct socket_info *i;
587 for (i = sockets; i; i = i->next) {
595 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
596 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
598 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
602 out->sa_family = AF_UNIX;
603 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
604 out->sa_len = sizeof(*out_addr);
607 switch (in_addr->sa_family) {
617 errno = ESOCKTNOSUPPORT;
621 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
623 return convert_in_un_remote(si, in_addr, out_addr, bcast);
629 errno = EAFNOSUPPORT;
633 static int sockaddr_convert_from_un(const struct socket_info *si,
634 const struct sockaddr_un *in_addr,
635 socklen_t un_addrlen,
637 struct sockaddr *out_addr,
638 socklen_t *out_addrlen)
642 if (out_addr == NULL || out_addrlen == NULL)
645 if (un_addrlen == 0) {
660 errno = ESOCKTNOSUPPORT;
663 ret = convert_un_in(in_addr, out_addr, out_addrlen);
664 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
665 out_addr->sa_len = *out_addrlen;
672 errno = EAFNOSUPPORT;
676 enum swrap_packet_type {
678 SWRAP_CONNECT_UNREACH,
686 SWRAP_SENDTO_UNREACH,
697 struct swrap_file_hdr {
699 uint16_t version_major;
700 uint16_t version_minor;
703 uint32_t frame_max_len;
704 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
707 #define SWRAP_FILE_HDR_SIZE 24
709 struct swrap_packet_frame {
711 uint32_t micro_seconds;
712 uint32_t recorded_length;
713 uint32_t full_length;
715 #define SWRAP_PACKET_FRAME_SIZE 16
717 union swrap_packet_ip {
721 uint16_t packet_length;
722 uint16_t identification;
727 uint16_t hdr_checksum;
731 #define SWRAP_PACKET_IP_V4_SIZE 20
734 uint8_t flow_label_high;
735 uint16_t flow_label_low;
736 uint16_t payload_length;
739 uint8_t src_addr[16];
740 uint8_t dest_addr[16];
742 #define SWRAP_PACKET_IP_V6_SIZE 40
744 #define SWRAP_PACKET_IP_SIZE 40
746 union swrap_packet_payload {
748 uint16_t source_port;
758 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
760 uint16_t source_port;
765 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
772 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
779 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
781 #define SWRAP_PACKET_PAYLOAD_SIZE 20
783 #define SWRAP_PACKET_MIN_ALLOC \
784 (SWRAP_PACKET_FRAME_SIZE + \
785 SWRAP_PACKET_IP_SIZE + \
786 SWRAP_PACKET_PAYLOAD_SIZE)
788 static const char *socket_wrapper_pcap_file(void)
790 static int initialized = 0;
791 static const char *s = NULL;
792 static const struct swrap_file_hdr h;
793 static const struct swrap_packet_frame f;
794 static const union swrap_packet_ip i;
795 static const union swrap_packet_payload p;
797 if (initialized == 1) {
803 * TODO: don't use the structs use plain buffer offsets
804 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
806 * for now make sure we disable PCAP support
807 * if the struct has alignment!
809 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
812 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
815 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
818 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
821 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
824 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
827 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
830 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
833 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
836 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
840 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
844 if (strncmp(s, "./", 2) == 0) {
850 static uint8_t *swrap_packet_init(struct timeval *tval,
851 const struct sockaddr *src,
852 const struct sockaddr *dest,
854 const uint8_t *payload,
856 unsigned long tcp_seqno,
857 unsigned long tcp_ack,
858 unsigned char tcp_ctl,
864 struct swrap_packet_frame *frame;
865 union swrap_packet_ip *ip;
866 union swrap_packet_payload *pay;
869 size_t nonwire_len = sizeof(*frame);
870 size_t wire_hdr_len = 0;
872 size_t ip_hdr_len = 0;
873 size_t icmp_hdr_len = 0;
874 size_t icmp_truncate_len = 0;
875 uint8_t protocol = 0, icmp_protocol = 0;
876 const struct sockaddr_in *src_in = NULL;
877 const struct sockaddr_in *dest_in = NULL;
879 const struct sockaddr_in6 *src_in6 = NULL;
880 const struct sockaddr_in6 *dest_in6 = NULL;
885 switch (src->sa_family) {
887 src_in = (const struct sockaddr_in *)src;
888 dest_in = (const struct sockaddr_in *)dest;
889 src_port = src_in->sin_port;
890 dest_port = dest_in->sin_port;
891 ip_hdr_len = sizeof(ip->v4);
895 src_in6 = (const struct sockaddr_in6 *)src;
896 dest_in6 = (const struct sockaddr_in6 *)dest;
897 src_port = src_in6->sin6_port;
898 dest_port = dest_in6->sin6_port;
899 ip_hdr_len = sizeof(ip->v6);
906 switch (socket_type) {
908 protocol = 0x06; /* TCP */
909 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
910 wire_len = wire_hdr_len + payload_len;
914 protocol = 0x11; /* UDP */
915 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
916 wire_len = wire_hdr_len + payload_len;
924 icmp_protocol = protocol;
925 switch (src->sa_family) {
927 protocol = 0x01; /* ICMPv4 */
928 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
932 protocol = 0x3A; /* ICMPv6 */
933 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
937 if (wire_len > 64 ) {
938 icmp_truncate_len = wire_len - 64;
940 wire_hdr_len += icmp_hdr_len;
941 wire_len += icmp_hdr_len;
944 packet_len = nonwire_len + wire_len;
945 alloc_len = packet_len;
946 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
947 alloc_len = SWRAP_PACKET_MIN_ALLOC;
950 base = (uint8_t *)malloc(alloc_len);
951 if (!base) return NULL;
955 frame = (struct swrap_packet_frame *)buf;
956 frame->seconds = tval->tv_sec;
957 frame->micro_seconds = tval->tv_usec;
958 frame->recorded_length = wire_len - icmp_truncate_len;
959 frame->full_length = wire_len - icmp_truncate_len;
960 buf += SWRAP_PACKET_FRAME_SIZE;
962 ip = (union swrap_packet_ip *)buf;
963 switch (src->sa_family) {
965 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
967 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
968 ip->v4.identification = htons(0xFFFF);
969 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
970 ip->v4.fragment = htons(0x0000);
972 ip->v4.protocol = protocol;
973 ip->v4.hdr_checksum = htons(0x0000);
974 ip->v4.src_addr = src_in->sin_addr.s_addr;
975 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
976 buf += SWRAP_PACKET_IP_V4_SIZE;
980 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
981 ip->v6.flow_label_high = 0x00;
982 ip->v6.flow_label_low = 0x0000;
983 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
984 ip->v6.next_header = protocol;
985 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
986 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
987 buf += SWRAP_PACKET_IP_V6_SIZE;
993 pay = (union swrap_packet_payload *)buf;
994 switch (src->sa_family) {
996 pay->icmp4.type = 0x03; /* destination unreachable */
997 pay->icmp4.code = 0x01; /* host unreachable */
998 pay->icmp4.checksum = htons(0x0000);
999 pay->icmp4.unused = htonl(0x00000000);
1000 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1002 /* set the ip header in the ICMP payload */
1003 ip = (union swrap_packet_ip *)buf;
1004 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1006 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1007 ip->v4.identification = htons(0xFFFF);
1008 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1009 ip->v4.fragment = htons(0x0000);
1011 ip->v4.protocol = icmp_protocol;
1012 ip->v4.hdr_checksum = htons(0x0000);
1013 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1014 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1015 buf += SWRAP_PACKET_IP_V4_SIZE;
1017 src_port = dest_in->sin_port;
1018 dest_port = src_in->sin_port;
1022 pay->icmp6.type = 0x01; /* destination unreachable */
1023 pay->icmp6.code = 0x03; /* address unreachable */
1024 pay->icmp6.checksum = htons(0x0000);
1025 pay->icmp6.unused = htonl(0x00000000);
1026 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1028 /* set the ip header in the ICMP payload */
1029 ip = (union swrap_packet_ip *)buf;
1030 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1031 ip->v6.flow_label_high = 0x00;
1032 ip->v6.flow_label_low = 0x0000;
1033 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1034 ip->v6.next_header = protocol;
1035 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1036 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1037 buf += SWRAP_PACKET_IP_V6_SIZE;
1039 src_port = dest_in6->sin6_port;
1040 dest_port = src_in6->sin6_port;
1046 pay = (union swrap_packet_payload *)buf;
1048 switch (socket_type) {
1050 pay->tcp.source_port = src_port;
1051 pay->tcp.dest_port = dest_port;
1052 pay->tcp.seq_num = htonl(tcp_seqno);
1053 pay->tcp.ack_num = htonl(tcp_ack);
1054 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1055 pay->tcp.control = tcp_ctl;
1056 pay->tcp.window = htons(0x7FFF);
1057 pay->tcp.checksum = htons(0x0000);
1058 pay->tcp.urg = htons(0x0000);
1059 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1064 pay->udp.source_port = src_port;
1065 pay->udp.dest_port = dest_port;
1066 pay->udp.length = htons(8 + payload_len);
1067 pay->udp.checksum = htons(0x0000);
1068 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1073 if (payload && payload_len > 0) {
1074 memcpy(buf, payload, payload_len);
1077 *_packet_len = packet_len - icmp_truncate_len;
1081 static int swrap_get_pcap_fd(const char *fname)
1085 if (fd != -1) return fd;
1087 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1089 struct swrap_file_hdr file_hdr;
1090 file_hdr.magic = 0xA1B2C3D4;
1091 file_hdr.version_major = 0x0002;
1092 file_hdr.version_minor = 0x0004;
1093 file_hdr.timezone = 0x00000000;
1094 file_hdr.sigfigs = 0x00000000;
1095 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1096 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1098 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1105 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1110 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1111 const struct sockaddr *addr,
1112 enum swrap_packet_type type,
1113 const void *buf, size_t len,
1116 const struct sockaddr *src_addr;
1117 const struct sockaddr *dest_addr;
1118 unsigned long tcp_seqno = 0;
1119 unsigned long tcp_ack = 0;
1120 unsigned char tcp_ctl = 0;
1121 int unreachable = 0;
1125 switch (si->family) {
1137 case SWRAP_CONNECT_SEND:
1138 if (si->type != SOCK_STREAM) return NULL;
1140 src_addr = si->myname;
1143 tcp_seqno = si->io.pck_snd;
1144 tcp_ack = si->io.pck_rcv;
1145 tcp_ctl = 0x02; /* SYN */
1147 si->io.pck_snd += 1;
1151 case SWRAP_CONNECT_RECV:
1152 if (si->type != SOCK_STREAM) return NULL;
1154 dest_addr = si->myname;
1157 tcp_seqno = si->io.pck_rcv;
1158 tcp_ack = si->io.pck_snd;
1159 tcp_ctl = 0x12; /** SYN,ACK */
1161 si->io.pck_rcv += 1;
1165 case SWRAP_CONNECT_UNREACH:
1166 if (si->type != SOCK_STREAM) return NULL;
1168 dest_addr = si->myname;
1171 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1172 tcp_seqno = si->io.pck_snd - 1;
1173 tcp_ack = si->io.pck_rcv;
1174 tcp_ctl = 0x02; /* SYN */
1179 case SWRAP_CONNECT_ACK:
1180 if (si->type != SOCK_STREAM) return NULL;
1182 src_addr = si->myname;
1185 tcp_seqno = si->io.pck_snd;
1186 tcp_ack = si->io.pck_rcv;
1187 tcp_ctl = 0x10; /* ACK */
1191 case SWRAP_ACCEPT_SEND:
1192 if (si->type != SOCK_STREAM) return NULL;
1194 dest_addr = si->myname;
1197 tcp_seqno = si->io.pck_rcv;
1198 tcp_ack = si->io.pck_snd;
1199 tcp_ctl = 0x02; /* SYN */
1201 si->io.pck_rcv += 1;
1205 case SWRAP_ACCEPT_RECV:
1206 if (si->type != SOCK_STREAM) return NULL;
1208 src_addr = si->myname;
1211 tcp_seqno = si->io.pck_snd;
1212 tcp_ack = si->io.pck_rcv;
1213 tcp_ctl = 0x12; /* SYN,ACK */
1215 si->io.pck_snd += 1;
1219 case SWRAP_ACCEPT_ACK:
1220 if (si->type != SOCK_STREAM) return NULL;
1222 dest_addr = si->myname;
1225 tcp_seqno = si->io.pck_rcv;
1226 tcp_ack = si->io.pck_snd;
1227 tcp_ctl = 0x10; /* ACK */
1232 src_addr = si->myname;
1233 dest_addr = si->peername;
1235 tcp_seqno = si->io.pck_snd;
1236 tcp_ack = si->io.pck_rcv;
1237 tcp_ctl = 0x18; /* PSH,ACK */
1239 si->io.pck_snd += len;
1243 case SWRAP_SEND_RST:
1244 dest_addr = si->myname;
1245 src_addr = si->peername;
1247 if (si->type == SOCK_DGRAM) {
1248 return swrap_marshall_packet(si, si->peername,
1249 SWRAP_SENDTO_UNREACH,
1250 buf, len, packet_len);
1253 tcp_seqno = si->io.pck_rcv;
1254 tcp_ack = si->io.pck_snd;
1255 tcp_ctl = 0x14; /** RST,ACK */
1259 case SWRAP_PENDING_RST:
1260 dest_addr = si->myname;
1261 src_addr = si->peername;
1263 if (si->type == SOCK_DGRAM) {
1267 tcp_seqno = si->io.pck_rcv;
1268 tcp_ack = si->io.pck_snd;
1269 tcp_ctl = 0x14; /* RST,ACK */
1274 dest_addr = si->myname;
1275 src_addr = si->peername;
1277 tcp_seqno = si->io.pck_rcv;
1278 tcp_ack = si->io.pck_snd;
1279 tcp_ctl = 0x18; /* PSH,ACK */
1281 si->io.pck_rcv += len;
1285 case SWRAP_RECV_RST:
1286 dest_addr = si->myname;
1287 src_addr = si->peername;
1289 if (si->type == SOCK_DGRAM) {
1293 tcp_seqno = si->io.pck_rcv;
1294 tcp_ack = si->io.pck_snd;
1295 tcp_ctl = 0x14; /* RST,ACK */
1300 src_addr = si->myname;
1303 si->io.pck_snd += len;
1307 case SWRAP_SENDTO_UNREACH:
1308 dest_addr = si->myname;
1315 case SWRAP_RECVFROM:
1316 dest_addr = si->myname;
1319 si->io.pck_rcv += len;
1323 case SWRAP_CLOSE_SEND:
1324 if (si->type != SOCK_STREAM) return NULL;
1326 src_addr = si->myname;
1327 dest_addr = si->peername;
1329 tcp_seqno = si->io.pck_snd;
1330 tcp_ack = si->io.pck_rcv;
1331 tcp_ctl = 0x11; /* FIN, ACK */
1333 si->io.pck_snd += 1;
1337 case SWRAP_CLOSE_RECV:
1338 if (si->type != SOCK_STREAM) return NULL;
1340 dest_addr = si->myname;
1341 src_addr = si->peername;
1343 tcp_seqno = si->io.pck_rcv;
1344 tcp_ack = si->io.pck_snd;
1345 tcp_ctl = 0x11; /* FIN,ACK */
1347 si->io.pck_rcv += 1;
1351 case SWRAP_CLOSE_ACK:
1352 if (si->type != SOCK_STREAM) return NULL;
1354 src_addr = si->myname;
1355 dest_addr = si->peername;
1357 tcp_seqno = si->io.pck_snd;
1358 tcp_ack = si->io.pck_rcv;
1359 tcp_ctl = 0x10; /* ACK */
1366 swrapGetTimeOfDay(&tv);
1368 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1369 (const uint8_t *)buf, len,
1370 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1374 static void swrap_dump_packet(struct socket_info *si,
1375 const struct sockaddr *addr,
1376 enum swrap_packet_type type,
1377 const void *buf, size_t len)
1379 const char *file_name;
1381 size_t packet_len = 0;
1384 file_name = socket_wrapper_pcap_file();
1389 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1394 fd = swrap_get_pcap_fd(file_name);
1396 if (write(fd, packet, packet_len) != packet_len) {
1405 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1407 struct socket_info *si;
1409 int real_type = type;
1411 real_type &= ~SOCK_CLOEXEC;
1413 #ifdef SOCK_NONBLOCK
1414 real_type &= ~SOCK_NONBLOCK;
1417 if (!socket_wrapper_dir()) {
1418 return real_socket(family, type, protocol);
1428 return real_socket(family, type, protocol);
1430 errno = EAFNOSUPPORT;
1434 switch (real_type) {
1440 errno = EPROTONOSUPPORT;
1448 if (real_type == SOCK_STREAM) {
1453 if (real_type == SOCK_DGRAM) {
1458 errno = EPROTONOSUPPORT;
1462 /* We must call real_socket with type, from the caller, not the version we removed
1463 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1464 fd = real_socket(AF_UNIX, type, 0);
1466 if (fd == -1) return -1;
1468 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1470 si->family = family;
1472 /* however, the rest of the socket_wrapper code expects just
1473 * the type, not the flags */
1474 si->type = real_type;
1475 si->protocol = protocol;
1478 SWRAP_DLIST_ADD(sockets, si);
1483 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1485 struct socket_info *parent_si, *child_si;
1487 struct sockaddr_un un_addr;
1488 socklen_t un_addrlen = sizeof(un_addr);
1489 struct sockaddr_un un_my_addr;
1490 socklen_t un_my_addrlen = sizeof(un_my_addr);
1491 struct sockaddr *my_addr;
1492 socklen_t my_addrlen, len;
1495 parent_si = find_socket_info(s);
1497 return real_accept(s, addr, addrlen);
1501 * assume out sockaddr have the same size as the in parent
1504 my_addrlen = socket_length(parent_si->family);
1505 if (my_addrlen <= 0) {
1510 my_addr = (struct sockaddr *)malloc(my_addrlen);
1511 if (my_addr == NULL) {
1515 memset(&un_addr, 0, sizeof(un_addr));
1516 memset(&un_my_addr, 0, sizeof(un_my_addr));
1518 ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
1527 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1528 parent_si->family, my_addr, &len);
1535 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1536 memset(child_si, 0, sizeof(*child_si));
1539 child_si->family = parent_si->family;
1540 child_si->type = parent_si->type;
1541 child_si->protocol = parent_si->protocol;
1542 child_si->bound = 1;
1543 child_si->is_server = 1;
1544 child_si->connected = 1;
1546 child_si->peername_len = len;
1547 child_si->peername = sockaddr_dup(my_addr, len);
1549 if (addr != NULL && addrlen != NULL) {
1550 size_t copy_len = MIN(*addrlen, len);
1552 memcpy(addr, my_addr, copy_len);
1557 ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr,
1566 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1567 child_si->family, my_addr, &len);
1575 child_si->myname_len = len;
1576 child_si->myname = sockaddr_dup(my_addr, len);
1579 SWRAP_DLIST_ADD(sockets, child_si);
1581 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1582 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1583 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1588 static int autobind_start_init;
1589 static int autobind_start;
1591 /* using sendto() or connect() on an unbound socket would give the
1592 recipient no way to reply, as unlike UDP and TCP, a unix domain
1593 socket can't auto-assign emphemeral port numbers, so we need to
1595 Note: this might change the family from ipv6 to ipv4
1597 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
1599 struct sockaddr_un un_addr;
1606 if (autobind_start_init != 1) {
1607 autobind_start_init = 1;
1608 autobind_start = getpid();
1609 autobind_start %= 50000;
1610 autobind_start += 10000;
1613 un_addr.sun_family = AF_UNIX;
1617 struct sockaddr_in in;
1621 type = SOCKET_TYPE_CHAR_TCP;
1624 type = SOCKET_TYPE_CHAR_UDP;
1627 errno = ESOCKTNOSUPPORT;
1631 memset(&in, 0, sizeof(in));
1632 in.sin_family = AF_INET;
1633 in.sin_addr.s_addr = htonl(127<<24 |
1634 socket_wrapper_default_iface());
1636 si->myname_len = sizeof(in);
1637 si->myname = sockaddr_dup(&in, si->myname_len);
1642 struct sockaddr_in6 in6;
1644 if (si->family != family) {
1645 errno = ENETUNREACH;
1651 type = SOCKET_TYPE_CHAR_TCP_V6;
1654 type = SOCKET_TYPE_CHAR_UDP_V6;
1657 errno = ESOCKTNOSUPPORT;
1661 memset(&in6, 0, sizeof(in6));
1662 in6.sin6_family = AF_INET6;
1663 in6.sin6_addr = *swrap_ipv6();
1664 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1665 si->myname_len = sizeof(in6);
1666 si->myname = sockaddr_dup(&in6, si->myname_len);
1671 errno = ESOCKTNOSUPPORT;
1675 if (autobind_start > 60000) {
1676 autobind_start = 10000;
1679 for (i=0;i<1000;i++) {
1680 port = autobind_start + i;
1681 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1682 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1683 type, socket_wrapper_default_iface(), port);
1684 if (stat(un_addr.sun_path, &st) == 0) continue;
1686 ret = real_bind(fd, (struct sockaddr *)(void *)&un_addr,
1688 if (ret == -1) return ret;
1690 si->tmp_path = strdup(un_addr.sun_path);
1692 autobind_start = port + 1;
1700 si->family = family;
1701 set_port(si->family, port, si->myname);
1707 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1710 struct sockaddr_un un_addr;
1711 struct socket_info *si = find_socket_info(s);
1715 return real_connect(s, serv_addr, addrlen);
1718 if (si->bound == 0) {
1719 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
1720 if (ret == -1) return -1;
1723 if (si->family != serv_addr->sa_family) {
1728 ret = sockaddr_convert_to_un(si, serv_addr,
1729 addrlen, &un_addr, 0, &bcast);
1730 if (ret == -1) return -1;
1733 errno = ENETUNREACH;
1737 if (si->type == SOCK_DGRAM) {
1738 si->defer_connect = 1;
1741 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1743 ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
1744 sizeof(struct sockaddr_un));
1747 /* to give better errors */
1748 if (ret == -1 && errno == ENOENT) {
1749 errno = EHOSTUNREACH;
1753 si->peername_len = addrlen;
1754 si->peername = sockaddr_dup(serv_addr, addrlen);
1757 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1758 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1760 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1766 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1769 struct sockaddr_un un_addr;
1770 struct socket_info *si = find_socket_info(s);
1773 return real_bind(s, myaddr, addrlen);
1776 si->myname_len = addrlen;
1777 si->myname = sockaddr_dup(myaddr, addrlen);
1779 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
1780 if (ret == -1) return -1;
1782 unlink(un_addr.sun_path);
1784 ret = real_bind(s, (struct sockaddr *)(void *)&un_addr,
1785 sizeof(struct sockaddr_un));
1794 _PUBLIC_ int swrap_listen(int s, int backlog)
1797 struct socket_info *si = find_socket_info(s);
1800 return real_listen(s, backlog);
1803 ret = real_listen(s, backlog);
1808 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1810 struct socket_info *si = find_socket_info(s);
1813 return real_getpeername(s, name, addrlen);
1822 memcpy(name, si->peername, si->peername_len);
1823 *addrlen = si->peername_len;
1828 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1830 struct socket_info *si = find_socket_info(s);
1833 return real_getsockname(s, name, addrlen);
1836 memcpy(name, si->myname, si->myname_len);
1837 *addrlen = si->myname_len;
1842 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1844 struct socket_info *si = find_socket_info(s);
1847 return real_getsockopt(s, level, optname, optval, optlen);
1850 if (level == SOL_SOCKET) {
1851 return real_getsockopt(s, level, optname, optval, optlen);
1854 errno = ENOPROTOOPT;
1858 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1860 struct socket_info *si = find_socket_info(s);
1863 return real_setsockopt(s, level, optname, optval, optlen);
1866 if (level == SOL_SOCKET) {
1867 return real_setsockopt(s, level, optname, optval, optlen);
1870 switch (si->family) {
1878 errno = ENOPROTOOPT;
1883 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1886 struct socket_info *si = find_socket_info(s);
1890 return real_ioctl(s, r, p);
1893 ret = real_ioctl(s, r, p);
1897 value = *((int *)p);
1898 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1899 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1900 } else if (value == 0) { /* END OF FILE */
1901 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1909 static ssize_t swrap_sendmsg_before(int fd,
1910 struct socket_info *si,
1912 struct iovec *tmp_iov,
1913 struct sockaddr_un *tmp_un,
1914 const struct sockaddr_un **to_un,
1915 const struct sockaddr **to,
1933 if (!si->connected) {
1938 if (msg->msg_iovlen == 0) {
1943 * cut down to 1500 byte packets for stream sockets,
1944 * which makes it easier to format PCAP capture files
1945 * (as the caller will simply continue from here)
1948 for (i=0; i < msg->msg_iovlen; i++) {
1950 nlen = len + msg->msg_iov[i].iov_len;
1955 msg->msg_iovlen = i;
1956 if (msg->msg_iovlen == 0) {
1957 *tmp_iov = msg->msg_iov[0];
1958 tmp_iov->iov_len = MIN(tmp_iov->iov_len, 1500);
1959 msg->msg_iov = tmp_iov;
1960 msg->msg_iovlen = 1;
1965 if (si->connected) {
1966 if (msg->msg_name) {
1971 const struct sockaddr *msg_name;
1972 msg_name = (const struct sockaddr *)msg->msg_name;
1974 if (msg_name == NULL) {
1980 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
1982 if (ret == -1) return -1;
1990 msg->msg_name = tmp_un;
1991 msg->msg_namelen = sizeof(*tmp_un);
1994 if (si->bound == 0) {
1995 ret = swrap_auto_bind(fd, si, si->family);
1996 if (ret == -1) return -1;
1999 if (!si->defer_connect) {
2003 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2005 if (ret == -1) return -1;
2007 ret = real_connect(fd, (struct sockaddr *)(void *)tmp_un,
2010 /* to give better errors */
2011 if (ret == -1 && errno == ENOENT) {
2012 errno = EHOSTUNREACH;
2019 si->defer_connect = 0;
2022 errno = EHOSTUNREACH;
2029 static void swrap_sendmsg_after(struct socket_info *si,
2031 const struct sockaddr *to,
2034 int saved_errno = errno;
2041 /* to give better errors */
2042 if (ret == -1 && saved_errno == ENOENT) {
2043 saved_errno = EHOSTUNREACH;
2046 for (i=0; i < msg->msg_iovlen; i++) {
2047 avail += msg->msg_iov[i].iov_len;
2051 remain = MIN(80, avail);
2056 /* we capture it as one single packet */
2057 buf = (uint8_t *)malloc(remain);
2059 /* we just not capture the packet */
2060 errno = saved_errno;
2064 for (i=0; i < msg->msg_iovlen; i++) {
2065 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2067 msg->msg_iov[i].iov_base,
2070 remain -= this_time;
2077 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2078 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2080 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2085 if (si->connected) {
2089 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2090 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
2092 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2098 errno = saved_errno;
2101 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
2103 struct sockaddr_un un_addr;
2104 socklen_t un_addrlen = sizeof(un_addr);
2106 struct socket_info *si = find_socket_info(s);
2107 struct sockaddr_storage ss;
2108 socklen_t ss_len = sizeof(ss);
2111 return real_recvfrom(s, buf, len, flags, from, fromlen);
2115 from = (struct sockaddr *)(void *)&ss;
2119 if (si->type == SOCK_STREAM) {
2120 /* cut down to 1500 byte packets for stream sockets,
2121 * which makes it easier to format PCAP capture files
2122 * (as the caller will simply continue from here) */
2123 len = MIN(len, 1500);
2126 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2127 memset(&un_addr, 0, sizeof(un_addr));
2128 ret = real_recvfrom(s, buf, len, flags,
2129 (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2133 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
2134 si->family, from, fromlen) == -1) {
2138 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
2144 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
2148 struct sockaddr_un un_addr;
2149 const struct sockaddr_un *to_un = NULL;
2151 struct socket_info *si = find_socket_info(s);
2155 return real_sendto(s, buf, len, flags, to, tolen);
2158 tmp.iov_base = discard_const_p(char, buf);
2162 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
2163 msg.msg_namelen = tolen; /* size of address */
2164 msg.msg_iov = &tmp; /* scatter/gather array */
2165 msg.msg_iovlen = 1; /* # elements in msg_iov */
2166 #if 0 /* not available on solaris */
2167 msg.msg_control = NULL; /* ancillary data, see below */
2168 msg.msg_controllen = 0; /* ancillary data buffer len */
2169 msg.msg_flags = 0; /* flags on received message */
2172 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2173 if (ret == -1) return -1;
2175 buf = msg.msg_iov[0].iov_base;
2176 len = msg.msg_iov[0].iov_len;
2181 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2184 type = SOCKET_TYPE_CHAR_UDP;
2186 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2187 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2188 socket_wrapper_dir(), type, iface, prt);
2189 if (stat(un_addr.sun_path, &st) != 0) continue;
2191 /* ignore the any errors in broadcast sends */
2192 real_sendto(s, buf, len, flags,
2193 (struct sockaddr *)(void *)&un_addr,
2197 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2202 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)msg.msg_name,
2205 swrap_sendmsg_after(si, &msg, to, ret);
2210 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
2213 struct socket_info *si = find_socket_info(s);
2216 return real_recv(s, buf, len, flags);
2219 if (si->type == SOCK_STREAM) {
2220 /* cut down to 1500 byte packets for stream sockets,
2221 * which makes it easier to format PCAP capture files
2222 * (as the caller will simply continue from here) */
2223 len = MIN(len, 1500);
2226 ret = real_recv(s, buf, len, flags);
2227 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2228 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2229 } else if (ret == 0) { /* END OF FILE */
2230 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2231 } else if (ret > 0) {
2232 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2238 _PUBLIC_ ssize_t swrap_read(int s, void *buf, size_t len)
2241 struct socket_info *si = find_socket_info(s);
2244 return real_read(s, buf, len);
2247 if (si->type == SOCK_STREAM) {
2248 /* cut down to 1500 byte packets for stream sockets,
2249 * which makes it easier to format PCAP capture files
2250 * (as the caller will simply continue from here) */
2251 len = MIN(len, 1500);
2254 ret = real_read(s, buf, len);
2255 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2256 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2257 } else if (ret == 0) { /* END OF FILE */
2258 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2259 } else if (ret > 0) {
2260 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2267 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2271 struct sockaddr_un un_addr;
2273 struct socket_info *si = find_socket_info(s);
2276 return real_send(s, buf, len, flags);
2279 tmp.iov_base = discard_const_p(char, buf);
2283 msg.msg_name = NULL; /* optional address */
2284 msg.msg_namelen = 0; /* size of address */
2285 msg.msg_iov = &tmp; /* scatter/gather array */
2286 msg.msg_iovlen = 1; /* # elements in msg_iov */
2287 #if 0 /* not available on solaris */
2288 msg.msg_control = NULL; /* ancillary data, see below */
2289 msg.msg_controllen = 0; /* ancillary data buffer len */
2290 msg.msg_flags = 0; /* flags on received message */
2293 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2294 if (ret == -1) return -1;
2296 buf = msg.msg_iov[0].iov_base;
2297 len = msg.msg_iov[0].iov_len;
2299 ret = real_send(s, buf, len, flags);
2301 swrap_sendmsg_after(si, &msg, NULL, ret);
2306 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
2310 struct sockaddr_un un_addr;
2311 const struct sockaddr_un *to_un = NULL;
2312 const struct sockaddr *to = NULL;
2314 struct socket_info *si = find_socket_info(s);
2318 return real_sendmsg(s, omsg, flags);
2321 tmp.iov_base = NULL;
2326 msg.msg_name = omsg->msg_name; /* optional address */
2327 msg.msg_namelen = omsg->msg_namelen; /* size of address */
2328 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
2329 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
2330 /* the following is not available on solaris */
2331 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
2332 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
2333 msg.msg_flags = omsg->msg_flags; /* flags on received message */
2336 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2337 if (ret == -1) return -1;
2342 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2350 for (i=0; i < msg.msg_iovlen; i++) {
2351 avail += msg.msg_iov[i].iov_len;
2357 /* we capture it as one single packet */
2358 buf = (uint8_t *)malloc(remain);
2363 for (i=0; i < msg.msg_iovlen; i++) {
2364 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
2366 msg.msg_iov[i].iov_base,
2369 remain -= this_time;
2372 type = SOCKET_TYPE_CHAR_UDP;
2374 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2375 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2376 socket_wrapper_dir(), type, iface, prt);
2377 if (stat(un_addr.sun_path, &st) != 0) continue;
2379 msg.msg_name = &un_addr; /* optional address */
2380 msg.msg_namelen = sizeof(un_addr); /* size of address */
2382 /* ignore the any errors in broadcast sends */
2383 real_sendmsg(s, &msg, flags);
2386 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2392 ret = real_sendmsg(s, &msg, flags);
2394 swrap_sendmsg_after(si, &msg, to, ret);
2399 int swrap_readv(int s, const struct iovec *vector, size_t count)
2402 struct socket_info *si = find_socket_info(s);
2406 return real_readv(s, vector, count);
2409 if (!si->connected) {
2414 if (si->type == SOCK_STREAM && count > 0) {
2415 /* cut down to 1500 byte packets for stream sockets,
2416 * which makes it easier to format PCAP capture files
2417 * (as the caller will simply continue from here) */
2420 for (i=0; i < count; i++) {
2422 nlen = len + vector[i].iov_len;
2430 v.iov_len = MIN(v.iov_len, 1500);
2436 ret = real_readv(s, vector, count);
2437 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2438 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2439 } else if (ret == 0) { /* END OF FILE */
2440 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2441 } else if (ret > 0) {
2445 size_t remain = ret;
2447 /* we capture it as one single packet */
2448 buf = (uint8_t *)malloc(ret);
2450 /* we just not capture the packet */
2455 for (i=0; i < count; i++) {
2456 size_t this_time = MIN(remain, vector[i].iov_len);
2461 remain -= this_time;
2464 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2471 int swrap_writev(int s, const struct iovec *vector, size_t count)
2475 struct sockaddr_un un_addr;
2477 struct socket_info *si = find_socket_info(s);
2480 return real_writev(s, vector, count);
2483 tmp.iov_base = NULL;
2487 msg.msg_name = NULL; /* optional address */
2488 msg.msg_namelen = 0; /* size of address */
2489 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
2490 msg.msg_iovlen = count; /* # elements in msg_iov */
2491 #if 0 /* not available on solaris */
2492 msg.msg_control = NULL; /* ancillary data, see below */
2493 msg.msg_controllen = 0; /* ancillary data buffer len */
2494 msg.msg_flags = 0; /* flags on received message */
2497 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2498 if (ret == -1) return -1;
2500 ret = real_writev(s, msg.msg_iov, msg.msg_iovlen);
2502 swrap_sendmsg_after(si, &msg, NULL, ret);
2507 _PUBLIC_ int swrap_close(int fd)
2509 struct socket_info *si = find_socket_info(fd);
2513 return real_close(fd);
2516 SWRAP_DLIST_REMOVE(sockets, si);
2518 if (si->myname && si->peername) {
2519 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2522 ret = real_close(fd);
2524 if (si->myname && si->peername) {
2525 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2526 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2529 if (si->myname) free(si->myname);
2530 if (si->peername) free(si->peername);
2532 unlink(si->tmp_path);
2540 _PUBLIC_ int swrap_dup(int fd)
2542 struct socket_info *si, *si2;
2545 si = find_socket_info(fd);
2548 return real_dup(fd);
2552 /* we would need reference counting to handle this */
2562 si2 = (struct socket_info *)malloc(sizeof(struct socket_info));
2569 /* copy the whole structure, then duplicate pointer elements */
2575 si2->myname = sockaddr_dup(si2->myname, si2->myname_len);
2576 if (si2->myname == NULL) {
2583 if (si2->peername) {
2584 si2->peername = sockaddr_dup(si2->peername, si2->peername_len);
2585 if (si2->peername == NULL) {
2592 SWRAP_DLIST_ADD(sockets, si2);
2596 _PUBLIC_ int swrap_dup2(int fd, int newfd)
2598 struct socket_info *si, *si2;
2601 si = find_socket_info(fd);
2604 return real_dup2(fd, newfd);
2608 /* we would need reference counting to handle this */
2613 if (find_socket_info(newfd)) {
2614 /* dup2() does an implicit close of newfd, which we
2615 * need to emulate */
2619 fd2 = real_dup2(fd, newfd);
2624 si2 = (struct socket_info *)malloc(sizeof(struct socket_info));
2631 /* copy the whole structure, then duplicate pointer elements */
2637 si2->myname = sockaddr_dup(si2->myname, si2->myname_len);
2638 if (si2->myname == NULL) {
2645 if (si2->peername) {
2646 si2->peername = sockaddr_dup(si2->peername, si2->peername_len);
2647 if (si2->peername == NULL) {
2654 SWRAP_DLIST_ADD(sockets, si2);