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_seqno,
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_seqno);
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 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
909 fd = open(fname, O_WRONLY|O_APPEND, 0644);
914 static struct swrap_packet *swrap_marshall_packet(struct socket_info *si,
915 const struct sockaddr *addr,
916 enum swrap_packet_type type,
917 const void *buf, size_t len,
920 const struct sockaddr_in *src_addr;
921 const struct sockaddr_in *dest_addr;
922 unsigned long tcp_seqno = 0;
923 unsigned long tcp_ack = 0;
924 unsigned char tcp_ctl = 0;
929 switch (si->family) {
937 case SWRAP_CONNECT_SEND:
938 if (si->type != SOCK_STREAM) return NULL;
940 src_addr = (const struct sockaddr_in *)si->myname;
941 dest_addr = (const struct sockaddr_in *)addr;
943 tcp_seqno = si->io.pck_snd;
944 tcp_ack = si->io.pck_rcv;
945 tcp_ctl = 0x02; /* SYN */
951 case SWRAP_CONNECT_RECV:
952 if (si->type != SOCK_STREAM) return NULL;
954 dest_addr = (const struct sockaddr_in *)si->myname;
955 src_addr = (const struct sockaddr_in *)addr;
957 tcp_seqno = si->io.pck_rcv;
958 tcp_ack = si->io.pck_snd;
959 tcp_ctl = 0x12; /** SYN,ACK */
965 case SWRAP_CONNECT_UNREACH:
966 if (si->type != SOCK_STREAM) return NULL;
968 dest_addr = (const struct sockaddr_in *)si->myname;
969 src_addr = (const struct sockaddr_in *)addr;
971 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
972 tcp_seqno = si->io.pck_snd - 1;
973 tcp_ack = si->io.pck_rcv;
974 tcp_ctl = 0x02; /* SYN */
979 case SWRAP_CONNECT_ACK:
980 if (si->type != SOCK_STREAM) return NULL;
982 src_addr = (const struct sockaddr_in *)si->myname;
983 dest_addr = (const struct sockaddr_in *)addr;
985 tcp_seqno = si->io.pck_snd;
986 tcp_ack = si->io.pck_rcv;
987 tcp_ctl = 0x10; /* ACK */
991 case SWRAP_ACCEPT_SEND:
992 if (si->type != SOCK_STREAM) return NULL;
994 dest_addr = (const struct sockaddr_in *)si->myname;
995 src_addr = (const struct sockaddr_in *)addr;
997 tcp_seqno = si->io.pck_rcv;
998 tcp_ack = si->io.pck_snd;
999 tcp_ctl = 0x02; /* SYN */
1001 si->io.pck_rcv += 1;
1005 case SWRAP_ACCEPT_RECV:
1006 if (si->type != SOCK_STREAM) return NULL;
1008 src_addr = (const struct sockaddr_in *)si->myname;
1009 dest_addr = (const struct sockaddr_in *)addr;
1011 tcp_seqno = si->io.pck_snd;
1012 tcp_ack = si->io.pck_rcv;
1013 tcp_ctl = 0x12; /* SYN,ACK */
1015 si->io.pck_snd += 1;
1019 case SWRAP_ACCEPT_ACK:
1020 if (si->type != SOCK_STREAM) return NULL;
1022 dest_addr = (const struct sockaddr_in *)si->myname;
1023 src_addr = (const struct sockaddr_in *)addr;
1025 tcp_seqno = si->io.pck_rcv;
1026 tcp_ack = si->io.pck_snd;
1027 tcp_ctl = 0x10; /* ACK */
1032 src_addr = (const struct sockaddr_in *)si->myname;
1033 dest_addr = (const struct sockaddr_in *)si->peername;
1035 tcp_seqno = si->io.pck_snd;
1036 tcp_ack = si->io.pck_rcv;
1037 tcp_ctl = 0x18; /* PSH,ACK */
1039 si->io.pck_snd += len;
1043 case SWRAP_SEND_RST:
1044 dest_addr = (const struct sockaddr_in *)si->myname;
1045 src_addr = (const struct sockaddr_in *)si->peername;
1047 if (si->type == SOCK_DGRAM) {
1048 return swrap_marshall_packet(si, si->peername,
1049 SWRAP_SENDTO_UNREACH,
1050 buf, len, packet_len);
1053 tcp_seqno = si->io.pck_rcv;
1054 tcp_ack = si->io.pck_snd;
1055 tcp_ctl = 0x14; /** RST,ACK */
1059 case SWRAP_PENDING_RST:
1060 dest_addr = (const struct sockaddr_in *)si->myname;
1061 src_addr = (const struct sockaddr_in *)si->peername;
1063 if (si->type == SOCK_DGRAM) {
1067 tcp_seqno = si->io.pck_rcv;
1068 tcp_ack = si->io.pck_snd;
1069 tcp_ctl = 0x14; /* RST,ACK */
1074 dest_addr = (const struct sockaddr_in *)si->myname;
1075 src_addr = (const struct sockaddr_in *)si->peername;
1077 tcp_seqno = si->io.pck_rcv;
1078 tcp_ack = si->io.pck_snd;
1079 tcp_ctl = 0x18; /* PSH,ACK */
1081 si->io.pck_rcv += len;
1085 case SWRAP_RECV_RST:
1086 dest_addr = (const struct sockaddr_in *)si->myname;
1087 src_addr = (const struct sockaddr_in *)si->peername;
1089 if (si->type == SOCK_DGRAM) {
1093 tcp_seqno = si->io.pck_rcv;
1094 tcp_ack = si->io.pck_snd;
1095 tcp_ctl = 0x14; /* RST,ACK */
1100 src_addr = (const struct sockaddr_in *)si->myname;
1101 dest_addr = (const struct sockaddr_in *)addr;
1103 si->io.pck_snd += len;
1107 case SWRAP_SENDTO_UNREACH:
1108 dest_addr = (const struct sockaddr_in *)si->myname;
1109 src_addr = (const struct sockaddr_in *)addr;
1115 case SWRAP_RECVFROM:
1116 dest_addr = (const struct sockaddr_in *)si->myname;
1117 src_addr = (const struct sockaddr_in *)addr;
1119 si->io.pck_rcv += len;
1123 case SWRAP_CLOSE_SEND:
1124 if (si->type != SOCK_STREAM) return NULL;
1126 src_addr = (const struct sockaddr_in *)si->myname;
1127 dest_addr = (const struct sockaddr_in *)si->peername;
1129 tcp_seqno = si->io.pck_snd;
1130 tcp_ack = si->io.pck_rcv;
1131 tcp_ctl = 0x11; /* FIN, ACK */
1133 si->io.pck_snd += 1;
1137 case SWRAP_CLOSE_RECV:
1138 if (si->type != SOCK_STREAM) return NULL;
1140 dest_addr = (const struct sockaddr_in *)si->myname;
1141 src_addr = (const struct sockaddr_in *)si->peername;
1143 tcp_seqno = si->io.pck_rcv;
1144 tcp_ack = si->io.pck_snd;
1145 tcp_ctl = 0x11; /* FIN,ACK */
1147 si->io.pck_rcv += 1;
1151 case SWRAP_CLOSE_ACK:
1152 if (si->type != SOCK_STREAM) return NULL;
1154 src_addr = (const struct sockaddr_in *)si->myname;
1155 dest_addr = (const struct sockaddr_in *)si->peername;
1157 tcp_seqno = si->io.pck_snd;
1158 tcp_ack = si->io.pck_rcv;
1159 tcp_ctl = 0x10; /* ACK */
1166 swrapGetTimeOfDay(&tv);
1168 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1169 (const unsigned char *)buf, len,
1170 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1174 static void swrap_dump_packet(struct socket_info *si,
1175 const struct sockaddr *addr,
1176 enum swrap_packet_type type,
1177 const void *buf, size_t len)
1179 const char *file_name;
1180 struct swrap_packet *packet;
1181 size_t packet_len = 0;
1184 file_name = socket_wrapper_pcap_file();
1189 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1194 fd = swrap_get_pcap_fd(file_name);
1196 if (write(fd, packet, packet_len) != packet_len) {
1205 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1207 struct socket_info *si;
1210 if (!socket_wrapper_dir()) {
1211 return real_socket(family, type, protocol);
1221 return real_socket(family, type, protocol);
1223 errno = EAFNOSUPPORT;
1233 errno = EPROTONOSUPPORT;
1241 if (type == SOCK_STREAM) {
1246 if (type == SOCK_DGRAM) {
1251 errno = EPROTONOSUPPORT;
1255 fd = real_socket(AF_UNIX, type, 0);
1257 if (fd == -1) return -1;
1259 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1261 si->family = family;
1263 si->protocol = protocol;
1266 SWRAP_DLIST_ADD(sockets, si);
1271 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1273 struct socket_info *parent_si, *child_si;
1275 struct sockaddr_un un_addr;
1276 socklen_t un_addrlen = sizeof(un_addr);
1277 struct sockaddr_un un_my_addr;
1278 socklen_t un_my_addrlen = sizeof(un_my_addr);
1279 struct sockaddr *my_addr;
1280 socklen_t my_addrlen, len;
1283 parent_si = find_socket_info(s);
1285 return real_accept(s, addr, addrlen);
1289 * assume out sockaddr have the same size as the in parent
1292 my_addrlen = socket_length(parent_si->family);
1293 if (my_addrlen <= 0) {
1298 my_addr = (struct sockaddr *)malloc(my_addrlen);
1299 if (my_addr == NULL) {
1303 memset(&un_addr, 0, sizeof(un_addr));
1304 memset(&un_my_addr, 0, sizeof(un_my_addr));
1306 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1315 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1316 parent_si->family, my_addr, &len);
1323 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1324 memset(child_si, 0, sizeof(*child_si));
1327 child_si->family = parent_si->family;
1328 child_si->type = parent_si->type;
1329 child_si->protocol = parent_si->protocol;
1330 child_si->bound = 1;
1331 child_si->is_server = 1;
1333 child_si->peername_len = len;
1334 child_si->peername = sockaddr_dup(my_addr, len);
1336 if (addr != NULL && addrlen != NULL) {
1338 if (*addrlen >= len)
1339 memcpy(addr, my_addr, len);
1343 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1351 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1352 child_si->family, my_addr, &len);
1360 child_si->myname_len = len;
1361 child_si->myname = sockaddr_dup(my_addr, len);
1364 SWRAP_DLIST_ADD(sockets, child_si);
1366 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1367 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1368 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1373 static int autobind_start_init;
1374 static int autobind_start;
1376 /* using sendto() or connect() on an unbound socket would give the
1377 recipient no way to reply, as unlike UDP and TCP, a unix domain
1378 socket can't auto-assign emphemeral port numbers, so we need to
1380 static int swrap_auto_bind(struct socket_info *si)
1382 struct sockaddr_un un_addr;
1389 if (autobind_start_init != 1) {
1390 autobind_start_init = 1;
1391 autobind_start = getpid();
1392 autobind_start %= 50000;
1393 autobind_start += 10000;
1396 un_addr.sun_family = AF_UNIX;
1398 switch (si->family) {
1400 struct sockaddr_in in;
1404 type = SOCKET_TYPE_CHAR_TCP;
1407 type = SOCKET_TYPE_CHAR_UDP;
1410 errno = ESOCKTNOSUPPORT;
1414 memset(&in, 0, sizeof(in));
1415 in.sin_family = AF_INET;
1416 in.sin_addr.s_addr = htonl(127<<24 |
1417 socket_wrapper_default_iface());
1419 si->myname_len = sizeof(in);
1420 si->myname = sockaddr_dup(&in, si->myname_len);
1425 struct sockaddr_in6 in6;
1429 type = SOCKET_TYPE_CHAR_TCP_V6;
1432 type = SOCKET_TYPE_CHAR_UDP_V6;
1435 errno = ESOCKTNOSUPPORT;
1439 memset(&in6, 0, sizeof(in6));
1440 in6.sin6_family = AF_INET6;
1441 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1442 si->myname_len = sizeof(in6);
1443 si->myname = sockaddr_dup(&in6, si->myname_len);
1448 errno = ESOCKTNOSUPPORT;
1452 if (autobind_start > 60000) {
1453 autobind_start = 10000;
1456 for (i=0;i<1000;i++) {
1457 port = autobind_start + i;
1458 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1459 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1460 type, socket_wrapper_default_iface(), port);
1461 if (stat(un_addr.sun_path, &st) == 0) continue;
1463 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1464 if (ret == -1) return ret;
1466 si->tmp_path = strdup(un_addr.sun_path);
1468 autobind_start = port + 1;
1476 set_port(si->family, port, si->myname);
1482 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1485 struct sockaddr_un un_addr;
1486 struct socket_info *si = find_socket_info(s);
1489 return real_connect(s, serv_addr, addrlen);
1492 if (si->bound == 0) {
1493 ret = swrap_auto_bind(si);
1494 if (ret == -1) return -1;
1497 if (si->family != serv_addr->sa_family) {
1502 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1503 if (ret == -1) return -1;
1505 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1507 ret = real_connect(s, (struct sockaddr *)&un_addr,
1508 sizeof(struct sockaddr_un));
1510 /* to give better errors */
1511 if (ret == -1 && errno == ENOENT) {
1512 errno = EHOSTUNREACH;
1516 si->peername_len = addrlen;
1517 si->peername = sockaddr_dup(serv_addr, addrlen);
1519 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1520 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1522 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1528 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1531 struct sockaddr_un un_addr;
1532 struct socket_info *si = find_socket_info(s);
1535 return real_bind(s, myaddr, addrlen);
1538 si->myname_len = addrlen;
1539 si->myname = sockaddr_dup(myaddr, addrlen);
1541 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1542 if (ret == -1) return -1;
1544 unlink(un_addr.sun_path);
1546 ret = real_bind(s, (struct sockaddr *)&un_addr,
1547 sizeof(struct sockaddr_un));
1556 _PUBLIC_ int swrap_listen(int s, int backlog)
1559 struct socket_info *si = find_socket_info(s);
1562 return real_listen(s, backlog);
1565 ret = real_listen(s, backlog);
1570 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1572 struct socket_info *si = find_socket_info(s);
1575 return real_getpeername(s, name, addrlen);
1584 memcpy(name, si->peername, si->peername_len);
1585 *addrlen = si->peername_len;
1590 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1592 struct socket_info *si = find_socket_info(s);
1595 return real_getsockname(s, name, addrlen);
1598 memcpy(name, si->myname, si->myname_len);
1599 *addrlen = si->myname_len;
1604 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1606 struct socket_info *si = find_socket_info(s);
1609 return real_getsockopt(s, level, optname, optval, optlen);
1612 if (level == SOL_SOCKET) {
1613 return real_getsockopt(s, level, optname, optval, optlen);
1616 errno = ENOPROTOOPT;
1620 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1622 struct socket_info *si = find_socket_info(s);
1625 return real_setsockopt(s, level, optname, optval, optlen);
1628 if (level == SOL_SOCKET) {
1629 return real_setsockopt(s, level, optname, optval, optlen);
1632 switch (si->family) {
1636 errno = ENOPROTOOPT;
1641 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1643 struct sockaddr_un un_addr;
1644 socklen_t un_addrlen = sizeof(un_addr);
1646 struct socket_info *si = find_socket_info(s);
1649 return real_recvfrom(s, buf, len, flags, from, fromlen);
1652 len = MIN(len, 1500);
1654 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1655 memset(&un_addr, 0, sizeof(un_addr));
1656 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1660 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1661 si->family, from, fromlen) == -1) {
1665 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1671 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1673 struct sockaddr_un un_addr;
1675 struct socket_info *si = find_socket_info(s);
1679 return real_sendto(s, buf, len, flags, to, tolen);
1682 len = MIN(len, 1500);
1686 ret = real_send(s, buf, len, flags);
1689 if (si->bound == 0) {
1690 ret = swrap_auto_bind(si);
1691 if (ret == -1) return -1;
1694 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1695 if (ret == -1) return -1;
1700 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1703 type = SOCKET_TYPE_CHAR_UDP;
1705 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1706 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1707 socket_wrapper_dir(), type, iface, prt);
1708 if (stat(un_addr.sun_path, &st) != 0) continue;
1710 /* ignore the any errors in broadcast sends */
1711 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1714 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1719 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1723 errno = EHOSTUNREACH;
1727 /* to give better errors */
1728 if (ret == -1 && errno == ENOENT) {
1729 errno = EHOSTUNREACH;
1733 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1734 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1736 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1742 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1745 struct socket_info *si = find_socket_info(s);
1749 return real_ioctl(s, r, p);
1752 ret = real_ioctl(s, r, p);
1756 value = *((int *)p);
1757 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1758 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1759 } else if (value == 0) { /* END OF FILE */
1760 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1768 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1771 struct socket_info *si = find_socket_info(s);
1774 return real_recv(s, buf, len, flags);
1777 len = MIN(len, 1500);
1779 ret = real_recv(s, buf, len, flags);
1780 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1781 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1782 } else if (ret == 0) { /* END OF FILE */
1783 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1784 } else if (ret > 0) {
1785 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1792 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1795 struct socket_info *si = find_socket_info(s);
1798 return real_send(s, buf, len, flags);
1801 len = MIN(len, 1500);
1803 ret = real_send(s, buf, len, flags);
1806 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1807 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1809 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1815 _PUBLIC_ int swrap_close(int fd)
1817 struct socket_info *si = find_socket_info(fd);
1821 return real_close(fd);
1824 SWRAP_DLIST_REMOVE(sockets, si);
1826 if (si->myname && si->peername) {
1827 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1830 ret = real_close(fd);
1832 if (si->myname && si->peername) {
1833 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1834 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1837 if (si->path) free(si->path);
1838 if (si->myname) free(si->myname);
1839 if (si->peername) free(si->peername);
1841 unlink(si->tmp_path);