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_frame {
641 uint32_t micro_seconds;
642 uint32_t recorded_length;
643 uint32_t full_length;
645 #define SWRAP_PACKET_FRAME_SIZE 16
647 union swrap_packet_ip {
651 uint16_t packet_length;
652 uint16_t identification;
657 uint16_t hdr_checksum;
661 #define SWRAP_PACKET_IP_V4_SIZE 20
663 #define SWRAP_PACKET_IP_SIZE 20
665 union swrap_packet_payload {
667 uint16_t source_port;
677 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
679 uint16_t source_port;
684 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
691 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
693 #define SWRAP_PACKET_PAYLOAD_SIZE 20
695 #define SWRAP_PACKET_MIN_ALLOC \
696 (SWRAP_PACKET_FRAME_SIZE + \
697 SWRAP_PACKET_IP_SIZE + \
698 SWRAP_PACKET_PAYLOAD_SIZE)
700 static const char *socket_wrapper_pcap_file(void)
702 static int initialized = 0;
703 static const char *s = NULL;
704 static const struct swrap_file_hdr h;
705 static const struct swrap_packet_frame f;
706 static const union swrap_packet_ip i;
707 static const union swrap_packet_payload p;
709 if (initialized == 1) {
715 * TODO: don't use the structs use plain buffer offsets
716 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
718 * for now make sure we disable PCAP support
719 * if the struct has alignment!
721 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
724 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
727 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
730 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
733 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
736 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
739 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
742 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
746 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
750 if (strncmp(s, "./", 2) == 0) {
756 static uint8_t *swrap_packet_init(struct timeval *tval,
757 const struct sockaddr *src,
758 const struct sockaddr *dest,
760 const uint8_t *payload,
762 unsigned long tcp_seqno,
763 unsigned long tcp_ack,
764 unsigned char tcp_ctl,
770 struct swrap_packet_frame *frame;
771 union swrap_packet_ip *ip;
772 union swrap_packet_payload *pay;
775 size_t nonwire_len = sizeof(*frame);
776 size_t wire_hdr_len = 0;
778 size_t ip_hdr_len = 0;
779 size_t icmp_hdr_len = 0;
780 size_t icmp_truncate_len = 0;
781 uint8_t protocol = 0, icmp_protocol = 0;
782 const struct sockaddr_in *src_in;
783 const struct sockaddr_in *dest_in;
787 switch (src->sa_family) {
789 src_in = (const struct sockaddr_in *)src;
790 dest_in = (const struct sockaddr_in *)dest;
791 src_port = src_in->sin_port;
792 dest_port = dest_in->sin_port;
793 ip_hdr_len = sizeof(ip->v4);
799 switch (socket_type) {
801 protocol = 0x06; /* TCP */
802 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
803 wire_len = wire_hdr_len + payload_len;
807 protocol = 0x11; /* UDP */
808 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
809 wire_len = wire_hdr_len + payload_len;
817 icmp_protocol = protocol;
818 protocol = 0x01; /* ICMP */
819 if (wire_len > 64 ) {
820 icmp_truncate_len = wire_len - 64;
822 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
823 wire_hdr_len += icmp_hdr_len;
824 wire_len += icmp_hdr_len;
827 packet_len = nonwire_len + wire_len;
828 alloc_len = packet_len;
829 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
830 alloc_len = SWRAP_PACKET_MIN_ALLOC;
833 base = (uint8_t *)malloc(alloc_len);
834 if (!base) return NULL;
838 frame = (struct swrap_packet_frame *)buf;
839 frame->seconds = tval->tv_sec;
840 frame->micro_seconds = tval->tv_usec;
841 frame->recorded_length = wire_len - icmp_truncate_len;
842 frame->full_length = wire_len - icmp_truncate_len;
843 buf += SWRAP_PACKET_FRAME_SIZE;
845 ip = (union swrap_packet_ip *)buf;
846 switch (src->sa_family) {
848 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
850 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
851 ip->v4.identification = htons(0xFFFF);
852 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
853 ip->v4.fragment = htons(0x0000);
855 ip->v4.protocol = protocol;
856 ip->v4.hdr_checksum = htons(0x0000);
857 ip->v4.src_addr = src_in->sin_addr.s_addr;
858 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
859 buf += SWRAP_PACKET_IP_V4_SIZE;
864 pay = (union swrap_packet_payload *)buf;
865 switch (src->sa_family) {
867 pay->icmp4.type = 0x03; /* destination unreachable */
868 pay->icmp4.code = 0x01; /* host unreachable */
869 pay->icmp4.checksum = htons(0x0000);
870 pay->icmp4.unused = htonl(0x00000000);
871 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
873 /* set the ip header in the ICMP payload */
874 ip = (union swrap_packet_ip *)buf;
875 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
877 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
878 ip->v4.identification = htons(0xFFFF);
879 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
880 ip->v4.fragment = htons(0x0000);
882 ip->v4.protocol = icmp_protocol;
883 ip->v4.hdr_checksum = htons(0x0000);
884 ip->v4.src_addr = dest_in->sin_addr.s_addr;
885 ip->v4.dest_addr = src_in->sin_addr.s_addr;
886 buf += SWRAP_PACKET_IP_V4_SIZE;
888 src_port = dest_in->sin_port;
889 dest_port = src_in->sin_port;
894 pay = (union swrap_packet_payload *)buf;
896 switch (socket_type) {
898 pay->tcp.source_port = src_port;
899 pay->tcp.dest_port = dest_port;
900 pay->tcp.seq_num = htonl(tcp_seqno);
901 pay->tcp.ack_num = htonl(tcp_ack);
902 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
903 pay->tcp.control = tcp_ctl;
904 pay->tcp.window = htons(0x7FFF);
905 pay->tcp.checksum = htons(0x0000);
906 pay->tcp.urg = htons(0x0000);
907 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
912 pay->udp.source_port = src_port;
913 pay->udp.dest_port = dest_port;
914 pay->udp.length = htons(8 + payload_len);
915 pay->udp.checksum = htons(0x0000);
916 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
921 if (payload && payload_len > 0) {
922 memcpy(buf, payload, payload_len);
925 *_packet_len = packet_len - icmp_truncate_len;
929 static int swrap_get_pcap_fd(const char *fname)
933 if (fd != -1) return fd;
935 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
937 struct swrap_file_hdr file_hdr;
938 file_hdr.magic = 0xA1B2C3D4;
939 file_hdr.version_major = 0x0002;
940 file_hdr.version_minor = 0x0004;
941 file_hdr.timezone = 0x00000000;
942 file_hdr.sigfigs = 0x00000000;
943 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
944 file_hdr.link_type = 0x0065; /* 101 RAW IP */
946 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
953 fd = open(fname, O_WRONLY|O_APPEND, 0644);
958 static uint8_t *swrap_marshall_packet(struct socket_info *si,
959 const struct sockaddr *addr,
960 enum swrap_packet_type type,
961 const void *buf, size_t len,
964 const struct sockaddr *src_addr;
965 const struct sockaddr *dest_addr;
966 unsigned long tcp_seqno = 0;
967 unsigned long tcp_ack = 0;
968 unsigned char tcp_ctl = 0;
973 switch (si->family) {
981 case SWRAP_CONNECT_SEND:
982 if (si->type != SOCK_STREAM) return NULL;
984 src_addr = si->myname;
987 tcp_seqno = si->io.pck_snd;
988 tcp_ack = si->io.pck_rcv;
989 tcp_ctl = 0x02; /* SYN */
995 case SWRAP_CONNECT_RECV:
996 if (si->type != SOCK_STREAM) return NULL;
998 dest_addr = si->myname;
1001 tcp_seqno = si->io.pck_rcv;
1002 tcp_ack = si->io.pck_snd;
1003 tcp_ctl = 0x12; /** SYN,ACK */
1005 si->io.pck_rcv += 1;
1009 case SWRAP_CONNECT_UNREACH:
1010 if (si->type != SOCK_STREAM) return NULL;
1012 dest_addr = si->myname;
1015 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1016 tcp_seqno = si->io.pck_snd - 1;
1017 tcp_ack = si->io.pck_rcv;
1018 tcp_ctl = 0x02; /* SYN */
1023 case SWRAP_CONNECT_ACK:
1024 if (si->type != SOCK_STREAM) return NULL;
1026 src_addr = si->myname;
1029 tcp_seqno = si->io.pck_snd;
1030 tcp_ack = si->io.pck_rcv;
1031 tcp_ctl = 0x10; /* ACK */
1035 case SWRAP_ACCEPT_SEND:
1036 if (si->type != SOCK_STREAM) return NULL;
1038 dest_addr = si->myname;
1041 tcp_seqno = si->io.pck_rcv;
1042 tcp_ack = si->io.pck_snd;
1043 tcp_ctl = 0x02; /* SYN */
1045 si->io.pck_rcv += 1;
1049 case SWRAP_ACCEPT_RECV:
1050 if (si->type != SOCK_STREAM) return NULL;
1052 src_addr = si->myname;
1055 tcp_seqno = si->io.pck_snd;
1056 tcp_ack = si->io.pck_rcv;
1057 tcp_ctl = 0x12; /* SYN,ACK */
1059 si->io.pck_snd += 1;
1063 case SWRAP_ACCEPT_ACK:
1064 if (si->type != SOCK_STREAM) return NULL;
1066 dest_addr = si->myname;
1069 tcp_seqno = si->io.pck_rcv;
1070 tcp_ack = si->io.pck_snd;
1071 tcp_ctl = 0x10; /* ACK */
1076 src_addr = si->myname;
1077 dest_addr = si->peername;
1079 tcp_seqno = si->io.pck_snd;
1080 tcp_ack = si->io.pck_rcv;
1081 tcp_ctl = 0x18; /* PSH,ACK */
1083 si->io.pck_snd += len;
1087 case SWRAP_SEND_RST:
1088 dest_addr = si->myname;
1089 src_addr = si->peername;
1091 if (si->type == SOCK_DGRAM) {
1092 return swrap_marshall_packet(si, si->peername,
1093 SWRAP_SENDTO_UNREACH,
1094 buf, len, packet_len);
1097 tcp_seqno = si->io.pck_rcv;
1098 tcp_ack = si->io.pck_snd;
1099 tcp_ctl = 0x14; /** RST,ACK */
1103 case SWRAP_PENDING_RST:
1104 dest_addr = si->myname;
1105 src_addr = si->peername;
1107 if (si->type == SOCK_DGRAM) {
1111 tcp_seqno = si->io.pck_rcv;
1112 tcp_ack = si->io.pck_snd;
1113 tcp_ctl = 0x14; /* RST,ACK */
1118 dest_addr = si->myname;
1119 src_addr = si->peername;
1121 tcp_seqno = si->io.pck_rcv;
1122 tcp_ack = si->io.pck_snd;
1123 tcp_ctl = 0x18; /* PSH,ACK */
1125 si->io.pck_rcv += len;
1129 case SWRAP_RECV_RST:
1130 dest_addr = si->myname;
1131 src_addr = si->peername;
1133 if (si->type == SOCK_DGRAM) {
1137 tcp_seqno = si->io.pck_rcv;
1138 tcp_ack = si->io.pck_snd;
1139 tcp_ctl = 0x14; /* RST,ACK */
1144 src_addr = si->myname;
1147 si->io.pck_snd += len;
1151 case SWRAP_SENDTO_UNREACH:
1152 dest_addr = si->myname;
1159 case SWRAP_RECVFROM:
1160 dest_addr = si->myname;
1163 si->io.pck_rcv += len;
1167 case SWRAP_CLOSE_SEND:
1168 if (si->type != SOCK_STREAM) return NULL;
1170 src_addr = si->myname;
1171 dest_addr = si->peername;
1173 tcp_seqno = si->io.pck_snd;
1174 tcp_ack = si->io.pck_rcv;
1175 tcp_ctl = 0x11; /* FIN, ACK */
1177 si->io.pck_snd += 1;
1181 case SWRAP_CLOSE_RECV:
1182 if (si->type != SOCK_STREAM) return NULL;
1184 dest_addr = si->myname;
1185 src_addr = si->peername;
1187 tcp_seqno = si->io.pck_rcv;
1188 tcp_ack = si->io.pck_snd;
1189 tcp_ctl = 0x11; /* FIN,ACK */
1191 si->io.pck_rcv += 1;
1195 case SWRAP_CLOSE_ACK:
1196 if (si->type != SOCK_STREAM) return NULL;
1198 src_addr = si->myname;
1199 dest_addr = si->peername;
1201 tcp_seqno = si->io.pck_snd;
1202 tcp_ack = si->io.pck_rcv;
1203 tcp_ctl = 0x10; /* ACK */
1210 swrapGetTimeOfDay(&tv);
1212 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1213 (const uint8_t *)buf, len,
1214 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1218 static void swrap_dump_packet(struct socket_info *si,
1219 const struct sockaddr *addr,
1220 enum swrap_packet_type type,
1221 const void *buf, size_t len)
1223 const char *file_name;
1225 size_t packet_len = 0;
1228 file_name = socket_wrapper_pcap_file();
1233 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1238 fd = swrap_get_pcap_fd(file_name);
1240 if (write(fd, packet, packet_len) != packet_len) {
1249 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1251 struct socket_info *si;
1254 if (!socket_wrapper_dir()) {
1255 return real_socket(family, type, protocol);
1265 return real_socket(family, type, protocol);
1267 errno = EAFNOSUPPORT;
1277 errno = EPROTONOSUPPORT;
1285 if (type == SOCK_STREAM) {
1290 if (type == SOCK_DGRAM) {
1295 errno = EPROTONOSUPPORT;
1299 fd = real_socket(AF_UNIX, type, 0);
1301 if (fd == -1) return -1;
1303 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1305 si->family = family;
1307 si->protocol = protocol;
1310 SWRAP_DLIST_ADD(sockets, si);
1315 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1317 struct socket_info *parent_si, *child_si;
1319 struct sockaddr_un un_addr;
1320 socklen_t un_addrlen = sizeof(un_addr);
1321 struct sockaddr_un un_my_addr;
1322 socklen_t un_my_addrlen = sizeof(un_my_addr);
1323 struct sockaddr *my_addr;
1324 socklen_t my_addrlen, len;
1327 parent_si = find_socket_info(s);
1329 return real_accept(s, addr, addrlen);
1333 * assume out sockaddr have the same size as the in parent
1336 my_addrlen = socket_length(parent_si->family);
1337 if (my_addrlen <= 0) {
1342 my_addr = (struct sockaddr *)malloc(my_addrlen);
1343 if (my_addr == NULL) {
1347 memset(&un_addr, 0, sizeof(un_addr));
1348 memset(&un_my_addr, 0, sizeof(un_my_addr));
1350 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1359 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1360 parent_si->family, my_addr, &len);
1367 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1368 memset(child_si, 0, sizeof(*child_si));
1371 child_si->family = parent_si->family;
1372 child_si->type = parent_si->type;
1373 child_si->protocol = parent_si->protocol;
1374 child_si->bound = 1;
1375 child_si->is_server = 1;
1377 child_si->peername_len = len;
1378 child_si->peername = sockaddr_dup(my_addr, len);
1380 if (addr != NULL && addrlen != NULL) {
1382 if (*addrlen >= len)
1383 memcpy(addr, my_addr, len);
1387 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1395 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1396 child_si->family, my_addr, &len);
1404 child_si->myname_len = len;
1405 child_si->myname = sockaddr_dup(my_addr, len);
1408 SWRAP_DLIST_ADD(sockets, child_si);
1410 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1411 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1412 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1417 static int autobind_start_init;
1418 static int autobind_start;
1420 /* using sendto() or connect() on an unbound socket would give the
1421 recipient no way to reply, as unlike UDP and TCP, a unix domain
1422 socket can't auto-assign emphemeral port numbers, so we need to
1424 static int swrap_auto_bind(struct socket_info *si)
1426 struct sockaddr_un un_addr;
1433 if (autobind_start_init != 1) {
1434 autobind_start_init = 1;
1435 autobind_start = getpid();
1436 autobind_start %= 50000;
1437 autobind_start += 10000;
1440 un_addr.sun_family = AF_UNIX;
1442 switch (si->family) {
1444 struct sockaddr_in in;
1448 type = SOCKET_TYPE_CHAR_TCP;
1451 type = SOCKET_TYPE_CHAR_UDP;
1454 errno = ESOCKTNOSUPPORT;
1458 memset(&in, 0, sizeof(in));
1459 in.sin_family = AF_INET;
1460 in.sin_addr.s_addr = htonl(127<<24 |
1461 socket_wrapper_default_iface());
1463 si->myname_len = sizeof(in);
1464 si->myname = sockaddr_dup(&in, si->myname_len);
1469 struct sockaddr_in6 in6;
1473 type = SOCKET_TYPE_CHAR_TCP_V6;
1476 type = SOCKET_TYPE_CHAR_UDP_V6;
1479 errno = ESOCKTNOSUPPORT;
1483 memset(&in6, 0, sizeof(in6));
1484 in6.sin6_family = AF_INET6;
1485 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1486 si->myname_len = sizeof(in6);
1487 si->myname = sockaddr_dup(&in6, si->myname_len);
1492 errno = ESOCKTNOSUPPORT;
1496 if (autobind_start > 60000) {
1497 autobind_start = 10000;
1500 for (i=0;i<1000;i++) {
1501 port = autobind_start + i;
1502 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1503 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1504 type, socket_wrapper_default_iface(), port);
1505 if (stat(un_addr.sun_path, &st) == 0) continue;
1507 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1508 if (ret == -1) return ret;
1510 si->tmp_path = strdup(un_addr.sun_path);
1512 autobind_start = port + 1;
1520 set_port(si->family, port, si->myname);
1526 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1529 struct sockaddr_un un_addr;
1530 struct socket_info *si = find_socket_info(s);
1533 return real_connect(s, serv_addr, addrlen);
1536 if (si->bound == 0) {
1537 ret = swrap_auto_bind(si);
1538 if (ret == -1) return -1;
1541 if (si->family != serv_addr->sa_family) {
1546 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1547 if (ret == -1) return -1;
1549 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1551 ret = real_connect(s, (struct sockaddr *)&un_addr,
1552 sizeof(struct sockaddr_un));
1554 /* to give better errors */
1555 if (ret == -1 && errno == ENOENT) {
1556 errno = EHOSTUNREACH;
1560 si->peername_len = addrlen;
1561 si->peername = sockaddr_dup(serv_addr, addrlen);
1563 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1564 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1566 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1572 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1575 struct sockaddr_un un_addr;
1576 struct socket_info *si = find_socket_info(s);
1579 return real_bind(s, myaddr, addrlen);
1582 si->myname_len = addrlen;
1583 si->myname = sockaddr_dup(myaddr, addrlen);
1585 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1586 if (ret == -1) return -1;
1588 unlink(un_addr.sun_path);
1590 ret = real_bind(s, (struct sockaddr *)&un_addr,
1591 sizeof(struct sockaddr_un));
1600 _PUBLIC_ int swrap_listen(int s, int backlog)
1603 struct socket_info *si = find_socket_info(s);
1606 return real_listen(s, backlog);
1609 ret = real_listen(s, backlog);
1614 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1616 struct socket_info *si = find_socket_info(s);
1619 return real_getpeername(s, name, addrlen);
1628 memcpy(name, si->peername, si->peername_len);
1629 *addrlen = si->peername_len;
1634 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1636 struct socket_info *si = find_socket_info(s);
1639 return real_getsockname(s, name, addrlen);
1642 memcpy(name, si->myname, si->myname_len);
1643 *addrlen = si->myname_len;
1648 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1650 struct socket_info *si = find_socket_info(s);
1653 return real_getsockopt(s, level, optname, optval, optlen);
1656 if (level == SOL_SOCKET) {
1657 return real_getsockopt(s, level, optname, optval, optlen);
1660 errno = ENOPROTOOPT;
1664 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1666 struct socket_info *si = find_socket_info(s);
1669 return real_setsockopt(s, level, optname, optval, optlen);
1672 if (level == SOL_SOCKET) {
1673 return real_setsockopt(s, level, optname, optval, optlen);
1676 switch (si->family) {
1680 errno = ENOPROTOOPT;
1685 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1687 struct sockaddr_un un_addr;
1688 socklen_t un_addrlen = sizeof(un_addr);
1690 struct socket_info *si = find_socket_info(s);
1693 return real_recvfrom(s, buf, len, flags, from, fromlen);
1696 len = MIN(len, 1500);
1698 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1699 memset(&un_addr, 0, sizeof(un_addr));
1700 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1704 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1705 si->family, from, fromlen) == -1) {
1709 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1715 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1717 struct sockaddr_un un_addr;
1719 struct socket_info *si = find_socket_info(s);
1723 return real_sendto(s, buf, len, flags, to, tolen);
1726 len = MIN(len, 1500);
1730 ret = real_send(s, buf, len, flags);
1733 if (si->bound == 0) {
1734 ret = swrap_auto_bind(si);
1735 if (ret == -1) return -1;
1738 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1739 if (ret == -1) return -1;
1744 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1747 type = SOCKET_TYPE_CHAR_UDP;
1749 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1750 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1751 socket_wrapper_dir(), type, iface, prt);
1752 if (stat(un_addr.sun_path, &st) != 0) continue;
1754 /* ignore the any errors in broadcast sends */
1755 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1758 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1763 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1767 errno = EHOSTUNREACH;
1771 /* to give better errors */
1772 if (ret == -1 && errno == ENOENT) {
1773 errno = EHOSTUNREACH;
1777 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1778 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1780 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1786 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1789 struct socket_info *si = find_socket_info(s);
1793 return real_ioctl(s, r, p);
1796 ret = real_ioctl(s, r, p);
1800 value = *((int *)p);
1801 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1802 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1803 } else if (value == 0) { /* END OF FILE */
1804 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1812 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1815 struct socket_info *si = find_socket_info(s);
1818 return real_recv(s, buf, len, flags);
1821 len = MIN(len, 1500);
1823 ret = real_recv(s, buf, len, flags);
1824 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1825 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1826 } else if (ret == 0) { /* END OF FILE */
1827 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1828 } else if (ret > 0) {
1829 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1836 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1839 struct socket_info *si = find_socket_info(s);
1842 return real_send(s, buf, len, flags);
1845 len = MIN(len, 1500);
1847 ret = real_send(s, buf, len, flags);
1850 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1851 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1853 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1859 _PUBLIC_ int swrap_close(int fd)
1861 struct socket_info *si = find_socket_info(fd);
1865 return real_close(fd);
1868 SWRAP_DLIST_REMOVE(sockets, si);
1870 if (si->myname && si->peername) {
1871 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1874 ret = real_close(fd);
1876 if (si->myname && si->peername) {
1877 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1878 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1881 if (si->path) free(si->path);
1882 if (si->myname) free(si->myname);
1883 if (si->peername) free(si->peername);
1885 unlink(si->tmp_path);