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
42 #define SOCKET_WRAPPER_NOT_REPLACE
47 #include "system/network.h"
48 #include "system/filesys.h"
60 #else /* _SAMBA_BUILD_ */
63 #undef SOCKET_WRAPPER_REPLACE
65 #include <sys/types.h>
66 #ifdef TIME_WITH_SYS_TIME
69 #elif defined(HAVE_SYS_TIME_H)
75 #include <sys/socket.h>
76 #include <sys/ioctl.h>
77 #ifdef HAVE_SYS_FILIO_H
78 #include <sys/filio.h>
82 #include <netinet/in.h>
83 #include <netinet/tcp.h>
91 #include "socket_wrapper.h"
93 #define HAVE_GETTIMEOFDAY_TZ 1
99 #define SWRAP_DLIST_ADD(list,item) do { \
101 (item)->prev = NULL; \
102 (item)->next = NULL; \
105 (item)->prev = NULL; \
106 (item)->next = (list); \
107 (list)->prev = (item); \
112 #define SWRAP_DLIST_REMOVE(list,item) do { \
113 if ((list) == (item)) { \
114 (list) = (item)->next; \
116 (list)->prev = NULL; \
119 if ((item)->prev) { \
120 (item)->prev->next = (item)->next; \
122 if ((item)->next) { \
123 (item)->next->prev = (item)->prev; \
126 (item)->prev = NULL; \
127 (item)->next = NULL; \
130 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
132 #define REWRITE_CALLS
135 #define real_accept accept
136 #define real_connect connect
137 #define real_bind bind
138 #define real_listen listen
139 #define real_getpeername getpeername
140 #define real_getsockname getsockname
141 #define real_getsockopt getsockopt
142 #define real_setsockopt setsockopt
143 #define real_recvfrom recvfrom
144 #define real_sendto sendto
145 #define real_ioctl ioctl
146 #define real_recv recv
147 #define real_send send
148 #define real_socket socket
149 #define real_close close
151 #define real_dup2 dup2
154 #ifdef HAVE_GETTIMEOFDAY_TZ
155 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
160 /* we need to use a very terse format here as IRIX 6.4 silently
161 truncates names to 16 chars, so if we use a longer name then we
162 can't tell which port a packet came from with recvfrom()
164 with this format we have 8 chars left for the directory name
166 #define SOCKET_FORMAT "%c%02X%04X"
167 #define SOCKET_TYPE_CHAR_TCP 'T'
168 #define SOCKET_TYPE_CHAR_UDP 'U'
169 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
170 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
172 #define MAX_WRAPPED_INTERFACES 16
174 #define SW_IPV6_ADDRESS 1
176 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
178 struct sockaddr *ret = (struct sockaddr *)malloc(len);
179 memcpy(ret, data, len);
183 static void set_port(int family, int prt, struct sockaddr *addr)
187 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
191 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
197 static int socket_length(int family)
201 return sizeof(struct sockaddr_in);
204 return sizeof(struct sockaddr_in6);
226 struct sockaddr *myname;
227 socklen_t myname_len;
229 struct sockaddr *peername;
230 socklen_t peername_len;
233 unsigned long pck_snd;
234 unsigned long pck_rcv;
237 struct socket_info *prev, *next;
240 static struct socket_info *sockets;
243 static const char *socket_wrapper_dir(void)
245 const char *s = getenv("SOCKET_WRAPPER_DIR");
249 if (strncmp(s, "./", 2) == 0) {
255 static unsigned int socket_wrapper_default_iface(void)
257 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
260 if (sscanf(s, "%u", &iface) == 1) {
261 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
267 return 1;/* 127.0.0.1 */
270 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
277 p = strrchr(un->sun_path, '/');
278 if (p) p++; else p = un->sun_path;
280 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
285 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
296 case SOCKET_TYPE_CHAR_TCP:
297 case SOCKET_TYPE_CHAR_UDP: {
298 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
300 if ((*len) < sizeof(*in2)) {
305 memset(in2, 0, sizeof(*in2));
306 in2->sin_family = AF_INET;
307 in2->sin_addr.s_addr = htonl((127<<24) | iface);
308 in2->sin_port = htons(prt);
314 case SOCKET_TYPE_CHAR_TCP_V6:
315 case SOCKET_TYPE_CHAR_UDP_V6: {
316 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
318 if ((*len) < sizeof(*in2)) {
323 memset(in2, 0, sizeof(*in2));
324 in2->sin6_family = AF_INET6;
325 in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
326 in2->sin6_port = htons(prt);
340 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
348 if (bcast) *bcast = 0;
350 switch (si->family) {
352 const struct sockaddr_in *in =
353 (const struct sockaddr_in *)inaddr;
354 unsigned int addr = ntohl(in->sin_addr.s_addr);
361 u_type = SOCKET_TYPE_CHAR_TCP;
364 u_type = SOCKET_TYPE_CHAR_UDP;
365 a_type = SOCKET_TYPE_CHAR_UDP;
366 b_type = SOCKET_TYPE_CHAR_UDP;
370 prt = ntohs(in->sin_port);
371 if (a_type && addr == 0xFFFFFFFF) {
372 /* 255.255.255.255 only udp */
375 iface = socket_wrapper_default_iface();
376 } else if (b_type && addr == 0x7FFFFFFF) {
377 /* 127.255.255.255 only udp */
380 iface = socket_wrapper_default_iface();
381 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
385 iface = (addr & 0x000000FF);
390 if (bcast) *bcast = is_bcast;
395 const struct sockaddr_in6 *in =
396 (const struct sockaddr_in6 *)inaddr;
400 type = SOCKET_TYPE_CHAR_TCP_V6;
403 type = SOCKET_TYPE_CHAR_UDP_V6;
407 /* XXX no multicast/broadcast */
409 prt = ntohs(in->sin6_port);
410 iface = SW_IPV6_ADDRESS;
426 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
427 socket_wrapper_dir());
428 /* the caller need to do more processing */
432 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
433 socket_wrapper_dir(), type, iface, prt);
438 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
447 if (bcast) *bcast = 0;
449 switch (si->family) {
451 const struct sockaddr_in *in =
452 (const struct sockaddr_in *)inaddr;
453 unsigned int addr = ntohl(in->sin_addr.s_addr);
459 prt = ntohs(in->sin_port);
463 u_type = SOCKET_TYPE_CHAR_TCP;
464 d_type = SOCKET_TYPE_CHAR_TCP;
467 u_type = SOCKET_TYPE_CHAR_UDP;
468 d_type = SOCKET_TYPE_CHAR_UDP;
469 a_type = SOCKET_TYPE_CHAR_UDP;
470 b_type = SOCKET_TYPE_CHAR_UDP;
478 iface = socket_wrapper_default_iface();
479 } else if (a_type && addr == 0xFFFFFFFF) {
480 /* 255.255.255.255 only udp */
483 iface = socket_wrapper_default_iface();
484 } else if (b_type && addr == 0x7FFFFFFF) {
485 /* 127.255.255.255 only udp */
488 iface = socket_wrapper_default_iface();
489 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
493 iface = (addr & 0x000000FF);
495 errno = EADDRNOTAVAIL;
502 const struct sockaddr_in6 *in =
503 (const struct sockaddr_in6 *)inaddr;
507 type = SOCKET_TYPE_CHAR_TCP_V6;
510 type = SOCKET_TYPE_CHAR_UDP_V6;
514 /* XXX no multicast/broadcast */
516 prt = ntohs(in->sin6_port);
517 iface = SW_IPV6_ADDRESS;
528 if (bcast) *bcast = is_bcast;
531 /* handle auto-allocation of ephemeral ports */
532 for (prt = 5001; prt < 10000; prt++) {
533 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
534 socket_wrapper_dir(), type, iface, prt);
535 if (stat(un->sun_path, &st) == 0) continue;
537 set_port(si->family, prt, si->myname);
541 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
542 socket_wrapper_dir(), type, iface, prt);
546 static struct socket_info *find_socket_info(int fd)
548 struct socket_info *i;
549 for (i = sockets; i; i = i->next) {
557 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
558 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
563 out_addr->sun_family = AF_UNIX;
565 switch (in_addr->sa_family) {
575 errno = ESOCKTNOSUPPORT;
579 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
581 return convert_in_un_remote(si, in_addr, out_addr, bcast);
587 errno = EAFNOSUPPORT;
591 static int sockaddr_convert_from_un(const struct socket_info *si,
592 const struct sockaddr_un *in_addr,
593 socklen_t un_addrlen,
595 struct sockaddr *out_addr,
596 socklen_t *out_addrlen)
598 if (out_addr == NULL || out_addrlen == NULL)
601 if (un_addrlen == 0) {
616 errno = ESOCKTNOSUPPORT;
619 return convert_un_in(in_addr, out_addr, out_addrlen);
624 errno = EAFNOSUPPORT;
628 enum swrap_packet_type {
630 SWRAP_CONNECT_UNREACH,
638 SWRAP_SENDTO_UNREACH,
649 struct swrap_file_hdr {
651 unsigned short version_major;
652 unsigned short version_minor;
654 unsigned long sigfigs;
655 unsigned long frame_max_len;
656 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
657 unsigned long link_type;
659 #define SWRAP_FILE_HDR_SIZE 24
661 struct swrap_packet {
663 unsigned long seconds;
664 unsigned long micro_seconds;
665 unsigned long recorded_length;
666 unsigned long full_length;
668 #define SWRAP_PACKET__FRAME_SIZE 16
672 unsigned char ver_hdrlen;
674 unsigned short packet_length;
675 unsigned short identification;
677 unsigned char fragment;
679 unsigned char protocol;
680 unsigned short hdr_checksum;
681 unsigned long src_addr;
682 unsigned long dest_addr;
684 #define SWRAP_PACKET__IP_HDR_SIZE 20
688 unsigned short source_port;
689 unsigned short dest_port;
690 unsigned long seq_num;
691 unsigned long ack_num;
692 unsigned char hdr_length;
693 unsigned char control;
694 unsigned short window;
695 unsigned short checksum;
698 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
700 unsigned short source_port;
701 unsigned short dest_port;
702 unsigned short length;
703 unsigned short checksum;
705 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
709 unsigned short checksum;
710 unsigned long unused;
712 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
716 #define SWRAP_PACKET_SIZE 56
718 static const char *socket_wrapper_pcap_file(void)
720 static int initialized = 0;
721 static const char *s = NULL;
722 static const struct swrap_file_hdr h;
723 static const struct swrap_packet p;
725 if (initialized == 1) {
731 * TODO: don't use the structs use plain buffer offsets
732 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
734 * for now make sure we disable PCAP support
735 * if the struct has alignment!
737 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
740 if (sizeof(p) != SWRAP_PACKET_SIZE) {
743 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
746 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
749 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
752 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
755 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
759 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
763 if (strncmp(s, "./", 2) == 0) {
769 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
770 const struct sockaddr_in *src_addr,
771 const struct sockaddr_in *dest_addr,
773 const unsigned char *payload,
775 unsigned long tcp_seq,
776 unsigned long tcp_ack,
777 unsigned char tcp_ctl,
781 struct swrap_packet *ret;
782 struct swrap_packet *packet;
785 size_t nonwire_len = sizeof(packet->frame);
786 size_t wire_hdr_len = 0;
788 size_t icmp_hdr_len = 0;
789 size_t icmp_truncate_len = 0;
790 unsigned char protocol = 0, icmp_protocol = 0;
791 unsigned short src_port = src_addr->sin_port;
792 unsigned short dest_port = dest_addr->sin_port;
794 switch (socket_type) {
796 protocol = 0x06; /* TCP */
797 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
798 wire_len = wire_hdr_len + payload_len;
802 protocol = 0x11; /* UDP */
803 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
804 wire_len = wire_hdr_len + payload_len;
809 icmp_protocol = protocol;
810 protocol = 0x01; /* ICMP */
811 if (wire_len > 64 ) {
812 icmp_truncate_len = wire_len - 64;
814 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
815 wire_hdr_len += icmp_hdr_len;
816 wire_len += icmp_hdr_len;
819 packet_len = nonwire_len + wire_len;
820 alloc_len = packet_len;
821 if (alloc_len < sizeof(struct swrap_packet)) {
822 alloc_len = sizeof(struct swrap_packet);
824 ret = (struct swrap_packet *)malloc(alloc_len);
825 if (!ret) return NULL;
829 packet->frame.seconds = tval->tv_sec;
830 packet->frame.micro_seconds = tval->tv_usec;
831 packet->frame.recorded_length = wire_len - icmp_truncate_len;
832 packet->frame.full_length = wire_len - icmp_truncate_len;
834 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
835 packet->ip.hdr.tos = 0x00;
836 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
837 packet->ip.hdr.identification = htons(0xFFFF);
838 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
839 packet->ip.hdr.fragment = htons(0x0000);
840 packet->ip.hdr.ttl = 0xFF;
841 packet->ip.hdr.protocol = protocol;
842 packet->ip.hdr.hdr_checksum = htons(0x0000);
843 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
844 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
847 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
848 packet->ip.p.icmp.code = 0x01; /* host unreachable */
849 packet->ip.p.icmp.checksum = htons(0x0000);
850 packet->ip.p.icmp.unused = htonl(0x00000000);
852 /* set the ip header in the ICMP payload */
853 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
854 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
855 packet->ip.hdr.tos = 0x00;
856 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
857 packet->ip.hdr.identification = htons(0xFFFF);
858 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
859 packet->ip.hdr.fragment = htons(0x0000);
860 packet->ip.hdr.ttl = 0xFF;
861 packet->ip.hdr.protocol = icmp_protocol;
862 packet->ip.hdr.hdr_checksum = htons(0x0000);
863 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
864 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
866 src_port = dest_addr->sin_port;
867 dest_port = src_addr->sin_port;
870 switch (socket_type) {
872 packet->ip.p.tcp.source_port = src_port;
873 packet->ip.p.tcp.dest_port = dest_port;
874 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
875 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
876 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
877 packet->ip.p.tcp.control = tcp_ctl;
878 packet->ip.p.tcp.window = htons(0x7FFF);
879 packet->ip.p.tcp.checksum = htons(0x0000);
880 packet->ip.p.tcp.urg = htons(0x0000);
885 packet->ip.p.udp.source_port = src_addr->sin_port;
886 packet->ip.p.udp.dest_port = dest_addr->sin_port;
887 packet->ip.p.udp.length = htons(8 + payload_len);
888 packet->ip.p.udp.checksum = htons(0x0000);
893 if (payload && payload_len > 0) {
894 unsigned char *p = (unsigned char *)ret;
897 memcpy(p, payload, payload_len);
900 *_packet_len = packet_len - icmp_truncate_len;
904 static int swrap_get_pcap_fd(const char *fname)
908 if (fd != -1) return fd;
910 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
912 struct swrap_file_hdr file_hdr;
913 file_hdr.magic = 0xA1B2C3D4;
914 file_hdr.version_major = 0x0002;
915 file_hdr.version_minor = 0x0004;
916 file_hdr.timezone = 0x00000000;
917 file_hdr.sigfigs = 0x00000000;
918 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
919 file_hdr.link_type = 0x0065; /* 101 RAW IP */
921 write(fd, &file_hdr, sizeof(file_hdr));
925 fd = open(fname, O_WRONLY|O_APPEND, 0644);
930 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
931 enum swrap_packet_type type,
932 const void *buf, size_t len)
934 const struct sockaddr_in *src_addr;
935 const struct sockaddr_in *dest_addr;
936 const char *file_name;
937 unsigned long tcp_seq = 0;
938 unsigned long tcp_ack = 0;
939 unsigned char tcp_ctl = 0;
942 struct swrap_packet *packet;
943 size_t packet_len = 0;
946 file_name = socket_wrapper_pcap_file();
951 switch (si->family) {
962 case SWRAP_CONNECT_SEND:
963 if (si->type != SOCK_STREAM) return;
965 src_addr = (const struct sockaddr_in *)si->myname;
966 dest_addr = (const struct sockaddr_in *)addr;
968 tcp_seq = si->io.pck_snd;
969 tcp_ack = si->io.pck_rcv;
970 tcp_ctl = 0x02; /* SYN */
976 case SWRAP_CONNECT_RECV:
977 if (si->type != SOCK_STREAM) return;
979 dest_addr = (const struct sockaddr_in *)si->myname;
980 src_addr = (const struct sockaddr_in *)addr;
982 tcp_seq = si->io.pck_rcv;
983 tcp_ack = si->io.pck_snd;
984 tcp_ctl = 0x12; /** SYN,ACK */
990 case SWRAP_CONNECT_UNREACH:
991 if (si->type != SOCK_STREAM) return;
993 dest_addr = (const struct sockaddr_in *)si->myname;
994 src_addr = (const struct sockaddr_in *)addr;
996 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
997 tcp_seq = si->io.pck_snd - 1;
998 tcp_ack = si->io.pck_rcv;
999 tcp_ctl = 0x02; /* SYN */
1004 case SWRAP_CONNECT_ACK:
1005 if (si->type != SOCK_STREAM) return;
1007 src_addr = (const struct sockaddr_in *)si->myname;
1008 dest_addr = (const struct sockaddr_in *)addr;
1010 tcp_seq = si->io.pck_snd;
1011 tcp_ack = si->io.pck_rcv;
1012 tcp_ctl = 0x10; /* ACK */
1016 case SWRAP_ACCEPT_SEND:
1017 if (si->type != SOCK_STREAM) return;
1019 dest_addr = (const struct sockaddr_in *)si->myname;
1020 src_addr = (const struct sockaddr_in *)addr;
1022 tcp_seq = si->io.pck_rcv;
1023 tcp_ack = si->io.pck_snd;
1024 tcp_ctl = 0x02; /* SYN */
1026 si->io.pck_rcv += 1;
1030 case SWRAP_ACCEPT_RECV:
1031 if (si->type != SOCK_STREAM) return;
1033 src_addr = (const struct sockaddr_in *)si->myname;
1034 dest_addr = (const struct sockaddr_in *)addr;
1036 tcp_seq = si->io.pck_snd;
1037 tcp_ack = si->io.pck_rcv;
1038 tcp_ctl = 0x12; /* SYN,ACK */
1040 si->io.pck_snd += 1;
1044 case SWRAP_ACCEPT_ACK:
1045 if (si->type != SOCK_STREAM) return;
1047 dest_addr = (const struct sockaddr_in *)si->myname;
1048 src_addr = (const struct sockaddr_in *)addr;
1050 tcp_seq = si->io.pck_rcv;
1051 tcp_ack = si->io.pck_snd;
1052 tcp_ctl = 0x10; /* ACK */
1057 src_addr = (const struct sockaddr_in *)si->myname;
1058 dest_addr = (const struct sockaddr_in *)si->peername;
1060 tcp_seq = si->io.pck_snd;
1061 tcp_ack = si->io.pck_rcv;
1062 tcp_ctl = 0x18; /* PSH,ACK */
1064 si->io.pck_snd += len;
1068 case SWRAP_SEND_RST:
1069 dest_addr = (const struct sockaddr_in *)si->myname;
1070 src_addr = (const struct sockaddr_in *)si->peername;
1072 if (si->type == SOCK_DGRAM) {
1073 swrap_dump_packet(si, si->peername,
1074 SWRAP_SENDTO_UNREACH,
1079 tcp_seq = si->io.pck_rcv;
1080 tcp_ack = si->io.pck_snd;
1081 tcp_ctl = 0x14; /** RST,ACK */
1085 case SWRAP_PENDING_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_seq = si->io.pck_rcv;
1094 tcp_ack = si->io.pck_snd;
1095 tcp_ctl = 0x14; /* RST,ACK */
1100 dest_addr = (const struct sockaddr_in *)si->myname;
1101 src_addr = (const struct sockaddr_in *)si->peername;
1103 tcp_seq = si->io.pck_rcv;
1104 tcp_ack = si->io.pck_snd;
1105 tcp_ctl = 0x18; /* PSH,ACK */
1107 si->io.pck_rcv += len;
1111 case SWRAP_RECV_RST:
1112 dest_addr = (const struct sockaddr_in *)si->myname;
1113 src_addr = (const struct sockaddr_in *)si->peername;
1115 if (si->type == SOCK_DGRAM) {
1119 tcp_seq = si->io.pck_rcv;
1120 tcp_ack = si->io.pck_snd;
1121 tcp_ctl = 0x14; /* RST,ACK */
1126 src_addr = (const struct sockaddr_in *)si->myname;
1127 dest_addr = (const struct sockaddr_in *)addr;
1129 si->io.pck_snd += len;
1133 case SWRAP_SENDTO_UNREACH:
1134 dest_addr = (const struct sockaddr_in *)si->myname;
1135 src_addr = (const struct sockaddr_in *)addr;
1141 case SWRAP_RECVFROM:
1142 dest_addr = (const struct sockaddr_in *)si->myname;
1143 src_addr = (const struct sockaddr_in *)addr;
1145 si->io.pck_rcv += len;
1149 case SWRAP_CLOSE_SEND:
1150 if (si->type != SOCK_STREAM) return;
1152 src_addr = (const struct sockaddr_in *)si->myname;
1153 dest_addr = (const struct sockaddr_in *)si->peername;
1155 tcp_seq = si->io.pck_snd;
1156 tcp_ack = si->io.pck_rcv;
1157 tcp_ctl = 0x11; /* FIN, ACK */
1159 si->io.pck_snd += 1;
1163 case SWRAP_CLOSE_RECV:
1164 if (si->type != SOCK_STREAM) return;
1166 dest_addr = (const struct sockaddr_in *)si->myname;
1167 src_addr = (const struct sockaddr_in *)si->peername;
1169 tcp_seq = si->io.pck_rcv;
1170 tcp_ack = si->io.pck_snd;
1171 tcp_ctl = 0x11; /* FIN,ACK */
1173 si->io.pck_rcv += 1;
1177 case SWRAP_CLOSE_ACK:
1178 if (si->type != SOCK_STREAM) return;
1180 src_addr = (const struct sockaddr_in *)si->myname;
1181 dest_addr = (const struct sockaddr_in *)si->peername;
1183 tcp_seq = si->io.pck_snd;
1184 tcp_ack = si->io.pck_rcv;
1185 tcp_ctl = 0x10; /* ACK */
1192 swrapGetTimeOfDay(&tv);
1194 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1195 (const unsigned char *)buf, len,
1196 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1202 fd = swrap_get_pcap_fd(file_name);
1204 write(fd, packet, packet_len);
1210 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1212 struct socket_info *si;
1215 if (!socket_wrapper_dir()) {
1216 return real_socket(family, type, protocol);
1226 return real_socket(family, type, protocol);
1228 errno = EAFNOSUPPORT;
1238 errno = EPROTONOSUPPORT;
1247 errno = EPROTONOSUPPORT;
1252 fd = real_socket(AF_UNIX, type, 0);
1254 if (fd == -1) return -1;
1256 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1258 si->family = family;
1260 si->protocol = protocol;
1263 SWRAP_DLIST_ADD(sockets, si);
1268 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1270 struct socket_info *parent_si, *child_si;
1272 struct sockaddr_un un_addr;
1273 socklen_t un_addrlen = sizeof(un_addr);
1274 struct sockaddr_un un_my_addr;
1275 socklen_t un_my_addrlen = sizeof(un_my_addr);
1276 struct sockaddr *my_addr;
1277 socklen_t my_addrlen, len;
1280 parent_si = find_socket_info(s);
1282 return real_accept(s, addr, addrlen);
1286 * assume out sockaddr have the same size as the in parent
1289 my_addrlen = socket_length(parent_si->family);
1290 if (my_addrlen < 0) {
1295 my_addr = malloc(my_addrlen);
1296 if (my_addr == NULL) {
1300 memset(&un_addr, 0, sizeof(un_addr));
1301 memset(&un_my_addr, 0, sizeof(un_my_addr));
1303 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1312 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1313 parent_si->family, my_addr, &len);
1320 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1321 memset(child_si, 0, sizeof(*child_si));
1324 child_si->family = parent_si->family;
1325 child_si->type = parent_si->type;
1326 child_si->protocol = parent_si->protocol;
1327 child_si->bound = 1;
1328 child_si->is_server = 1;
1330 child_si->peername_len = len;
1331 child_si->peername = sockaddr_dup(my_addr, len);
1333 if (addr != NULL && addrlen != NULL) {
1335 if (*addrlen >= len)
1336 memcpy(addr, my_addr, len);
1340 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1348 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1349 child_si->family, my_addr, &len);
1357 child_si->myname_len = len;
1358 child_si->myname = sockaddr_dup(my_addr, len);
1361 SWRAP_DLIST_ADD(sockets, child_si);
1363 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1364 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1365 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1370 static int autobind_start_init;
1371 static int autobind_start;
1373 /* using sendto() or connect() on an unbound socket would give the
1374 recipient no way to reply, as unlike UDP and TCP, a unix domain
1375 socket can't auto-assign emphemeral port numbers, so we need to
1377 static int swrap_auto_bind(struct socket_info *si)
1379 struct sockaddr_un un_addr;
1386 if (autobind_start_init != 1) {
1387 autobind_start_init = 1;
1388 autobind_start = getpid();
1389 autobind_start %= 50000;
1390 autobind_start += 10000;
1393 un_addr.sun_family = AF_UNIX;
1395 switch (si->family) {
1397 struct sockaddr_in in;
1401 type = SOCKET_TYPE_CHAR_TCP;
1404 type = SOCKET_TYPE_CHAR_UDP;
1407 errno = ESOCKTNOSUPPORT;
1411 memset(&in, 0, sizeof(in));
1412 in.sin_family = AF_INET;
1413 in.sin_addr.s_addr = htonl(127<<24 |
1414 socket_wrapper_default_iface());
1416 si->myname_len = sizeof(in);
1417 si->myname = sockaddr_dup(&in, si->myname_len);
1422 struct sockaddr_in6 in6;
1426 type = SOCKET_TYPE_CHAR_TCP_V6;
1429 type = SOCKET_TYPE_CHAR_UDP_V6;
1432 errno = ESOCKTNOSUPPORT;
1436 memset(&in6, 0, sizeof(in6));
1437 in6.sin6_family = AF_INET6;
1438 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1439 si->myname_len = sizeof(in6);
1440 si->myname = sockaddr_dup(&in6, si->myname_len);
1445 errno = ESOCKTNOSUPPORT;
1449 if (autobind_start > 60000) {
1450 autobind_start = 10000;
1453 for (i=0;i<1000;i++) {
1454 port = autobind_start + i;
1455 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1456 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1457 type, socket_wrapper_default_iface(), port);
1458 if (stat(un_addr.sun_path, &st) == 0) continue;
1460 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1461 if (ret == -1) return ret;
1463 si->tmp_path = strdup(un_addr.sun_path);
1465 autobind_start = port + 1;
1473 set_port(si->family, port, si->myname);
1479 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1482 struct sockaddr_un un_addr;
1483 struct socket_info *si = find_socket_info(s);
1486 return real_connect(s, serv_addr, addrlen);
1489 if (si->bound == 0) {
1490 ret = swrap_auto_bind(si);
1491 if (ret == -1) return -1;
1494 if (si->family != serv_addr->sa_family) {
1499 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1500 if (ret == -1) return -1;
1502 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1504 ret = real_connect(s, (struct sockaddr *)&un_addr,
1505 sizeof(struct sockaddr_un));
1507 /* to give better errors */
1508 if (ret == -1 && errno == ENOENT) {
1509 errno = EHOSTUNREACH;
1513 si->peername_len = addrlen;
1514 si->peername = sockaddr_dup(serv_addr, addrlen);
1516 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1517 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1519 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1525 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1528 struct sockaddr_un un_addr;
1529 struct socket_info *si = find_socket_info(s);
1532 return real_bind(s, myaddr, addrlen);
1535 si->myname_len = addrlen;
1536 si->myname = sockaddr_dup(myaddr, addrlen);
1538 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1539 if (ret == -1) return -1;
1541 unlink(un_addr.sun_path);
1543 ret = real_bind(s, (struct sockaddr *)&un_addr,
1544 sizeof(struct sockaddr_un));
1553 _PUBLIC_ int swrap_listen(int s, int backlog)
1556 struct socket_info *si = find_socket_info(s);
1559 return real_listen(s, backlog);
1562 ret = real_listen(s, backlog);
1567 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1569 struct socket_info *si = find_socket_info(s);
1572 return real_getpeername(s, name, addrlen);
1581 memcpy(name, si->peername, si->peername_len);
1582 *addrlen = si->peername_len;
1587 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1589 struct socket_info *si = find_socket_info(s);
1592 return real_getsockname(s, name, addrlen);
1595 memcpy(name, si->myname, si->myname_len);
1596 *addrlen = si->myname_len;
1601 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1603 struct socket_info *si = find_socket_info(s);
1606 return real_getsockopt(s, level, optname, optval, optlen);
1609 if (level == SOL_SOCKET) {
1610 return real_getsockopt(s, level, optname, optval, optlen);
1613 errno = ENOPROTOOPT;
1617 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1619 struct socket_info *si = find_socket_info(s);
1622 return real_setsockopt(s, level, optname, optval, optlen);
1625 if (level == SOL_SOCKET) {
1626 return real_setsockopt(s, level, optname, optval, optlen);
1629 switch (si->family) {
1633 errno = ENOPROTOOPT;
1638 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1640 struct sockaddr_un un_addr;
1641 socklen_t un_addrlen = sizeof(un_addr);
1643 struct socket_info *si = find_socket_info(s);
1646 return real_recvfrom(s, buf, len, flags, from, fromlen);
1649 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1650 memset(&un_addr, 0, sizeof(un_addr));
1651 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1655 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1656 si->family, from, fromlen) == -1) {
1660 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1666 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1668 struct sockaddr_un un_addr;
1670 struct socket_info *si = find_socket_info(s);
1674 return real_sendto(s, buf, len, flags, to, tolen);
1679 ret = real_send(s, buf, len, flags);
1682 if (si->bound == 0) {
1683 ret = swrap_auto_bind(si);
1684 if (ret == -1) return -1;
1687 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1688 if (ret == -1) return -1;
1693 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1696 type = SOCKET_TYPE_CHAR_UDP;
1698 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1699 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1700 socket_wrapper_dir(), type, iface, prt);
1701 if (stat(un_addr.sun_path, &st) != 0) continue;
1703 /* ignore the any errors in broadcast sends */
1704 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1707 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1712 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1716 errno = EHOSTUNREACH;
1720 /* to give better errors */
1721 if (ret == -1 && errno == ENOENT) {
1722 errno = EHOSTUNREACH;
1726 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1727 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1729 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1735 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1738 struct socket_info *si = find_socket_info(s);
1742 return real_ioctl(s, r, p);
1745 ret = real_ioctl(s, r, p);
1749 value = *((int *)p);
1750 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1751 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1752 } else if (value == 0) { /* END OF FILE */
1753 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1761 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1764 struct socket_info *si = find_socket_info(s);
1767 return real_recv(s, buf, len, flags);
1770 ret = real_recv(s, buf, len, flags);
1771 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1772 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1773 } else if (ret == 0) { /* END OF FILE */
1774 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1776 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1783 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1786 struct socket_info *si = find_socket_info(s);
1789 return real_send(s, buf, len, flags);
1792 ret = real_send(s, buf, len, flags);
1795 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1796 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1798 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1804 _PUBLIC_ int swrap_close(int fd)
1806 struct socket_info *si = find_socket_info(fd);
1810 return real_close(fd);
1813 SWRAP_DLIST_REMOVE(sockets, si);
1815 if (si->myname && si->peername) {
1816 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1819 ret = real_close(fd);
1821 if (si->myname && si->peername) {
1822 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1823 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1826 if (si->path) free(si->path);
1827 if (si->myname) free(si->myname);
1828 if (si->peername) free(si->peername);
1830 unlink(si->tmp_path);
1839 dup_internal(const struct socket_info *si_oldd, int fd)
1841 struct socket_info *si_newd;
1843 si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1847 si_newd->family = si_oldd->family;
1848 si_newd->type = si_oldd->type;
1849 si_newd->protocol = si_oldd->protocol;
1850 si_newd->bound = si_oldd->bound;
1851 si_newd->bcast = si_oldd->bcast;
1853 si_newd->path = strdup(si_oldd->path);
1854 if (si_oldd->tmp_path)
1855 si_newd->tmp_path = strdup(si_oldd->tmp_path);
1857 sockaddr_dup(si_oldd->myname, si_oldd->myname_len);
1858 si_newd->myname_len = si_oldd->myname_len;
1860 sockaddr_dup(si_oldd->peername, si_oldd->peername_len);
1861 si_newd->peername_len = si_oldd->peername_len;
1863 si_newd->io = si_oldd->io;
1865 SWRAP_DLIST_ADD(sockets, si_newd);
1871 _PUBLIC_ int swrap_dup(int oldd)
1873 struct socket_info *si;
1876 si = find_socket_info(oldd);
1878 return real_dup(oldd);
1880 fd = real_dup(si->fd);
1884 return dup_internal(si, fd);
1888 _PUBLIC_ int swrap_dup2(int oldd, int newd)
1890 struct socket_info *si_newd, *si_oldd;
1896 si_oldd = find_socket_info(oldd);
1897 si_newd = find_socket_info(newd);
1899 if (si_oldd == NULL && si_newd == NULL)
1900 return real_dup2(oldd, newd);
1902 fd = real_dup2(si_oldd->fd, newd);
1906 /* close new socket first */
1910 return dup_internal(si_oldd, fd);