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) {
1207 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1209 struct socket_info *si;
1212 if (!socket_wrapper_dir()) {
1213 return real_socket(family, type, protocol);
1223 return real_socket(family, type, protocol);
1225 errno = EAFNOSUPPORT;
1235 errno = EPROTONOSUPPORT;
1243 if (type == SOCK_STREAM) {
1248 if (type == SOCK_DGRAM) {
1253 errno = EPROTONOSUPPORT;
1257 fd = real_socket(AF_UNIX, type, 0);
1259 if (fd == -1) return -1;
1261 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1263 si->family = family;
1265 si->protocol = protocol;
1268 SWRAP_DLIST_ADD(sockets, si);
1273 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1275 struct socket_info *parent_si, *child_si;
1277 struct sockaddr_un un_addr;
1278 socklen_t un_addrlen = sizeof(un_addr);
1279 struct sockaddr_un un_my_addr;
1280 socklen_t un_my_addrlen = sizeof(un_my_addr);
1281 struct sockaddr *my_addr;
1282 socklen_t my_addrlen, len;
1285 parent_si = find_socket_info(s);
1287 return real_accept(s, addr, addrlen);
1291 * assume out sockaddr have the same size as the in parent
1294 my_addrlen = socket_length(parent_si->family);
1295 if (my_addrlen <= 0) {
1300 my_addr = (struct sockaddr *)malloc(my_addrlen);
1301 if (my_addr == NULL) {
1305 memset(&un_addr, 0, sizeof(un_addr));
1306 memset(&un_my_addr, 0, sizeof(un_my_addr));
1308 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1317 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1318 parent_si->family, my_addr, &len);
1325 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1326 memset(child_si, 0, sizeof(*child_si));
1329 child_si->family = parent_si->family;
1330 child_si->type = parent_si->type;
1331 child_si->protocol = parent_si->protocol;
1332 child_si->bound = 1;
1333 child_si->is_server = 1;
1335 child_si->peername_len = len;
1336 child_si->peername = sockaddr_dup(my_addr, len);
1338 if (addr != NULL && addrlen != NULL) {
1340 if (*addrlen >= len)
1341 memcpy(addr, my_addr, len);
1345 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1353 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1354 child_si->family, my_addr, &len);
1362 child_si->myname_len = len;
1363 child_si->myname = sockaddr_dup(my_addr, len);
1366 SWRAP_DLIST_ADD(sockets, child_si);
1368 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1369 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1370 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1375 static int autobind_start_init;
1376 static int autobind_start;
1378 /* using sendto() or connect() on an unbound socket would give the
1379 recipient no way to reply, as unlike UDP and TCP, a unix domain
1380 socket can't auto-assign emphemeral port numbers, so we need to
1382 static int swrap_auto_bind(struct socket_info *si)
1384 struct sockaddr_un un_addr;
1391 if (autobind_start_init != 1) {
1392 autobind_start_init = 1;
1393 autobind_start = getpid();
1394 autobind_start %= 50000;
1395 autobind_start += 10000;
1398 un_addr.sun_family = AF_UNIX;
1400 switch (si->family) {
1402 struct sockaddr_in in;
1406 type = SOCKET_TYPE_CHAR_TCP;
1409 type = SOCKET_TYPE_CHAR_UDP;
1412 errno = ESOCKTNOSUPPORT;
1416 memset(&in, 0, sizeof(in));
1417 in.sin_family = AF_INET;
1418 in.sin_addr.s_addr = htonl(127<<24 |
1419 socket_wrapper_default_iface());
1421 si->myname_len = sizeof(in);
1422 si->myname = sockaddr_dup(&in, si->myname_len);
1427 struct sockaddr_in6 in6;
1431 type = SOCKET_TYPE_CHAR_TCP_V6;
1434 type = SOCKET_TYPE_CHAR_UDP_V6;
1437 errno = ESOCKTNOSUPPORT;
1441 memset(&in6, 0, sizeof(in6));
1442 in6.sin6_family = AF_INET6;
1443 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1444 si->myname_len = sizeof(in6);
1445 si->myname = sockaddr_dup(&in6, si->myname_len);
1450 errno = ESOCKTNOSUPPORT;
1454 if (autobind_start > 60000) {
1455 autobind_start = 10000;
1458 for (i=0;i<1000;i++) {
1459 port = autobind_start + i;
1460 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1461 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1462 type, socket_wrapper_default_iface(), port);
1463 if (stat(un_addr.sun_path, &st) == 0) continue;
1465 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1466 if (ret == -1) return ret;
1468 si->tmp_path = strdup(un_addr.sun_path);
1470 autobind_start = port + 1;
1478 set_port(si->family, port, si->myname);
1484 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1487 struct sockaddr_un un_addr;
1488 struct socket_info *si = find_socket_info(s);
1491 return real_connect(s, serv_addr, addrlen);
1494 if (si->bound == 0) {
1495 ret = swrap_auto_bind(si);
1496 if (ret == -1) return -1;
1499 if (si->family != serv_addr->sa_family) {
1504 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1505 if (ret == -1) return -1;
1507 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1509 ret = real_connect(s, (struct sockaddr *)&un_addr,
1510 sizeof(struct sockaddr_un));
1512 /* to give better errors */
1513 if (ret == -1 && errno == ENOENT) {
1514 errno = EHOSTUNREACH;
1518 si->peername_len = addrlen;
1519 si->peername = sockaddr_dup(serv_addr, addrlen);
1521 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1522 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1524 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1530 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1533 struct sockaddr_un un_addr;
1534 struct socket_info *si = find_socket_info(s);
1537 return real_bind(s, myaddr, addrlen);
1540 si->myname_len = addrlen;
1541 si->myname = sockaddr_dup(myaddr, addrlen);
1543 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1544 if (ret == -1) return -1;
1546 unlink(un_addr.sun_path);
1548 ret = real_bind(s, (struct sockaddr *)&un_addr,
1549 sizeof(struct sockaddr_un));
1558 _PUBLIC_ int swrap_listen(int s, int backlog)
1561 struct socket_info *si = find_socket_info(s);
1564 return real_listen(s, backlog);
1567 ret = real_listen(s, backlog);
1572 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1574 struct socket_info *si = find_socket_info(s);
1577 return real_getpeername(s, name, addrlen);
1586 memcpy(name, si->peername, si->peername_len);
1587 *addrlen = si->peername_len;
1592 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1594 struct socket_info *si = find_socket_info(s);
1597 return real_getsockname(s, name, addrlen);
1600 memcpy(name, si->myname, si->myname_len);
1601 *addrlen = si->myname_len;
1606 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1608 struct socket_info *si = find_socket_info(s);
1611 return real_getsockopt(s, level, optname, optval, optlen);
1614 if (level == SOL_SOCKET) {
1615 return real_getsockopt(s, level, optname, optval, optlen);
1618 errno = ENOPROTOOPT;
1622 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1624 struct socket_info *si = find_socket_info(s);
1627 return real_setsockopt(s, level, optname, optval, optlen);
1630 if (level == SOL_SOCKET) {
1631 return real_setsockopt(s, level, optname, optval, optlen);
1634 switch (si->family) {
1638 errno = ENOPROTOOPT;
1643 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1645 struct sockaddr_un un_addr;
1646 socklen_t un_addrlen = sizeof(un_addr);
1648 struct socket_info *si = find_socket_info(s);
1651 return real_recvfrom(s, buf, len, flags, from, fromlen);
1654 len = MIN(len, 1500);
1656 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1657 memset(&un_addr, 0, sizeof(un_addr));
1658 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1662 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1663 si->family, from, fromlen) == -1) {
1667 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1673 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1675 struct sockaddr_un un_addr;
1677 struct socket_info *si = find_socket_info(s);
1681 return real_sendto(s, buf, len, flags, to, tolen);
1684 len = MIN(len, 1500);
1688 ret = real_send(s, buf, len, flags);
1691 if (si->bound == 0) {
1692 ret = swrap_auto_bind(si);
1693 if (ret == -1) return -1;
1696 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1697 if (ret == -1) return -1;
1702 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1705 type = SOCKET_TYPE_CHAR_UDP;
1707 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1708 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1709 socket_wrapper_dir(), type, iface, prt);
1710 if (stat(un_addr.sun_path, &st) != 0) continue;
1712 /* ignore the any errors in broadcast sends */
1713 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1716 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1721 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1725 errno = EHOSTUNREACH;
1729 /* to give better errors */
1730 if (ret == -1 && errno == ENOENT) {
1731 errno = EHOSTUNREACH;
1735 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1736 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1738 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1744 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1747 struct socket_info *si = find_socket_info(s);
1751 return real_ioctl(s, r, p);
1754 ret = real_ioctl(s, r, p);
1758 value = *((int *)p);
1759 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1760 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1761 } else if (value == 0) { /* END OF FILE */
1762 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1770 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1773 struct socket_info *si = find_socket_info(s);
1776 return real_recv(s, buf, len, flags);
1779 len = MIN(len, 1500);
1781 ret = real_recv(s, buf, len, flags);
1782 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1783 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1784 } else if (ret == 0) { /* END OF FILE */
1785 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1787 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1794 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1797 struct socket_info *si = find_socket_info(s);
1800 return real_send(s, buf, len, flags);
1803 len = MIN(len, 1500);
1805 ret = real_send(s, buf, len, flags);
1808 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1809 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1811 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1817 _PUBLIC_ int swrap_close(int fd)
1819 struct socket_info *si = find_socket_info(fd);
1823 return real_close(fd);
1826 SWRAP_DLIST_REMOVE(sockets, si);
1828 if (si->myname && si->peername) {
1829 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1832 ret = real_close(fd);
1834 if (si->myname && si->peername) {
1835 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1836 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1839 if (si->path) free(si->path);
1840 if (si->myname) free(si->myname);
1841 if (si->peername) free(si->peername);
1843 unlink(si->tmp_path);