2 * Copyright (C) Jelmer Vernooij 2005 <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
46 #include "system/network.h"
47 #include "system/filesys.h"
59 #else /* _SAMBA_BUILD_ */
61 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <sys/ioctl.h>
66 #include <sys/filio.h>
69 #include <netinet/in.h>
70 #include <netinet/tcp.h>
81 #define SWRAP_DLIST_ADD(list,item) do { \
83 (item)->prev = NULL; \
84 (item)->next = NULL; \
87 (item)->prev = NULL; \
88 (item)->next = (list); \
89 (list)->prev = (item); \
94 #define SWRAP_DLIST_REMOVE(list,item) do { \
95 if ((list) == (item)) { \
96 (list) = (item)->next; \
98 (list)->prev = NULL; \
101 if ((item)->prev) { \
102 (item)->prev->next = (item)->next; \
104 if ((item)->next) { \
105 (item)->next->prev = (item)->prev; \
108 (item)->prev = NULL; \
109 (item)->next = NULL; \
112 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
114 #define REWRITE_CALLS
117 #define real_accept accept
118 #define real_connect connect
119 #define real_bind bind
120 #define real_listen listen
121 #define real_getpeername getpeername
122 #define real_getsockname getsockname
123 #define real_getsockopt getsockopt
124 #define real_setsockopt setsockopt
125 #define real_recvfrom recvfrom
126 #define real_sendto sendto
127 #define real_ioctl ioctl
128 #define real_recv recv
129 #define real_send send
130 #define real_socket socket
131 #define real_close close
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
140 /* we need to use a very terse format here as IRIX 6.4 silently
141 truncates names to 16 chars, so if we use a longer name then we
142 can't tell which port a packet came from with recvfrom()
144 with this format we have 8 chars left for the directory name
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
149 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
150 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
152 #define MAX_WRAPPED_INTERFACES 16
154 #define SW_IPV6_ADDRESS 1
156 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
158 struct sockaddr *ret = (struct sockaddr *)malloc(len);
159 memcpy(ret, data, len);
163 static void set_port(int family, int prt, struct sockaddr *addr)
167 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
171 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
177 static size_t socket_length(int family)
181 return sizeof(struct sockaddr_in);
184 return sizeof(struct sockaddr_in6);
206 struct sockaddr *myname;
207 socklen_t myname_len;
209 struct sockaddr *peername;
210 socklen_t peername_len;
213 unsigned long pck_snd;
214 unsigned long pck_rcv;
217 struct socket_info *prev, *next;
220 static struct socket_info *sockets;
223 const char *socket_wrapper_dir(void)
225 const char *s = getenv("SOCKET_WRAPPER_DIR");
229 if (strncmp(s, "./", 2) == 0) {
235 unsigned int socket_wrapper_default_iface(void)
237 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
240 if (sscanf(s, "%u", &iface) == 1) {
241 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
247 return 1;/* 127.0.0.1 */
250 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
257 p = strrchr(un->sun_path, '/');
258 if (p) p++; else p = un->sun_path;
260 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
265 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
276 case SOCKET_TYPE_CHAR_TCP:
277 case SOCKET_TYPE_CHAR_UDP: {
278 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
280 if ((*len) < sizeof(*in2)) {
285 memset(in2, 0, sizeof(*in2));
286 in2->sin_family = AF_INET;
287 in2->sin_addr.s_addr = htonl((127<<24) | iface);
288 in2->sin_port = htons(prt);
294 case SOCKET_TYPE_CHAR_TCP_V6:
295 case SOCKET_TYPE_CHAR_UDP_V6: {
296 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
298 if ((*len) < sizeof(*in2)) {
303 memset(in2, 0, sizeof(*in2));
304 in2->sin6_family = AF_INET6;
305 in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
306 in2->sin6_port = htons(prt);
320 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
328 if (bcast) *bcast = 0;
330 switch (si->family) {
332 const struct sockaddr_in *in =
333 (const struct sockaddr_in *)inaddr;
334 unsigned int addr = ntohl(in->sin_addr.s_addr);
341 u_type = SOCKET_TYPE_CHAR_TCP;
344 u_type = SOCKET_TYPE_CHAR_UDP;
345 a_type = SOCKET_TYPE_CHAR_UDP;
346 b_type = SOCKET_TYPE_CHAR_UDP;
350 prt = ntohs(in->sin_port);
351 if (a_type && addr == 0xFFFFFFFF) {
352 /* 255.255.255.255 only udp */
355 iface = socket_wrapper_default_iface();
356 } else if (b_type && addr == 0x7FFFFFFF) {
357 /* 127.255.255.255 only udp */
360 iface = socket_wrapper_default_iface();
361 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
365 iface = (addr & 0x000000FF);
370 if (bcast) *bcast = is_bcast;
375 const struct sockaddr_in6 *in =
376 (const struct sockaddr_in6 *)inaddr;
380 type = SOCKET_TYPE_CHAR_TCP_V6;
383 type = SOCKET_TYPE_CHAR_UDP_V6;
387 /* XXX no multicast/broadcast */
389 prt = ntohs(in->sin6_port);
390 iface = SW_IPV6_ADDRESS;
406 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
407 socket_wrapper_dir());
408 /* the caller need to do more processing */
412 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
413 socket_wrapper_dir(), type, iface, prt);
418 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
427 if (bcast) *bcast = 0;
429 switch (si->family) {
431 const struct sockaddr_in *in =
432 (const struct sockaddr_in *)inaddr;
433 unsigned int addr = ntohl(in->sin_addr.s_addr);
439 prt = ntohs(in->sin_port);
443 u_type = SOCKET_TYPE_CHAR_TCP;
444 d_type = SOCKET_TYPE_CHAR_TCP;
447 u_type = SOCKET_TYPE_CHAR_UDP;
448 d_type = SOCKET_TYPE_CHAR_UDP;
449 a_type = SOCKET_TYPE_CHAR_UDP;
450 b_type = SOCKET_TYPE_CHAR_UDP;
458 iface = socket_wrapper_default_iface();
459 } else if (a_type && addr == 0xFFFFFFFF) {
460 /* 255.255.255.255 only udp */
463 iface = socket_wrapper_default_iface();
464 } else if (b_type && addr == 0x7FFFFFFF) {
465 /* 127.255.255.255 only udp */
468 iface = socket_wrapper_default_iface();
469 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
473 iface = (addr & 0x000000FF);
475 errno = EADDRNOTAVAIL;
482 const struct sockaddr_in6 *in =
483 (const struct sockaddr_in6 *)inaddr;
487 type = SOCKET_TYPE_CHAR_TCP_V6;
490 type = SOCKET_TYPE_CHAR_UDP_V6;
494 /* XXX no multicast/broadcast */
496 prt = ntohs(in->sin6_port);
497 iface = SW_IPV6_ADDRESS;
508 if (bcast) *bcast = is_bcast;
511 /* handle auto-allocation of ephemeral ports */
512 for (prt = 5001; prt < 10000; prt++) {
513 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
514 socket_wrapper_dir(), type, iface, prt);
515 if (stat(un->sun_path, &st) == 0) continue;
517 set_port(si->family, prt, si->myname);
526 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
527 socket_wrapper_dir(), type, iface, prt);
531 static struct socket_info *find_socket_info(int fd)
533 struct socket_info *i;
534 for (i = sockets; i; i = i->next) {
542 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
543 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
548 out_addr->sun_family = AF_UNIX;
550 switch (in_addr->sa_family) {
560 errno = ESOCKTNOSUPPORT;
564 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
566 return convert_in_un_remote(si, in_addr, out_addr, bcast);
572 errno = EAFNOSUPPORT;
576 static int sockaddr_convert_from_un(const struct socket_info *si,
577 const struct sockaddr_un *in_addr,
578 socklen_t un_addrlen,
580 struct sockaddr *out_addr,
581 socklen_t *out_addrlen)
583 if (out_addr == NULL || out_addrlen == NULL)
586 if (un_addrlen == 0) {
601 errno = ESOCKTNOSUPPORT;
604 return convert_un_in(in_addr, out_addr, out_addrlen);
609 errno = EAFNOSUPPORT;
613 enum swrap_packet_type {
615 SWRAP_CONNECT_UNREACH,
623 SWRAP_SENDTO_UNREACH,
634 struct swrap_file_hdr {
636 unsigned short version_major;
637 unsigned short version_minor;
639 unsigned long sigfigs;
640 unsigned long frame_max_len;
641 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
642 unsigned long link_type;
644 #define SWRAP_FILE_HDR_SIZE 24
646 struct swrap_packet {
648 unsigned long seconds;
649 unsigned long micro_seconds;
650 unsigned long recorded_length;
651 unsigned long full_length;
653 #define SWRAP_PACKET__FRAME_SIZE 16
657 unsigned char ver_hdrlen;
659 unsigned short packet_length;
660 unsigned short identification;
662 unsigned char fragment;
664 unsigned char protocol;
665 unsigned short hdr_checksum;
666 unsigned long src_addr;
667 unsigned long dest_addr;
669 #define SWRAP_PACKET__IP_HDR_SIZE 20
673 unsigned short source_port;
674 unsigned short dest_port;
675 unsigned long seq_num;
676 unsigned long ack_num;
677 unsigned char hdr_length;
678 unsigned char control;
679 unsigned short window;
680 unsigned short checksum;
683 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
685 unsigned short source_port;
686 unsigned short dest_port;
687 unsigned short length;
688 unsigned short checksum;
690 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
694 unsigned short checksum;
695 unsigned long unused;
697 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
701 #define SWRAP_PACKET_SIZE 56
703 static const char *socket_wrapper_pcap_file(void)
705 static int initialized = 0;
706 static const char *s = NULL;
707 static const struct swrap_file_hdr h;
708 static const struct swrap_packet p;
710 if (initialized == 1) {
716 * TODO: don't use the structs use plain buffer offsets
717 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
719 * for now make sure we disable PCAP support
720 * if the struct has alignment!
722 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
725 if (sizeof(p) != SWRAP_PACKET_SIZE) {
728 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
731 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
734 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
737 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
740 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
744 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
748 if (strncmp(s, "./", 2) == 0) {
754 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
755 const struct sockaddr_in *src_addr,
756 const struct sockaddr_in *dest_addr,
758 const unsigned char *payload,
760 unsigned long tcp_seq,
761 unsigned long tcp_ack,
762 unsigned char tcp_ctl,
766 struct swrap_packet *ret;
767 struct swrap_packet *packet;
770 size_t nonwire_len = sizeof(packet->frame);
771 size_t wire_hdr_len = 0;
773 size_t icmp_hdr_len = 0;
774 size_t icmp_truncate_len = 0;
775 unsigned char protocol = 0, icmp_protocol = 0;
776 unsigned short src_port = src_addr->sin_port;
777 unsigned short dest_port = dest_addr->sin_port;
779 switch (socket_type) {
781 protocol = 0x06; /* TCP */
782 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
783 wire_len = wire_hdr_len + payload_len;
787 protocol = 0x11; /* UDP */
788 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
789 wire_len = wire_hdr_len + payload_len;
797 icmp_protocol = protocol;
798 protocol = 0x01; /* ICMP */
799 if (wire_len > 64 ) {
800 icmp_truncate_len = wire_len - 64;
802 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
803 wire_hdr_len += icmp_hdr_len;
804 wire_len += icmp_hdr_len;
807 packet_len = nonwire_len + wire_len;
808 alloc_len = packet_len;
809 if (alloc_len < sizeof(struct swrap_packet)) {
810 alloc_len = sizeof(struct swrap_packet);
812 ret = (struct swrap_packet *)malloc(alloc_len);
813 if (!ret) return NULL;
817 packet->frame.seconds = tval->tv_sec;
818 packet->frame.micro_seconds = tval->tv_usec;
819 packet->frame.recorded_length = wire_len - icmp_truncate_len;
820 packet->frame.full_length = wire_len - icmp_truncate_len;
822 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
823 packet->ip.hdr.tos = 0x00;
824 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
825 packet->ip.hdr.identification = htons(0xFFFF);
826 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
827 packet->ip.hdr.fragment = htons(0x0000);
828 packet->ip.hdr.ttl = 0xFF;
829 packet->ip.hdr.protocol = protocol;
830 packet->ip.hdr.hdr_checksum = htons(0x0000);
831 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
832 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
835 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
836 packet->ip.p.icmp.code = 0x01; /* host unreachable */
837 packet->ip.p.icmp.checksum = htons(0x0000);
838 packet->ip.p.icmp.unused = htonl(0x00000000);
840 /* set the ip header in the ICMP payload */
841 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
842 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
843 packet->ip.hdr.tos = 0x00;
844 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
845 packet->ip.hdr.identification = htons(0xFFFF);
846 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
847 packet->ip.hdr.fragment = htons(0x0000);
848 packet->ip.hdr.ttl = 0xFF;
849 packet->ip.hdr.protocol = icmp_protocol;
850 packet->ip.hdr.hdr_checksum = htons(0x0000);
851 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
852 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
854 src_port = dest_addr->sin_port;
855 dest_port = src_addr->sin_port;
858 switch (socket_type) {
860 packet->ip.p.tcp.source_port = src_port;
861 packet->ip.p.tcp.dest_port = dest_port;
862 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
863 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
864 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
865 packet->ip.p.tcp.control = tcp_ctl;
866 packet->ip.p.tcp.window = htons(0x7FFF);
867 packet->ip.p.tcp.checksum = htons(0x0000);
868 packet->ip.p.tcp.urg = htons(0x0000);
873 packet->ip.p.udp.source_port = src_addr->sin_port;
874 packet->ip.p.udp.dest_port = dest_addr->sin_port;
875 packet->ip.p.udp.length = htons(8 + payload_len);
876 packet->ip.p.udp.checksum = htons(0x0000);
881 if (payload && payload_len > 0) {
882 unsigned char *p = (unsigned char *)ret;
885 memcpy(p, payload, payload_len);
888 *_packet_len = packet_len - icmp_truncate_len;
892 static int swrap_get_pcap_fd(const char *fname)
896 if (fd != -1) return fd;
898 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
900 struct swrap_file_hdr file_hdr;
901 file_hdr.magic = 0xA1B2C3D4;
902 file_hdr.version_major = 0x0002;
903 file_hdr.version_minor = 0x0004;
904 file_hdr.timezone = 0x00000000;
905 file_hdr.sigfigs = 0x00000000;
906 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
907 file_hdr.link_type = 0x0065; /* 101 RAW IP */
909 write(fd, &file_hdr, sizeof(file_hdr));
913 fd = open(fname, O_WRONLY|O_APPEND, 0644);
918 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
919 enum swrap_packet_type type,
920 const void *buf, size_t len)
922 const struct sockaddr_in *src_addr;
923 const struct sockaddr_in *dest_addr;
924 const char *file_name;
925 unsigned long tcp_seq = 0;
926 unsigned long tcp_ack = 0;
927 unsigned char tcp_ctl = 0;
930 struct swrap_packet *packet;
931 size_t packet_len = 0;
934 file_name = socket_wrapper_pcap_file();
939 switch (si->family) {
950 case SWRAP_CONNECT_SEND:
951 if (si->type != SOCK_STREAM) return;
953 src_addr = (const struct sockaddr_in *)si->myname;
954 dest_addr = (const struct sockaddr_in *)addr;
956 tcp_seq = si->io.pck_snd;
957 tcp_ack = si->io.pck_rcv;
958 tcp_ctl = 0x02; /* SYN */
964 case SWRAP_CONNECT_RECV:
965 if (si->type != SOCK_STREAM) return;
967 dest_addr = (const struct sockaddr_in *)si->myname;
968 src_addr = (const struct sockaddr_in *)addr;
970 tcp_seq = si->io.pck_rcv;
971 tcp_ack = si->io.pck_snd;
972 tcp_ctl = 0x12; /** SYN,ACK */
978 case SWRAP_CONNECT_UNREACH:
979 if (si->type != SOCK_STREAM) return;
981 dest_addr = (const struct sockaddr_in *)si->myname;
982 src_addr = (const struct sockaddr_in *)addr;
984 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
985 tcp_seq = si->io.pck_snd - 1;
986 tcp_ack = si->io.pck_rcv;
987 tcp_ctl = 0x02; /* SYN */
992 case SWRAP_CONNECT_ACK:
993 if (si->type != SOCK_STREAM) return;
995 src_addr = (const struct sockaddr_in *)si->myname;
996 dest_addr = (const struct sockaddr_in *)addr;
998 tcp_seq = si->io.pck_snd;
999 tcp_ack = si->io.pck_rcv;
1000 tcp_ctl = 0x10; /* ACK */
1004 case SWRAP_ACCEPT_SEND:
1005 if (si->type != SOCK_STREAM) return;
1007 dest_addr = (const struct sockaddr_in *)si->myname;
1008 src_addr = (const struct sockaddr_in *)addr;
1010 tcp_seq = si->io.pck_rcv;
1011 tcp_ack = si->io.pck_snd;
1012 tcp_ctl = 0x02; /* SYN */
1014 si->io.pck_rcv += 1;
1018 case SWRAP_ACCEPT_RECV:
1019 if (si->type != SOCK_STREAM) return;
1021 src_addr = (const struct sockaddr_in *)si->myname;
1022 dest_addr = (const struct sockaddr_in *)addr;
1024 tcp_seq = si->io.pck_snd;
1025 tcp_ack = si->io.pck_rcv;
1026 tcp_ctl = 0x12; /* SYN,ACK */
1028 si->io.pck_snd += 1;
1032 case SWRAP_ACCEPT_ACK:
1033 if (si->type != SOCK_STREAM) return;
1035 dest_addr = (const struct sockaddr_in *)si->myname;
1036 src_addr = (const struct sockaddr_in *)addr;
1038 tcp_seq = si->io.pck_rcv;
1039 tcp_ack = si->io.pck_snd;
1040 tcp_ctl = 0x10; /* ACK */
1045 src_addr = (const struct sockaddr_in *)si->myname;
1046 dest_addr = (const struct sockaddr_in *)si->peername;
1048 tcp_seq = si->io.pck_snd;
1049 tcp_ack = si->io.pck_rcv;
1050 tcp_ctl = 0x18; /* PSH,ACK */
1052 si->io.pck_snd += len;
1056 case SWRAP_SEND_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) {
1061 swrap_dump_packet(si, si->peername,
1062 SWRAP_SENDTO_UNREACH,
1067 tcp_seq = si->io.pck_rcv;
1068 tcp_ack = si->io.pck_snd;
1069 tcp_ctl = 0x14; /** RST,ACK */
1073 case SWRAP_PENDING_RST:
1074 dest_addr = (const struct sockaddr_in *)si->myname;
1075 src_addr = (const struct sockaddr_in *)si->peername;
1077 if (si->type == SOCK_DGRAM) {
1081 tcp_seq = si->io.pck_rcv;
1082 tcp_ack = si->io.pck_snd;
1083 tcp_ctl = 0x14; /* RST,ACK */
1088 dest_addr = (const struct sockaddr_in *)si->myname;
1089 src_addr = (const struct sockaddr_in *)si->peername;
1091 tcp_seq = si->io.pck_rcv;
1092 tcp_ack = si->io.pck_snd;
1093 tcp_ctl = 0x18; /* PSH,ACK */
1095 si->io.pck_rcv += len;
1099 case SWRAP_RECV_RST:
1100 dest_addr = (const struct sockaddr_in *)si->myname;
1101 src_addr = (const struct sockaddr_in *)si->peername;
1103 if (si->type == SOCK_DGRAM) {
1107 tcp_seq = si->io.pck_rcv;
1108 tcp_ack = si->io.pck_snd;
1109 tcp_ctl = 0x14; /* RST,ACK */
1114 src_addr = (const struct sockaddr_in *)si->myname;
1115 dest_addr = (const struct sockaddr_in *)addr;
1117 si->io.pck_snd += len;
1121 case SWRAP_SENDTO_UNREACH:
1122 dest_addr = (const struct sockaddr_in *)si->myname;
1123 src_addr = (const struct sockaddr_in *)addr;
1129 case SWRAP_RECVFROM:
1130 dest_addr = (const struct sockaddr_in *)si->myname;
1131 src_addr = (const struct sockaddr_in *)addr;
1133 si->io.pck_rcv += len;
1137 case SWRAP_CLOSE_SEND:
1138 if (si->type != SOCK_STREAM) return;
1140 src_addr = (const struct sockaddr_in *)si->myname;
1141 dest_addr = (const struct sockaddr_in *)si->peername;
1143 tcp_seq = si->io.pck_snd;
1144 tcp_ack = si->io.pck_rcv;
1145 tcp_ctl = 0x11; /* FIN, ACK */
1147 si->io.pck_snd += 1;
1151 case SWRAP_CLOSE_RECV:
1152 if (si->type != SOCK_STREAM) return;
1154 dest_addr = (const struct sockaddr_in *)si->myname;
1155 src_addr = (const struct sockaddr_in *)si->peername;
1157 tcp_seq = si->io.pck_rcv;
1158 tcp_ack = si->io.pck_snd;
1159 tcp_ctl = 0x11; /* FIN,ACK */
1161 si->io.pck_rcv += 1;
1165 case SWRAP_CLOSE_ACK:
1166 if (si->type != SOCK_STREAM) return;
1168 src_addr = (const struct sockaddr_in *)si->myname;
1169 dest_addr = (const struct sockaddr_in *)si->peername;
1171 tcp_seq = si->io.pck_snd;
1172 tcp_ack = si->io.pck_rcv;
1173 tcp_ctl = 0x10; /* ACK */
1180 swrapGetTimeOfDay(&tv);
1182 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1183 (const unsigned char *)buf, len,
1184 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1190 fd = swrap_get_pcap_fd(file_name);
1192 write(fd, packet, packet_len);
1198 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1200 struct socket_info *si;
1203 if (!socket_wrapper_dir()) {
1204 return real_socket(family, type, protocol);
1214 return real_socket(family, type, protocol);
1216 errno = EAFNOSUPPORT;
1226 errno = EPROTONOSUPPORT;
1234 if (type == SOCK_STREAM) {
1239 if (type == SOCK_DGRAM) {
1244 errno = EPROTONOSUPPORT;
1248 fd = real_socket(AF_UNIX, type, 0);
1250 if (fd == -1) return -1;
1252 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1254 si->family = family;
1256 si->protocol = protocol;
1259 SWRAP_DLIST_ADD(sockets, si);
1264 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1266 struct socket_info *parent_si, *child_si;
1268 struct sockaddr_un un_addr;
1269 socklen_t un_addrlen = sizeof(un_addr);
1270 struct sockaddr_un un_my_addr;
1271 socklen_t un_my_addrlen = sizeof(un_my_addr);
1272 struct sockaddr *my_addr;
1273 socklen_t my_addrlen, len;
1276 parent_si = find_socket_info(s);
1278 return real_accept(s, addr, addrlen);
1282 * assume out sockaddr have the same size as the in parent
1285 my_addrlen = socket_length(parent_si->family);
1286 if (my_addrlen <= 0) {
1291 my_addr = malloc(my_addrlen);
1292 if (my_addr == NULL) {
1296 memset(&un_addr, 0, sizeof(un_addr));
1297 memset(&un_my_addr, 0, sizeof(un_my_addr));
1299 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1308 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1309 parent_si->family, my_addr, &len);
1316 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1317 memset(child_si, 0, sizeof(*child_si));
1320 child_si->family = parent_si->family;
1321 child_si->type = parent_si->type;
1322 child_si->protocol = parent_si->protocol;
1323 child_si->bound = 1;
1324 child_si->is_server = 1;
1326 child_si->peername_len = len;
1327 child_si->peername = sockaddr_dup(my_addr, len);
1329 if (addr != NULL && addrlen != NULL) {
1331 if (*addrlen >= len)
1332 memcpy(addr, my_addr, len);
1336 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1344 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1345 child_si->family, my_addr, &len);
1353 child_si->myname_len = len;
1354 child_si->myname = sockaddr_dup(my_addr, len);
1357 SWRAP_DLIST_ADD(sockets, child_si);
1359 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1360 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1361 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1366 static int autobind_start_init;
1367 static int autobind_start;
1369 /* using sendto() or connect() on an unbound socket would give the
1370 recipient no way to reply, as unlike UDP and TCP, a unix domain
1371 socket can't auto-assign emphemeral port numbers, so we need to
1373 static int swrap_auto_bind(struct socket_info *si)
1375 struct sockaddr_un un_addr;
1382 if (autobind_start_init != 1) {
1383 autobind_start_init = 1;
1384 autobind_start = getpid();
1385 autobind_start %= 50000;
1386 autobind_start += 10000;
1389 un_addr.sun_family = AF_UNIX;
1391 switch (si->family) {
1393 struct sockaddr_in in;
1397 type = SOCKET_TYPE_CHAR_TCP;
1400 type = SOCKET_TYPE_CHAR_UDP;
1403 errno = ESOCKTNOSUPPORT;
1407 memset(&in, 0, sizeof(in));
1408 in.sin_family = AF_INET;
1409 in.sin_addr.s_addr = htonl(127<<24 |
1410 socket_wrapper_default_iface());
1412 si->myname_len = sizeof(in);
1413 si->myname = sockaddr_dup(&in, si->myname_len);
1418 struct sockaddr_in6 in6;
1422 type = SOCKET_TYPE_CHAR_TCP_V6;
1425 type = SOCKET_TYPE_CHAR_UDP_V6;
1428 errno = ESOCKTNOSUPPORT;
1432 memset(&in6, 0, sizeof(in6));
1433 in6.sin6_family = AF_INET6;
1434 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1435 si->myname_len = sizeof(in6);
1436 si->myname = sockaddr_dup(&in6, si->myname_len);
1441 errno = ESOCKTNOSUPPORT;
1445 if (autobind_start > 60000) {
1446 autobind_start = 10000;
1449 for (i=0;i<1000;i++) {
1450 port = autobind_start + i;
1451 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1452 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1453 type, socket_wrapper_default_iface(), port);
1454 if (stat(un_addr.sun_path, &st) == 0) continue;
1456 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1457 if (ret == -1) return ret;
1459 si->tmp_path = strdup(un_addr.sun_path);
1461 autobind_start = port + 1;
1469 set_port(si->family, port, si->myname);
1475 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1478 struct sockaddr_un un_addr;
1479 struct socket_info *si = find_socket_info(s);
1482 return real_connect(s, serv_addr, addrlen);
1485 if (si->bound == 0) {
1486 ret = swrap_auto_bind(si);
1487 if (ret == -1) return -1;
1490 if (si->family != serv_addr->sa_family) {
1495 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1496 if (ret == -1) return -1;
1498 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1500 ret = real_connect(s, (struct sockaddr *)&un_addr,
1501 sizeof(struct sockaddr_un));
1503 /* to give better errors */
1504 if (ret == -1 && errno == ENOENT) {
1505 errno = EHOSTUNREACH;
1509 si->peername_len = addrlen;
1510 si->peername = sockaddr_dup(serv_addr, addrlen);
1512 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1513 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1515 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1521 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1524 struct sockaddr_un un_addr;
1525 struct socket_info *si = find_socket_info(s);
1528 return real_bind(s, myaddr, addrlen);
1531 si->myname_len = addrlen;
1532 si->myname = sockaddr_dup(myaddr, addrlen);
1534 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1535 if (ret == -1) return -1;
1537 unlink(un_addr.sun_path);
1539 ret = real_bind(s, (struct sockaddr *)&un_addr,
1540 sizeof(struct sockaddr_un));
1549 _PUBLIC_ int swrap_listen(int s, int backlog)
1552 struct socket_info *si = find_socket_info(s);
1555 return real_listen(s, backlog);
1558 ret = real_listen(s, backlog);
1563 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1565 struct socket_info *si = find_socket_info(s);
1568 return real_getpeername(s, name, addrlen);
1577 memcpy(name, si->peername, si->peername_len);
1578 *addrlen = si->peername_len;
1583 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1585 struct socket_info *si = find_socket_info(s);
1588 return real_getsockname(s, name, addrlen);
1591 memcpy(name, si->myname, si->myname_len);
1592 *addrlen = si->myname_len;
1597 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1599 struct socket_info *si = find_socket_info(s);
1602 return real_getsockopt(s, level, optname, optval, optlen);
1605 if (level == SOL_SOCKET) {
1606 return real_getsockopt(s, level, optname, optval, optlen);
1609 errno = ENOPROTOOPT;
1613 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1615 struct socket_info *si = find_socket_info(s);
1618 return real_setsockopt(s, level, optname, optval, optlen);
1621 if (level == SOL_SOCKET) {
1622 return real_setsockopt(s, level, optname, optval, optlen);
1625 switch (si->family) {
1629 errno = ENOPROTOOPT;
1634 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1636 struct sockaddr_un un_addr;
1637 socklen_t un_addrlen = sizeof(un_addr);
1639 struct socket_info *si = find_socket_info(s);
1642 return real_recvfrom(s, buf, len, flags, from, fromlen);
1645 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1646 memset(&un_addr, 0, sizeof(un_addr));
1647 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1651 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1652 si->family, from, fromlen) == -1) {
1656 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1662 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1664 struct sockaddr_un un_addr;
1666 struct socket_info *si = find_socket_info(s);
1670 return real_sendto(s, buf, len, flags, to, tolen);
1675 ret = real_send(s, buf, len, flags);
1678 if (si->bound == 0) {
1679 ret = swrap_auto_bind(si);
1680 if (ret == -1) return -1;
1683 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1684 if (ret == -1) return -1;
1689 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1692 type = SOCKET_TYPE_CHAR_UDP;
1694 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1695 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1696 socket_wrapper_dir(), type, iface, prt);
1697 if (stat(un_addr.sun_path, &st) != 0) continue;
1699 /* ignore the any errors in broadcast sends */
1700 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1703 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1708 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1712 errno = EHOSTUNREACH;
1716 /* to give better errors */
1717 if (ret == -1 && errno == ENOENT) {
1718 errno = EHOSTUNREACH;
1722 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1723 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1725 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1731 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1734 struct socket_info *si = find_socket_info(s);
1738 return real_ioctl(s, r, p);
1741 ret = real_ioctl(s, r, p);
1745 value = *((int *)p);
1746 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1747 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1748 } else if (value == 0) { /* END OF FILE */
1749 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1757 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1760 struct socket_info *si = find_socket_info(s);
1763 return real_recv(s, buf, len, flags);
1766 ret = real_recv(s, buf, len, flags);
1767 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1768 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1769 } else if (ret == 0) { /* END OF FILE */
1770 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1772 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1779 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1782 struct socket_info *si = find_socket_info(s);
1785 return real_send(s, buf, len, flags);
1788 ret = real_send(s, buf, len, flags);
1791 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1792 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1794 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1800 _PUBLIC_ int swrap_close(int fd)
1802 struct socket_info *si = find_socket_info(fd);
1806 return real_close(fd);
1809 SWRAP_DLIST_REMOVE(sockets, si);
1811 if (si->myname && si->peername) {
1812 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1815 ret = real_close(fd);
1817 if (si->myname && si->peername) {
1818 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1819 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1822 if (si->path) free(si->path);
1823 if (si->myname) free(si->myname);
1824 if (si->peername) free(si->peername);
1826 unlink(si->tmp_path);