2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <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_ioctl ioctl
122 #define real_recv recv
123 #define real_send send
124 #define real_socket socket
125 #define real_close close
128 #ifdef HAVE_GETTIMEOFDAY_TZ
129 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
131 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
134 /* we need to use a very terse format here as IRIX 6.4 silently
135 truncates names to 16 chars, so if we use a longer name then we
136 can't tell which port a packet came from with recvfrom()
138 with this format we have 8 chars left for the directory name
140 #define SOCKET_FORMAT "%c%02X%04X"
141 #define SOCKET_TYPE_CHAR_TCP 'T'
142 #define SOCKET_TYPE_CHAR_UDP 'U'
143 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
144 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
146 #define MAX_WRAPPED_INTERFACES 16
148 #define SW_IPV6_ADDRESS 1
150 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
152 struct sockaddr *ret = (struct sockaddr *)malloc(len);
153 memcpy(ret, data, len);
157 static void set_port(int family, int prt, struct sockaddr *addr)
161 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
165 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
171 static size_t socket_length(int family)
175 return sizeof(struct sockaddr_in);
178 return sizeof(struct sockaddr_in6);
200 struct sockaddr *myname;
201 socklen_t myname_len;
203 struct sockaddr *peername;
204 socklen_t peername_len;
207 unsigned long pck_snd;
208 unsigned long pck_rcv;
211 struct socket_info *prev, *next;
214 static struct socket_info *sockets;
216 const char *socket_wrapper_dir(void)
218 const char *s = getenv("SOCKET_WRAPPER_DIR");
222 if (strncmp(s, "./", 2) == 0) {
228 unsigned int socket_wrapper_default_iface(void)
230 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
233 if (sscanf(s, "%u", &iface) == 1) {
234 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
240 return 1;/* 127.0.0.1 */
243 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
250 p = strrchr(un->sun_path, '/');
251 if (p) p++; else p = un->sun_path;
253 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
258 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
269 case SOCKET_TYPE_CHAR_TCP:
270 case SOCKET_TYPE_CHAR_UDP: {
271 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
273 if ((*len) < sizeof(*in2)) {
278 memset(in2, 0, sizeof(*in2));
279 in2->sin_family = AF_INET;
280 in2->sin_addr.s_addr = htonl((127<<24) | iface);
281 in2->sin_port = htons(prt);
287 case SOCKET_TYPE_CHAR_TCP_V6:
288 case SOCKET_TYPE_CHAR_UDP_V6: {
289 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
291 if ((*len) < sizeof(*in2)) {
296 memset(in2, 0, sizeof(*in2));
297 in2->sin6_family = AF_INET6;
298 in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
299 in2->sin6_port = htons(prt);
313 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
321 if (bcast) *bcast = 0;
323 switch (si->family) {
325 const struct sockaddr_in *in =
326 (const struct sockaddr_in *)inaddr;
327 unsigned int addr = ntohl(in->sin_addr.s_addr);
334 u_type = SOCKET_TYPE_CHAR_TCP;
337 u_type = SOCKET_TYPE_CHAR_UDP;
338 a_type = SOCKET_TYPE_CHAR_UDP;
339 b_type = SOCKET_TYPE_CHAR_UDP;
343 prt = ntohs(in->sin_port);
344 if (a_type && addr == 0xFFFFFFFF) {
345 /* 255.255.255.255 only udp */
348 iface = socket_wrapper_default_iface();
349 } else if (b_type && addr == 0x7FFFFFFF) {
350 /* 127.255.255.255 only udp */
353 iface = socket_wrapper_default_iface();
354 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
358 iface = (addr & 0x000000FF);
363 if (bcast) *bcast = is_bcast;
368 const struct sockaddr_in6 *in =
369 (const struct sockaddr_in6 *)inaddr;
373 type = SOCKET_TYPE_CHAR_TCP_V6;
376 type = SOCKET_TYPE_CHAR_UDP_V6;
380 /* XXX no multicast/broadcast */
382 prt = ntohs(in->sin6_port);
383 iface = SW_IPV6_ADDRESS;
399 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
400 socket_wrapper_dir());
401 /* the caller need to do more processing */
405 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
406 socket_wrapper_dir(), type, iface, prt);
411 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
420 if (bcast) *bcast = 0;
422 switch (si->family) {
424 const struct sockaddr_in *in =
425 (const struct sockaddr_in *)inaddr;
426 unsigned int addr = ntohl(in->sin_addr.s_addr);
432 prt = ntohs(in->sin_port);
436 u_type = SOCKET_TYPE_CHAR_TCP;
437 d_type = SOCKET_TYPE_CHAR_TCP;
440 u_type = SOCKET_TYPE_CHAR_UDP;
441 d_type = SOCKET_TYPE_CHAR_UDP;
442 a_type = SOCKET_TYPE_CHAR_UDP;
443 b_type = SOCKET_TYPE_CHAR_UDP;
451 iface = socket_wrapper_default_iface();
452 } else if (a_type && addr == 0xFFFFFFFF) {
453 /* 255.255.255.255 only udp */
456 iface = socket_wrapper_default_iface();
457 } else if (b_type && addr == 0x7FFFFFFF) {
458 /* 127.255.255.255 only udp */
461 iface = socket_wrapper_default_iface();
462 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
466 iface = (addr & 0x000000FF);
468 errno = EADDRNOTAVAIL;
475 const struct sockaddr_in6 *in =
476 (const struct sockaddr_in6 *)inaddr;
480 type = SOCKET_TYPE_CHAR_TCP_V6;
483 type = SOCKET_TYPE_CHAR_UDP_V6;
487 /* XXX no multicast/broadcast */
489 prt = ntohs(in->sin6_port);
490 iface = SW_IPV6_ADDRESS;
501 if (bcast) *bcast = is_bcast;
504 /* handle auto-allocation of ephemeral ports */
505 for (prt = 5001; prt < 10000; prt++) {
506 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
507 socket_wrapper_dir(), type, iface, prt);
508 if (stat(un->sun_path, &st) == 0) continue;
510 set_port(si->family, prt, si->myname);
519 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
520 socket_wrapper_dir(), type, iface, prt);
524 static struct socket_info *find_socket_info(int fd)
526 struct socket_info *i;
527 for (i = sockets; i; i = i->next) {
535 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
536 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
541 out_addr->sun_family = AF_UNIX;
543 switch (in_addr->sa_family) {
553 errno = ESOCKTNOSUPPORT;
557 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
559 return convert_in_un_remote(si, in_addr, out_addr, bcast);
565 errno = EAFNOSUPPORT;
569 static int sockaddr_convert_from_un(const struct socket_info *si,
570 const struct sockaddr_un *in_addr,
571 socklen_t un_addrlen,
573 struct sockaddr *out_addr,
574 socklen_t *out_addrlen)
576 if (out_addr == NULL || out_addrlen == NULL)
579 if (un_addrlen == 0) {
594 errno = ESOCKTNOSUPPORT;
597 return convert_un_in(in_addr, out_addr, out_addrlen);
602 errno = EAFNOSUPPORT;
606 enum swrap_packet_type {
608 SWRAP_CONNECT_UNREACH,
616 SWRAP_SENDTO_UNREACH,
627 struct swrap_file_hdr {
629 uint16_t version_major;
630 uint16_t version_minor;
633 uint32_t frame_max_len;
634 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
637 #define SWRAP_FILE_HDR_SIZE 24
639 struct swrap_packet {
642 uint32_t micro_seconds;
643 uint32_t recorded_length;
644 uint32_t full_length;
646 #define SWRAP_PACKET__FRAME_SIZE 16
652 uint16_t packet_length;
653 uint16_t identification;
658 uint16_t hdr_checksum;
662 #define SWRAP_PACKET__IP_HDR_SIZE 20
666 uint16_t source_port;
676 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
678 uint16_t source_port;
683 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
690 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
694 #define SWRAP_PACKET_SIZE 56
696 static const char *socket_wrapper_pcap_file(void)
698 static int initialized = 0;
699 static const char *s = NULL;
700 static const struct swrap_file_hdr h = { 0, };
701 static const struct swrap_packet p = { { 0, }, { { 0, }, { { 0, } } } };
703 if (initialized == 1) {
709 * TODO: don't use the structs use plain buffer offsets
710 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
712 * for now make sure we disable PCAP support
713 * if the struct has alignment!
715 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
718 if (sizeof(p) != SWRAP_PACKET_SIZE) {
721 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
724 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
727 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
730 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
733 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
737 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
741 if (strncmp(s, "./", 2) == 0) {
747 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
748 const struct sockaddr_in *src_addr,
749 const struct sockaddr_in *dest_addr,
751 const unsigned char *payload,
753 unsigned long tcp_seq,
754 unsigned long tcp_ack,
755 unsigned char tcp_ctl,
759 struct swrap_packet *ret;
760 struct swrap_packet *packet;
763 size_t nonwire_len = sizeof(packet->frame);
764 size_t wire_hdr_len = 0;
766 size_t icmp_hdr_len = 0;
767 size_t icmp_truncate_len = 0;
768 unsigned char protocol = 0, icmp_protocol = 0;
769 unsigned short src_port = src_addr->sin_port;
770 unsigned short dest_port = dest_addr->sin_port;
772 switch (socket_type) {
774 protocol = 0x06; /* TCP */
775 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
776 wire_len = wire_hdr_len + payload_len;
780 protocol = 0x11; /* UDP */
781 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
782 wire_len = wire_hdr_len + payload_len;
790 icmp_protocol = protocol;
791 protocol = 0x01; /* ICMP */
792 if (wire_len > 64 ) {
793 icmp_truncate_len = wire_len - 64;
795 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
796 wire_hdr_len += icmp_hdr_len;
797 wire_len += icmp_hdr_len;
800 packet_len = nonwire_len + wire_len;
801 alloc_len = packet_len;
802 if (alloc_len < sizeof(struct swrap_packet)) {
803 alloc_len = sizeof(struct swrap_packet);
805 ret = (struct swrap_packet *)malloc(alloc_len);
806 if (!ret) return NULL;
810 packet->frame.seconds = tval->tv_sec;
811 packet->frame.micro_seconds = tval->tv_usec;
812 packet->frame.recorded_length = wire_len - icmp_truncate_len;
813 packet->frame.full_length = wire_len - icmp_truncate_len;
815 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
816 packet->ip.hdr.tos = 0x00;
817 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
818 packet->ip.hdr.identification = htons(0xFFFF);
819 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
820 packet->ip.hdr.fragment = htons(0x0000);
821 packet->ip.hdr.ttl = 0xFF;
822 packet->ip.hdr.protocol = protocol;
823 packet->ip.hdr.hdr_checksum = htons(0x0000);
824 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
825 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
828 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
829 packet->ip.p.icmp.code = 0x01; /* host unreachable */
830 packet->ip.p.icmp.checksum = htons(0x0000);
831 packet->ip.p.icmp.unused = htonl(0x00000000);
833 /* set the ip header in the ICMP payload */
834 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
835 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
836 packet->ip.hdr.tos = 0x00;
837 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
838 packet->ip.hdr.identification = htons(0xFFFF);
839 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
840 packet->ip.hdr.fragment = htons(0x0000);
841 packet->ip.hdr.ttl = 0xFF;
842 packet->ip.hdr.protocol = icmp_protocol;
843 packet->ip.hdr.hdr_checksum = htons(0x0000);
844 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
845 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
847 src_port = dest_addr->sin_port;
848 dest_port = src_addr->sin_port;
851 switch (socket_type) {
853 packet->ip.p.tcp.source_port = src_port;
854 packet->ip.p.tcp.dest_port = dest_port;
855 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
856 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
857 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
858 packet->ip.p.tcp.control = tcp_ctl;
859 packet->ip.p.tcp.window = htons(0x7FFF);
860 packet->ip.p.tcp.checksum = htons(0x0000);
861 packet->ip.p.tcp.urg = htons(0x0000);
866 packet->ip.p.udp.source_port = src_addr->sin_port;
867 packet->ip.p.udp.dest_port = dest_addr->sin_port;
868 packet->ip.p.udp.length = htons(8 + payload_len);
869 packet->ip.p.udp.checksum = htons(0x0000);
874 if (payload && payload_len > 0) {
875 unsigned char *p = (unsigned char *)ret;
878 memcpy(p, payload, payload_len);
881 *_packet_len = packet_len - icmp_truncate_len;
885 static int swrap_get_pcap_fd(const char *fname)
889 if (fd != -1) return fd;
891 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
893 struct swrap_file_hdr file_hdr;
894 file_hdr.magic = 0xA1B2C3D4;
895 file_hdr.version_major = 0x0002;
896 file_hdr.version_minor = 0x0004;
897 file_hdr.timezone = 0x00000000;
898 file_hdr.sigfigs = 0x00000000;
899 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
900 file_hdr.link_type = 0x0065; /* 101 RAW IP */
902 write(fd, &file_hdr, sizeof(file_hdr));
906 fd = open(fname, O_WRONLY|O_APPEND, 0644);
911 static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
912 const struct sockaddr *addr,
913 enum swrap_packet_type type,
914 const void *buf, size_t len,
917 const struct sockaddr_in *src_addr;
918 const struct sockaddr_in *dest_addr;
919 unsigned long tcp_seq = 0;
920 unsigned long tcp_ack = 0;
921 unsigned char tcp_ctl = 0;
926 switch (si->family) {
934 case SWRAP_CONNECT_SEND:
935 if (si->type != SOCK_STREAM) return NULL;
937 src_addr = (const struct sockaddr_in *)si->myname;
938 dest_addr = (const struct sockaddr_in *)addr;
940 tcp_seq = si->io.pck_snd;
941 tcp_ack = si->io.pck_rcv;
942 tcp_ctl = 0x02; /* SYN */
948 case SWRAP_CONNECT_RECV:
949 if (si->type != SOCK_STREAM) return NULL;
951 dest_addr = (const struct sockaddr_in *)si->myname;
952 src_addr = (const struct sockaddr_in *)addr;
954 tcp_seq = si->io.pck_rcv;
955 tcp_ack = si->io.pck_snd;
956 tcp_ctl = 0x12; /** SYN,ACK */
962 case SWRAP_CONNECT_UNREACH:
963 if (si->type != SOCK_STREAM) return NULL;
965 dest_addr = (const struct sockaddr_in *)si->myname;
966 src_addr = (const struct sockaddr_in *)addr;
968 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
969 tcp_seq = si->io.pck_snd - 1;
970 tcp_ack = si->io.pck_rcv;
971 tcp_ctl = 0x02; /* SYN */
976 case SWRAP_CONNECT_ACK:
977 if (si->type != SOCK_STREAM) return NULL;
979 src_addr = (const struct sockaddr_in *)si->myname;
980 dest_addr = (const struct sockaddr_in *)addr;
982 tcp_seq = si->io.pck_snd;
983 tcp_ack = si->io.pck_rcv;
984 tcp_ctl = 0x10; /* ACK */
988 case SWRAP_ACCEPT_SEND:
989 if (si->type != SOCK_STREAM) return NULL;
991 dest_addr = (const struct sockaddr_in *)si->myname;
992 src_addr = (const struct sockaddr_in *)addr;
994 tcp_seq = si->io.pck_rcv;
995 tcp_ack = si->io.pck_snd;
996 tcp_ctl = 0x02; /* SYN */
1002 case SWRAP_ACCEPT_RECV:
1003 if (si->type != SOCK_STREAM) return NULL;
1005 src_addr = (const struct sockaddr_in *)si->myname;
1006 dest_addr = (const struct sockaddr_in *)addr;
1008 tcp_seq = si->io.pck_snd;
1009 tcp_ack = si->io.pck_rcv;
1010 tcp_ctl = 0x12; /* SYN,ACK */
1012 si->io.pck_snd += 1;
1016 case SWRAP_ACCEPT_ACK:
1017 if (si->type != SOCK_STREAM) return NULL;
1019 dest_addr = (const struct sockaddr_in *)si->myname;
1020 src_addr = (const struct sockaddr_in *)addr;
1022 tcp_seq = si->io.pck_rcv;
1023 tcp_ack = si->io.pck_snd;
1024 tcp_ctl = 0x10; /* ACK */
1029 src_addr = (const struct sockaddr_in *)si->myname;
1030 dest_addr = (const struct sockaddr_in *)si->peername;
1032 tcp_seq = si->io.pck_snd;
1033 tcp_ack = si->io.pck_rcv;
1034 tcp_ctl = 0x18; /* PSH,ACK */
1036 si->io.pck_snd += len;
1040 case SWRAP_SEND_RST:
1041 dest_addr = (const struct sockaddr_in *)si->myname;
1042 src_addr = (const struct sockaddr_in *)si->peername;
1044 if (si->type == SOCK_DGRAM) {
1045 return swrap_marshall_packet(si, si->peername,
1046 SWRAP_SENDTO_UNREACH,
1047 buf, len, packet_len);
1050 tcp_seq = si->io.pck_rcv;
1051 tcp_ack = si->io.pck_snd;
1052 tcp_ctl = 0x14; /** RST,ACK */
1056 case SWRAP_PENDING_RST:
1057 dest_addr = (const struct sockaddr_in *)si->myname;
1058 src_addr = (const struct sockaddr_in *)si->peername;
1060 if (si->type == SOCK_DGRAM) {
1064 tcp_seq = si->io.pck_rcv;
1065 tcp_ack = si->io.pck_snd;
1066 tcp_ctl = 0x14; /* RST,ACK */
1071 dest_addr = (const struct sockaddr_in *)si->myname;
1072 src_addr = (const struct sockaddr_in *)si->peername;
1074 tcp_seq = si->io.pck_rcv;
1075 tcp_ack = si->io.pck_snd;
1076 tcp_ctl = 0x18; /* PSH,ACK */
1078 si->io.pck_rcv += len;
1082 case SWRAP_RECV_RST:
1083 dest_addr = (const struct sockaddr_in *)si->myname;
1084 src_addr = (const struct sockaddr_in *)si->peername;
1086 if (si->type == SOCK_DGRAM) {
1090 tcp_seq = si->io.pck_rcv;
1091 tcp_ack = si->io.pck_snd;
1092 tcp_ctl = 0x14; /* RST,ACK */
1097 src_addr = (const struct sockaddr_in *)si->myname;
1098 dest_addr = (const struct sockaddr_in *)addr;
1100 si->io.pck_snd += len;
1104 case SWRAP_SENDTO_UNREACH:
1105 dest_addr = (const struct sockaddr_in *)si->myname;
1106 src_addr = (const struct sockaddr_in *)addr;
1112 case SWRAP_RECVFROM:
1113 dest_addr = (const struct sockaddr_in *)si->myname;
1114 src_addr = (const struct sockaddr_in *)addr;
1116 si->io.pck_rcv += len;
1120 case SWRAP_CLOSE_SEND:
1121 if (si->type != SOCK_STREAM) return NULL;
1123 src_addr = (const struct sockaddr_in *)si->myname;
1124 dest_addr = (const struct sockaddr_in *)si->peername;
1126 tcp_seq = si->io.pck_snd;
1127 tcp_ack = si->io.pck_rcv;
1128 tcp_ctl = 0x11; /* FIN, ACK */
1130 si->io.pck_snd += 1;
1134 case SWRAP_CLOSE_RECV:
1135 if (si->type != SOCK_STREAM) return NULL;
1137 dest_addr = (const struct sockaddr_in *)si->myname;
1138 src_addr = (const struct sockaddr_in *)si->peername;
1140 tcp_seq = si->io.pck_rcv;
1141 tcp_ack = si->io.pck_snd;
1142 tcp_ctl = 0x11; /* FIN,ACK */
1144 si->io.pck_rcv += 1;
1148 case SWRAP_CLOSE_ACK:
1149 if (si->type != SOCK_STREAM) return NULL;
1151 src_addr = (const struct sockaddr_in *)si->myname;
1152 dest_addr = (const struct sockaddr_in *)si->peername;
1154 tcp_seq = si->io.pck_snd;
1155 tcp_ack = si->io.pck_rcv;
1156 tcp_ctl = 0x10; /* ACK */
1163 swrapGetTimeOfDay(&tv);
1165 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1166 (const unsigned char *)buf, len,
1167 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1171 static void swrap_dump_packet(struct socket_info *si,
1172 const struct sockaddr *addr,
1173 enum swrap_packet_type type,
1174 const void *buf, size_t len)
1176 const char *file_name;
1177 struct swrap_packet *packet;
1178 size_t packet_len = 0;
1181 file_name = socket_wrapper_pcap_file();
1186 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1191 fd = swrap_get_pcap_fd(file_name);
1193 write(fd, packet, packet_len);
1199 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1201 struct socket_info *si;
1204 if (!socket_wrapper_dir()) {
1205 return real_socket(family, type, protocol);
1215 return real_socket(family, type, protocol);
1217 errno = EAFNOSUPPORT;
1227 errno = EPROTONOSUPPORT;
1235 if (type == SOCK_STREAM) {
1240 if (type == SOCK_DGRAM) {
1245 errno = EPROTONOSUPPORT;
1249 fd = real_socket(AF_UNIX, type, 0);
1251 if (fd == -1) return -1;
1253 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1255 si->family = family;
1257 si->protocol = protocol;
1260 SWRAP_DLIST_ADD(sockets, si);
1265 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1267 struct socket_info *parent_si, *child_si;
1269 struct sockaddr_un un_addr;
1270 socklen_t un_addrlen = sizeof(un_addr);
1271 struct sockaddr_un un_my_addr;
1272 socklen_t un_my_addrlen = sizeof(un_my_addr);
1273 struct sockaddr *my_addr;
1274 socklen_t my_addrlen, len;
1277 parent_si = find_socket_info(s);
1279 return real_accept(s, addr, addrlen);
1283 * assume out sockaddr have the same size as the in parent
1286 my_addrlen = socket_length(parent_si->family);
1287 if (my_addrlen <= 0) {
1292 my_addr = (struct sockaddr *)malloc(my_addrlen);
1293 if (my_addr == NULL) {
1297 memset(&un_addr, 0, sizeof(un_addr));
1298 memset(&un_my_addr, 0, sizeof(un_my_addr));
1300 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1309 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1310 parent_si->family, my_addr, &len);
1317 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1318 memset(child_si, 0, sizeof(*child_si));
1321 child_si->family = parent_si->family;
1322 child_si->type = parent_si->type;
1323 child_si->protocol = parent_si->protocol;
1324 child_si->bound = 1;
1325 child_si->is_server = 1;
1327 child_si->peername_len = len;
1328 child_si->peername = sockaddr_dup(my_addr, len);
1330 if (addr != NULL && addrlen != NULL) {
1332 if (*addrlen >= len)
1333 memcpy(addr, my_addr, len);
1337 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1345 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1346 child_si->family, my_addr, &len);
1354 child_si->myname_len = len;
1355 child_si->myname = sockaddr_dup(my_addr, len);
1358 SWRAP_DLIST_ADD(sockets, child_si);
1360 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1361 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1362 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1367 static int autobind_start_init;
1368 static int autobind_start;
1370 /* using sendto() or connect() on an unbound socket would give the
1371 recipient no way to reply, as unlike UDP and TCP, a unix domain
1372 socket can't auto-assign emphemeral port numbers, so we need to
1374 static int swrap_auto_bind(struct socket_info *si)
1376 struct sockaddr_un un_addr;
1383 if (autobind_start_init != 1) {
1384 autobind_start_init = 1;
1385 autobind_start = getpid();
1386 autobind_start %= 50000;
1387 autobind_start += 10000;
1390 un_addr.sun_family = AF_UNIX;
1392 switch (si->family) {
1394 struct sockaddr_in in;
1398 type = SOCKET_TYPE_CHAR_TCP;
1401 type = SOCKET_TYPE_CHAR_UDP;
1404 errno = ESOCKTNOSUPPORT;
1408 memset(&in, 0, sizeof(in));
1409 in.sin_family = AF_INET;
1410 in.sin_addr.s_addr = htonl(127<<24 |
1411 socket_wrapper_default_iface());
1413 si->myname_len = sizeof(in);
1414 si->myname = sockaddr_dup(&in, si->myname_len);
1419 struct sockaddr_in6 in6;
1423 type = SOCKET_TYPE_CHAR_TCP_V6;
1426 type = SOCKET_TYPE_CHAR_UDP_V6;
1429 errno = ESOCKTNOSUPPORT;
1433 memset(&in6, 0, sizeof(in6));
1434 in6.sin6_family = AF_INET6;
1435 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1436 si->myname_len = sizeof(in6);
1437 si->myname = sockaddr_dup(&in6, si->myname_len);
1442 errno = ESOCKTNOSUPPORT;
1446 if (autobind_start > 60000) {
1447 autobind_start = 10000;
1450 for (i=0;i<1000;i++) {
1451 port = autobind_start + i;
1452 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1453 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1454 type, socket_wrapper_default_iface(), port);
1455 if (stat(un_addr.sun_path, &st) == 0) continue;
1457 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1458 if (ret == -1) return ret;
1460 si->tmp_path = strdup(un_addr.sun_path);
1462 autobind_start = port + 1;
1470 set_port(si->family, port, si->myname);
1476 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1479 struct sockaddr_un un_addr;
1480 struct socket_info *si = find_socket_info(s);
1483 return real_connect(s, serv_addr, addrlen);
1486 if (si->bound == 0) {
1487 ret = swrap_auto_bind(si);
1488 if (ret == -1) return -1;
1491 if (si->family != serv_addr->sa_family) {
1496 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1497 if (ret == -1) return -1;
1499 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1501 ret = real_connect(s, (struct sockaddr *)&un_addr,
1502 sizeof(struct sockaddr_un));
1504 /* to give better errors */
1505 if (ret == -1 && errno == ENOENT) {
1506 errno = EHOSTUNREACH;
1510 si->peername_len = addrlen;
1511 si->peername = sockaddr_dup(serv_addr, addrlen);
1513 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1514 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1516 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1522 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1525 struct sockaddr_un un_addr;
1526 struct socket_info *si = find_socket_info(s);
1529 return real_bind(s, myaddr, addrlen);
1532 si->myname_len = addrlen;
1533 si->myname = sockaddr_dup(myaddr, addrlen);
1535 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1536 if (ret == -1) return -1;
1538 unlink(un_addr.sun_path);
1540 ret = real_bind(s, (struct sockaddr *)&un_addr,
1541 sizeof(struct sockaddr_un));
1550 _PUBLIC_ int swrap_listen(int s, int backlog)
1553 struct socket_info *si = find_socket_info(s);
1556 return real_listen(s, backlog);
1559 ret = real_listen(s, backlog);
1564 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1566 struct socket_info *si = find_socket_info(s);
1569 return real_getpeername(s, name, addrlen);
1578 memcpy(name, si->peername, si->peername_len);
1579 *addrlen = si->peername_len;
1584 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1586 struct socket_info *si = find_socket_info(s);
1589 return real_getsockname(s, name, addrlen);
1592 memcpy(name, si->myname, si->myname_len);
1593 *addrlen = si->myname_len;
1598 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1600 struct socket_info *si = find_socket_info(s);
1603 return real_getsockopt(s, level, optname, optval, optlen);
1606 if (level == SOL_SOCKET) {
1607 return real_getsockopt(s, level, optname, optval, optlen);
1610 errno = ENOPROTOOPT;
1614 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1616 struct socket_info *si = find_socket_info(s);
1619 return real_setsockopt(s, level, optname, optval, optlen);
1622 if (level == SOL_SOCKET) {
1623 return real_setsockopt(s, level, optname, optval, optlen);
1626 switch (si->family) {
1630 errno = ENOPROTOOPT;
1635 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1637 struct sockaddr_un un_addr;
1638 socklen_t un_addrlen = sizeof(un_addr);
1640 struct socket_info *si = find_socket_info(s);
1643 return real_recvfrom(s, buf, len, flags, from, fromlen);
1646 len = MIN(len, 1500);
1648 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1649 memset(&un_addr, 0, sizeof(un_addr));
1650 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1654 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1655 si->family, from, fromlen) == -1) {
1659 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1665 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1667 struct sockaddr_un un_addr;
1669 struct socket_info *si = find_socket_info(s);
1673 return real_sendto(s, buf, len, flags, to, tolen);
1676 len = MIN(len, 1500);
1680 ret = real_send(s, buf, len, flags);
1683 if (si->bound == 0) {
1684 ret = swrap_auto_bind(si);
1685 if (ret == -1) return -1;
1688 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1689 if (ret == -1) return -1;
1694 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1697 type = SOCKET_TYPE_CHAR_UDP;
1699 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1700 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1701 socket_wrapper_dir(), type, iface, prt);
1702 if (stat(un_addr.sun_path, &st) != 0) continue;
1704 /* ignore the any errors in broadcast sends */
1705 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1708 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1713 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1717 errno = EHOSTUNREACH;
1721 /* to give better errors */
1722 if (ret == -1 && errno == ENOENT) {
1723 errno = EHOSTUNREACH;
1727 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1728 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1730 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1736 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1739 struct socket_info *si = find_socket_info(s);
1743 return real_ioctl(s, r, p);
1746 ret = real_ioctl(s, r, p);
1750 value = *((int *)p);
1751 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1752 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1753 } else if (value == 0) { /* END OF FILE */
1754 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1762 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1765 struct socket_info *si = find_socket_info(s);
1768 return real_recv(s, buf, len, flags);
1771 len = MIN(len, 1500);
1773 ret = real_recv(s, buf, len, flags);
1774 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1775 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1776 } else if (ret == 0) { /* END OF FILE */
1777 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1779 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1786 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1789 struct socket_info *si = find_socket_info(s);
1792 return real_send(s, buf, len, flags);
1795 len = MIN(len, 1500);
1797 ret = real_send(s, buf, len, flags);
1800 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1801 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1803 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1809 _PUBLIC_ int swrap_close(int fd)
1811 struct socket_info *si = find_socket_info(fd);
1815 return real_close(fd);
1818 SWRAP_DLIST_REMOVE(sockets, si);
1820 if (si->myname && si->peername) {
1821 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1824 ret = real_close(fd);
1826 if (si->myname && si->peername) {
1827 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1828 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1831 if (si->path) free(si->path);
1832 if (si->myname) free(si->myname);
1833 if (si->peername) free(si->peername);
1835 unlink(si->tmp_path);