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
45 #include "lib/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;
217 const char *socket_wrapper_dir(void)
219 const char *s = getenv("SOCKET_WRAPPER_DIR");
223 if (strncmp(s, "./", 2) == 0) {
229 unsigned int socket_wrapper_default_iface(void)
231 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
234 if (sscanf(s, "%u", &iface) == 1) {
235 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
241 return 1;/* 127.0.0.1 */
244 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
251 p = strrchr(un->sun_path, '/');
252 if (p) p++; else p = un->sun_path;
254 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
259 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
270 case SOCKET_TYPE_CHAR_TCP:
271 case SOCKET_TYPE_CHAR_UDP: {
272 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
274 if ((*len) < sizeof(*in2)) {
279 memset(in2, 0, sizeof(*in2));
280 in2->sin_family = AF_INET;
281 in2->sin_addr.s_addr = htonl((127<<24) | iface);
282 in2->sin_port = htons(prt);
288 case SOCKET_TYPE_CHAR_TCP_V6:
289 case SOCKET_TYPE_CHAR_UDP_V6: {
290 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
292 if ((*len) < sizeof(*in2)) {
297 memset(in2, 0, sizeof(*in2));
298 in2->sin6_family = AF_INET6;
299 in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
300 in2->sin6_port = htons(prt);
314 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
322 if (bcast) *bcast = 0;
324 switch (si->family) {
326 const struct sockaddr_in *in =
327 (const struct sockaddr_in *)inaddr;
328 unsigned int addr = ntohl(in->sin_addr.s_addr);
335 u_type = SOCKET_TYPE_CHAR_TCP;
338 u_type = SOCKET_TYPE_CHAR_UDP;
339 a_type = SOCKET_TYPE_CHAR_UDP;
340 b_type = SOCKET_TYPE_CHAR_UDP;
344 prt = ntohs(in->sin_port);
345 if (a_type && addr == 0xFFFFFFFF) {
346 /* 255.255.255.255 only udp */
349 iface = socket_wrapper_default_iface();
350 } else if (b_type && addr == 0x7FFFFFFF) {
351 /* 127.255.255.255 only udp */
354 iface = socket_wrapper_default_iface();
355 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
359 iface = (addr & 0x000000FF);
364 if (bcast) *bcast = is_bcast;
369 const struct sockaddr_in6 *in =
370 (const struct sockaddr_in6 *)inaddr;
374 type = SOCKET_TYPE_CHAR_TCP_V6;
377 type = SOCKET_TYPE_CHAR_UDP_V6;
381 /* XXX no multicast/broadcast */
383 prt = ntohs(in->sin6_port);
384 iface = SW_IPV6_ADDRESS;
400 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
401 socket_wrapper_dir());
402 /* the caller need to do more processing */
406 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
407 socket_wrapper_dir(), type, iface, prt);
412 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
421 if (bcast) *bcast = 0;
423 switch (si->family) {
425 const struct sockaddr_in *in =
426 (const struct sockaddr_in *)inaddr;
427 unsigned int addr = ntohl(in->sin_addr.s_addr);
433 prt = ntohs(in->sin_port);
437 u_type = SOCKET_TYPE_CHAR_TCP;
438 d_type = SOCKET_TYPE_CHAR_TCP;
441 u_type = SOCKET_TYPE_CHAR_UDP;
442 d_type = SOCKET_TYPE_CHAR_UDP;
443 a_type = SOCKET_TYPE_CHAR_UDP;
444 b_type = SOCKET_TYPE_CHAR_UDP;
452 iface = socket_wrapper_default_iface();
453 } else if (a_type && addr == 0xFFFFFFFF) {
454 /* 255.255.255.255 only udp */
457 iface = socket_wrapper_default_iface();
458 } else if (b_type && addr == 0x7FFFFFFF) {
459 /* 127.255.255.255 only udp */
462 iface = socket_wrapper_default_iface();
463 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
467 iface = (addr & 0x000000FF);
469 errno = EADDRNOTAVAIL;
476 const struct sockaddr_in6 *in =
477 (const struct sockaddr_in6 *)inaddr;
481 type = SOCKET_TYPE_CHAR_TCP_V6;
484 type = SOCKET_TYPE_CHAR_UDP_V6;
488 /* XXX no multicast/broadcast */
490 prt = ntohs(in->sin6_port);
491 iface = SW_IPV6_ADDRESS;
502 if (bcast) *bcast = is_bcast;
505 /* handle auto-allocation of ephemeral ports */
506 for (prt = 5001; prt < 10000; prt++) {
507 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
508 socket_wrapper_dir(), type, iface, prt);
509 if (stat(un->sun_path, &st) == 0) continue;
511 set_port(si->family, prt, si->myname);
520 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
521 socket_wrapper_dir(), type, iface, prt);
525 static struct socket_info *find_socket_info(int fd)
527 struct socket_info *i;
528 for (i = sockets; i; i = i->next) {
536 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
537 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
542 out_addr->sun_family = AF_UNIX;
544 switch (in_addr->sa_family) {
554 errno = ESOCKTNOSUPPORT;
558 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
560 return convert_in_un_remote(si, in_addr, out_addr, bcast);
566 errno = EAFNOSUPPORT;
570 static int sockaddr_convert_from_un(const struct socket_info *si,
571 const struct sockaddr_un *in_addr,
572 socklen_t un_addrlen,
574 struct sockaddr *out_addr,
575 socklen_t *out_addrlen)
577 if (out_addr == NULL || out_addrlen == NULL)
580 if (un_addrlen == 0) {
595 errno = ESOCKTNOSUPPORT;
598 return convert_un_in(in_addr, out_addr, out_addrlen);
603 errno = EAFNOSUPPORT;
607 enum swrap_packet_type {
609 SWRAP_CONNECT_UNREACH,
617 SWRAP_SENDTO_UNREACH,
628 struct swrap_file_hdr {
630 uint16_t version_major;
631 uint16_t version_minor;
634 uint32_t frame_max_len;
635 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
638 #define SWRAP_FILE_HDR_SIZE 24
640 struct swrap_packet {
643 uint32_t micro_seconds;
644 uint32_t recorded_length;
645 uint32_t full_length;
647 #define SWRAP_PACKET__FRAME_SIZE 16
653 uint16_t packet_length;
654 uint16_t identification;
659 uint16_t hdr_checksum;
663 #define SWRAP_PACKET__IP_HDR_SIZE 20
667 uint16_t source_port;
677 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
679 uint16_t source_port;
684 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
691 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
695 #define SWRAP_PACKET_SIZE 56
697 static const char *socket_wrapper_pcap_file(void)
699 static int initialized = 0;
700 static const char *s = NULL;
701 static const struct swrap_file_hdr h = { 0, };
702 static const struct swrap_packet p = { { 0, }, { { 0, }, { { 0, } } } };
704 if (initialized == 1) {
710 * TODO: don't use the structs use plain buffer offsets
711 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
713 * for now make sure we disable PCAP support
714 * if the struct has alignment!
716 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
719 if (sizeof(p) != SWRAP_PACKET_SIZE) {
722 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
725 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
728 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
731 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
734 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
738 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
742 if (strncmp(s, "./", 2) == 0) {
748 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
749 const struct sockaddr_in *src_addr,
750 const struct sockaddr_in *dest_addr,
752 const unsigned char *payload,
754 unsigned long tcp_seq,
755 unsigned long tcp_ack,
756 unsigned char tcp_ctl,
760 struct swrap_packet *ret;
761 struct swrap_packet *packet;
764 size_t nonwire_len = sizeof(packet->frame);
765 size_t wire_hdr_len = 0;
767 size_t icmp_hdr_len = 0;
768 size_t icmp_truncate_len = 0;
769 unsigned char protocol = 0, icmp_protocol = 0;
770 unsigned short src_port = src_addr->sin_port;
771 unsigned short dest_port = dest_addr->sin_port;
773 switch (socket_type) {
775 protocol = 0x06; /* TCP */
776 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
777 wire_len = wire_hdr_len + payload_len;
781 protocol = 0x11; /* UDP */
782 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
783 wire_len = wire_hdr_len + payload_len;
791 icmp_protocol = protocol;
792 protocol = 0x01; /* ICMP */
793 if (wire_len > 64 ) {
794 icmp_truncate_len = wire_len - 64;
796 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
797 wire_hdr_len += icmp_hdr_len;
798 wire_len += icmp_hdr_len;
801 packet_len = nonwire_len + wire_len;
802 alloc_len = packet_len;
803 if (alloc_len < sizeof(struct swrap_packet)) {
804 alloc_len = sizeof(struct swrap_packet);
806 ret = (struct swrap_packet *)malloc(alloc_len);
807 if (!ret) return NULL;
811 packet->frame.seconds = tval->tv_sec;
812 packet->frame.micro_seconds = tval->tv_usec;
813 packet->frame.recorded_length = wire_len - icmp_truncate_len;
814 packet->frame.full_length = wire_len - icmp_truncate_len;
816 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
817 packet->ip.hdr.tos = 0x00;
818 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
819 packet->ip.hdr.identification = htons(0xFFFF);
820 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
821 packet->ip.hdr.fragment = htons(0x0000);
822 packet->ip.hdr.ttl = 0xFF;
823 packet->ip.hdr.protocol = protocol;
824 packet->ip.hdr.hdr_checksum = htons(0x0000);
825 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
826 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
829 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
830 packet->ip.p.icmp.code = 0x01; /* host unreachable */
831 packet->ip.p.icmp.checksum = htons(0x0000);
832 packet->ip.p.icmp.unused = htonl(0x00000000);
834 /* set the ip header in the ICMP payload */
835 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
836 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
837 packet->ip.hdr.tos = 0x00;
838 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
839 packet->ip.hdr.identification = htons(0xFFFF);
840 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
841 packet->ip.hdr.fragment = htons(0x0000);
842 packet->ip.hdr.ttl = 0xFF;
843 packet->ip.hdr.protocol = icmp_protocol;
844 packet->ip.hdr.hdr_checksum = htons(0x0000);
845 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
846 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
848 src_port = dest_addr->sin_port;
849 dest_port = src_addr->sin_port;
852 switch (socket_type) {
854 packet->ip.p.tcp.source_port = src_port;
855 packet->ip.p.tcp.dest_port = dest_port;
856 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
857 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
858 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
859 packet->ip.p.tcp.control = tcp_ctl;
860 packet->ip.p.tcp.window = htons(0x7FFF);
861 packet->ip.p.tcp.checksum = htons(0x0000);
862 packet->ip.p.tcp.urg = htons(0x0000);
867 packet->ip.p.udp.source_port = src_addr->sin_port;
868 packet->ip.p.udp.dest_port = dest_addr->sin_port;
869 packet->ip.p.udp.length = htons(8 + payload_len);
870 packet->ip.p.udp.checksum = htons(0x0000);
875 if (payload && payload_len > 0) {
876 unsigned char *p = (unsigned char *)ret;
879 memcpy(p, payload, payload_len);
882 *_packet_len = packet_len - icmp_truncate_len;
886 static int swrap_get_pcap_fd(const char *fname)
890 if (fd != -1) return fd;
892 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
894 struct swrap_file_hdr file_hdr;
895 file_hdr.magic = 0xA1B2C3D4;
896 file_hdr.version_major = 0x0002;
897 file_hdr.version_minor = 0x0004;
898 file_hdr.timezone = 0x00000000;
899 file_hdr.sigfigs = 0x00000000;
900 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
901 file_hdr.link_type = 0x0065; /* 101 RAW IP */
903 write(fd, &file_hdr, sizeof(file_hdr));
907 fd = open(fname, O_WRONLY|O_APPEND, 0644);
912 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
913 enum swrap_packet_type type,
914 const void *buf, size_t len)
916 const struct sockaddr_in *src_addr;
917 const struct sockaddr_in *dest_addr;
918 const char *file_name;
919 unsigned long tcp_seq = 0;
920 unsigned long tcp_ack = 0;
921 unsigned char tcp_ctl = 0;
924 struct swrap_packet *packet;
925 size_t packet_len = 0;
928 file_name = socket_wrapper_pcap_file();
933 switch (si->family) {
944 case SWRAP_CONNECT_SEND:
945 if (si->type != SOCK_STREAM) return;
947 src_addr = (const struct sockaddr_in *)si->myname;
948 dest_addr = (const struct sockaddr_in *)addr;
950 tcp_seq = si->io.pck_snd;
951 tcp_ack = si->io.pck_rcv;
952 tcp_ctl = 0x02; /* SYN */
958 case SWRAP_CONNECT_RECV:
959 if (si->type != SOCK_STREAM) return;
961 dest_addr = (const struct sockaddr_in *)si->myname;
962 src_addr = (const struct sockaddr_in *)addr;
964 tcp_seq = si->io.pck_rcv;
965 tcp_ack = si->io.pck_snd;
966 tcp_ctl = 0x12; /** SYN,ACK */
972 case SWRAP_CONNECT_UNREACH:
973 if (si->type != SOCK_STREAM) return;
975 dest_addr = (const struct sockaddr_in *)si->myname;
976 src_addr = (const struct sockaddr_in *)addr;
978 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
979 tcp_seq = si->io.pck_snd - 1;
980 tcp_ack = si->io.pck_rcv;
981 tcp_ctl = 0x02; /* SYN */
986 case SWRAP_CONNECT_ACK:
987 if (si->type != SOCK_STREAM) return;
989 src_addr = (const struct sockaddr_in *)si->myname;
990 dest_addr = (const struct sockaddr_in *)addr;
992 tcp_seq = si->io.pck_snd;
993 tcp_ack = si->io.pck_rcv;
994 tcp_ctl = 0x10; /* ACK */
998 case SWRAP_ACCEPT_SEND:
999 if (si->type != SOCK_STREAM) return;
1001 dest_addr = (const struct sockaddr_in *)si->myname;
1002 src_addr = (const struct sockaddr_in *)addr;
1004 tcp_seq = si->io.pck_rcv;
1005 tcp_ack = si->io.pck_snd;
1006 tcp_ctl = 0x02; /* SYN */
1008 si->io.pck_rcv += 1;
1012 case SWRAP_ACCEPT_RECV:
1013 if (si->type != SOCK_STREAM) return;
1015 src_addr = (const struct sockaddr_in *)si->myname;
1016 dest_addr = (const struct sockaddr_in *)addr;
1018 tcp_seq = si->io.pck_snd;
1019 tcp_ack = si->io.pck_rcv;
1020 tcp_ctl = 0x12; /* SYN,ACK */
1022 si->io.pck_snd += 1;
1026 case SWRAP_ACCEPT_ACK:
1027 if (si->type != SOCK_STREAM) return;
1029 dest_addr = (const struct sockaddr_in *)si->myname;
1030 src_addr = (const struct sockaddr_in *)addr;
1032 tcp_seq = si->io.pck_rcv;
1033 tcp_ack = si->io.pck_snd;
1034 tcp_ctl = 0x10; /* ACK */
1039 src_addr = (const struct sockaddr_in *)si->myname;
1040 dest_addr = (const struct sockaddr_in *)si->peername;
1042 tcp_seq = si->io.pck_snd;
1043 tcp_ack = si->io.pck_rcv;
1044 tcp_ctl = 0x18; /* PSH,ACK */
1046 si->io.pck_snd += len;
1050 case SWRAP_SEND_RST:
1051 dest_addr = (const struct sockaddr_in *)si->myname;
1052 src_addr = (const struct sockaddr_in *)si->peername;
1054 if (si->type == SOCK_DGRAM) {
1055 swrap_dump_packet(si, si->peername,
1056 SWRAP_SENDTO_UNREACH,
1061 tcp_seq = si->io.pck_rcv;
1062 tcp_ack = si->io.pck_snd;
1063 tcp_ctl = 0x14; /** RST,ACK */
1067 case SWRAP_PENDING_RST:
1068 dest_addr = (const struct sockaddr_in *)si->myname;
1069 src_addr = (const struct sockaddr_in *)si->peername;
1071 if (si->type == SOCK_DGRAM) {
1075 tcp_seq = si->io.pck_rcv;
1076 tcp_ack = si->io.pck_snd;
1077 tcp_ctl = 0x14; /* RST,ACK */
1082 dest_addr = (const struct sockaddr_in *)si->myname;
1083 src_addr = (const struct sockaddr_in *)si->peername;
1085 tcp_seq = si->io.pck_rcv;
1086 tcp_ack = si->io.pck_snd;
1087 tcp_ctl = 0x18; /* PSH,ACK */
1089 si->io.pck_rcv += len;
1093 case SWRAP_RECV_RST:
1094 dest_addr = (const struct sockaddr_in *)si->myname;
1095 src_addr = (const struct sockaddr_in *)si->peername;
1097 if (si->type == SOCK_DGRAM) {
1101 tcp_seq = si->io.pck_rcv;
1102 tcp_ack = si->io.pck_snd;
1103 tcp_ctl = 0x14; /* RST,ACK */
1108 src_addr = (const struct sockaddr_in *)si->myname;
1109 dest_addr = (const struct sockaddr_in *)addr;
1111 si->io.pck_snd += len;
1115 case SWRAP_SENDTO_UNREACH:
1116 dest_addr = (const struct sockaddr_in *)si->myname;
1117 src_addr = (const struct sockaddr_in *)addr;
1123 case SWRAP_RECVFROM:
1124 dest_addr = (const struct sockaddr_in *)si->myname;
1125 src_addr = (const struct sockaddr_in *)addr;
1127 si->io.pck_rcv += len;
1131 case SWRAP_CLOSE_SEND:
1132 if (si->type != SOCK_STREAM) return;
1134 src_addr = (const struct sockaddr_in *)si->myname;
1135 dest_addr = (const struct sockaddr_in *)si->peername;
1137 tcp_seq = si->io.pck_snd;
1138 tcp_ack = si->io.pck_rcv;
1139 tcp_ctl = 0x11; /* FIN, ACK */
1141 si->io.pck_snd += 1;
1145 case SWRAP_CLOSE_RECV:
1146 if (si->type != SOCK_STREAM) return;
1148 dest_addr = (const struct sockaddr_in *)si->myname;
1149 src_addr = (const struct sockaddr_in *)si->peername;
1151 tcp_seq = si->io.pck_rcv;
1152 tcp_ack = si->io.pck_snd;
1153 tcp_ctl = 0x11; /* FIN,ACK */
1155 si->io.pck_rcv += 1;
1159 case SWRAP_CLOSE_ACK:
1160 if (si->type != SOCK_STREAM) return;
1162 src_addr = (const struct sockaddr_in *)si->myname;
1163 dest_addr = (const struct sockaddr_in *)si->peername;
1165 tcp_seq = si->io.pck_snd;
1166 tcp_ack = si->io.pck_rcv;
1167 tcp_ctl = 0x10; /* ACK */
1174 swrapGetTimeOfDay(&tv);
1176 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1177 (const unsigned char *)buf, len,
1178 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1184 fd = swrap_get_pcap_fd(file_name);
1186 write(fd, packet, packet_len);
1192 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1194 struct socket_info *si;
1197 if (!socket_wrapper_dir()) {
1198 return real_socket(family, type, protocol);
1208 return real_socket(family, type, protocol);
1210 errno = EAFNOSUPPORT;
1220 errno = EPROTONOSUPPORT;
1228 if (type == SOCK_STREAM) {
1233 if (type == SOCK_DGRAM) {
1238 errno = EPROTONOSUPPORT;
1242 fd = real_socket(AF_UNIX, type, 0);
1244 if (fd == -1) return -1;
1246 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1248 si->family = family;
1250 si->protocol = protocol;
1253 SWRAP_DLIST_ADD(sockets, si);
1258 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1260 struct socket_info *parent_si, *child_si;
1262 struct sockaddr_un un_addr;
1263 socklen_t un_addrlen = sizeof(un_addr);
1264 struct sockaddr_un un_my_addr;
1265 socklen_t un_my_addrlen = sizeof(un_my_addr);
1266 struct sockaddr *my_addr;
1267 socklen_t my_addrlen, len;
1270 parent_si = find_socket_info(s);
1272 return real_accept(s, addr, addrlen);
1276 * assume out sockaddr have the same size as the in parent
1279 my_addrlen = socket_length(parent_si->family);
1280 if (my_addrlen <= 0) {
1285 my_addr = malloc(my_addrlen);
1286 if (my_addr == NULL) {
1290 memset(&un_addr, 0, sizeof(un_addr));
1291 memset(&un_my_addr, 0, sizeof(un_my_addr));
1293 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1302 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1303 parent_si->family, my_addr, &len);
1310 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1311 memset(child_si, 0, sizeof(*child_si));
1314 child_si->family = parent_si->family;
1315 child_si->type = parent_si->type;
1316 child_si->protocol = parent_si->protocol;
1317 child_si->bound = 1;
1318 child_si->is_server = 1;
1320 child_si->peername_len = len;
1321 child_si->peername = sockaddr_dup(my_addr, len);
1323 if (addr != NULL && addrlen != NULL) {
1325 if (*addrlen >= len)
1326 memcpy(addr, my_addr, len);
1330 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1338 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1339 child_si->family, my_addr, &len);
1347 child_si->myname_len = len;
1348 child_si->myname = sockaddr_dup(my_addr, len);
1351 SWRAP_DLIST_ADD(sockets, child_si);
1353 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1354 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1355 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1360 static int autobind_start_init;
1361 static int autobind_start;
1363 /* using sendto() or connect() on an unbound socket would give the
1364 recipient no way to reply, as unlike UDP and TCP, a unix domain
1365 socket can't auto-assign emphemeral port numbers, so we need to
1367 static int swrap_auto_bind(struct socket_info *si)
1369 struct sockaddr_un un_addr;
1376 if (autobind_start_init != 1) {
1377 autobind_start_init = 1;
1378 autobind_start = getpid();
1379 autobind_start %= 50000;
1380 autobind_start += 10000;
1383 un_addr.sun_family = AF_UNIX;
1385 switch (si->family) {
1387 struct sockaddr_in in;
1391 type = SOCKET_TYPE_CHAR_TCP;
1394 type = SOCKET_TYPE_CHAR_UDP;
1397 errno = ESOCKTNOSUPPORT;
1401 memset(&in, 0, sizeof(in));
1402 in.sin_family = AF_INET;
1403 in.sin_addr.s_addr = htonl(127<<24 |
1404 socket_wrapper_default_iface());
1406 si->myname_len = sizeof(in);
1407 si->myname = sockaddr_dup(&in, si->myname_len);
1412 struct sockaddr_in6 in6;
1416 type = SOCKET_TYPE_CHAR_TCP_V6;
1419 type = SOCKET_TYPE_CHAR_UDP_V6;
1422 errno = ESOCKTNOSUPPORT;
1426 memset(&in6, 0, sizeof(in6));
1427 in6.sin6_family = AF_INET6;
1428 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1429 si->myname_len = sizeof(in6);
1430 si->myname = sockaddr_dup(&in6, si->myname_len);
1435 errno = ESOCKTNOSUPPORT;
1439 if (autobind_start > 60000) {
1440 autobind_start = 10000;
1443 for (i=0;i<1000;i++) {
1444 port = autobind_start + i;
1445 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1446 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1447 type, socket_wrapper_default_iface(), port);
1448 if (stat(un_addr.sun_path, &st) == 0) continue;
1450 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1451 if (ret == -1) return ret;
1453 si->tmp_path = strdup(un_addr.sun_path);
1455 autobind_start = port + 1;
1463 set_port(si->family, port, si->myname);
1469 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1472 struct sockaddr_un un_addr;
1473 struct socket_info *si = find_socket_info(s);
1476 return real_connect(s, serv_addr, addrlen);
1479 if (si->bound == 0) {
1480 ret = swrap_auto_bind(si);
1481 if (ret == -1) return -1;
1484 if (si->family != serv_addr->sa_family) {
1489 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1490 if (ret == -1) return -1;
1492 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1494 ret = real_connect(s, (struct sockaddr *)&un_addr,
1495 sizeof(struct sockaddr_un));
1497 /* to give better errors */
1498 if (ret == -1 && errno == ENOENT) {
1499 errno = EHOSTUNREACH;
1503 si->peername_len = addrlen;
1504 si->peername = sockaddr_dup(serv_addr, addrlen);
1506 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1507 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1509 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1515 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1518 struct sockaddr_un un_addr;
1519 struct socket_info *si = find_socket_info(s);
1522 return real_bind(s, myaddr, addrlen);
1525 si->myname_len = addrlen;
1526 si->myname = sockaddr_dup(myaddr, addrlen);
1528 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1529 if (ret == -1) return -1;
1531 unlink(un_addr.sun_path);
1533 ret = real_bind(s, (struct sockaddr *)&un_addr,
1534 sizeof(struct sockaddr_un));
1543 _PUBLIC_ int swrap_listen(int s, int backlog)
1546 struct socket_info *si = find_socket_info(s);
1549 return real_listen(s, backlog);
1552 ret = real_listen(s, backlog);
1557 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1559 struct socket_info *si = find_socket_info(s);
1562 return real_getpeername(s, name, addrlen);
1571 memcpy(name, si->peername, si->peername_len);
1572 *addrlen = si->peername_len;
1577 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1579 struct socket_info *si = find_socket_info(s);
1582 return real_getsockname(s, name, addrlen);
1585 memcpy(name, si->myname, si->myname_len);
1586 *addrlen = si->myname_len;
1591 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1593 struct socket_info *si = find_socket_info(s);
1596 return real_getsockopt(s, level, optname, optval, optlen);
1599 if (level == SOL_SOCKET) {
1600 return real_getsockopt(s, level, optname, optval, optlen);
1603 errno = ENOPROTOOPT;
1607 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1609 struct socket_info *si = find_socket_info(s);
1612 return real_setsockopt(s, level, optname, optval, optlen);
1615 if (level == SOL_SOCKET) {
1616 return real_setsockopt(s, level, optname, optval, optlen);
1619 switch (si->family) {
1623 errno = ENOPROTOOPT;
1628 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1630 struct sockaddr_un un_addr;
1631 socklen_t un_addrlen = sizeof(un_addr);
1633 struct socket_info *si = find_socket_info(s);
1636 return real_recvfrom(s, buf, len, flags, from, fromlen);
1639 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1640 memset(&un_addr, 0, sizeof(un_addr));
1641 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1645 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1646 si->family, from, fromlen) == -1) {
1650 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1656 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1658 struct sockaddr_un un_addr;
1660 struct socket_info *si = find_socket_info(s);
1664 return real_sendto(s, buf, len, flags, to, tolen);
1669 ret = real_send(s, buf, len, flags);
1672 if (si->bound == 0) {
1673 ret = swrap_auto_bind(si);
1674 if (ret == -1) return -1;
1677 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1678 if (ret == -1) return -1;
1683 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1686 type = SOCKET_TYPE_CHAR_UDP;
1688 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1689 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1690 socket_wrapper_dir(), type, iface, prt);
1691 if (stat(un_addr.sun_path, &st) != 0) continue;
1693 /* ignore the any errors in broadcast sends */
1694 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1697 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1702 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1706 errno = EHOSTUNREACH;
1710 /* to give better errors */
1711 if (ret == -1 && errno == ENOENT) {
1712 errno = EHOSTUNREACH;
1716 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1717 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1719 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1725 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1728 struct socket_info *si = find_socket_info(s);
1732 return real_ioctl(s, r, p);
1735 ret = real_ioctl(s, r, p);
1739 value = *((int *)p);
1740 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1741 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1742 } else if (value == 0) { /* END OF FILE */
1743 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1751 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1754 struct socket_info *si = find_socket_info(s);
1757 return real_recv(s, buf, len, flags);
1760 ret = real_recv(s, buf, len, flags);
1761 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1762 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1763 } else if (ret == 0) { /* END OF FILE */
1764 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1766 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1773 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1776 struct socket_info *si = find_socket_info(s);
1779 return real_send(s, buf, len, flags);
1782 ret = real_send(s, buf, len, flags);
1785 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1786 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1788 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1794 _PUBLIC_ int swrap_close(int fd)
1796 struct socket_info *si = find_socket_info(fd);
1800 return real_close(fd);
1803 SWRAP_DLIST_REMOVE(sockets, si);
1805 if (si->myname && si->peername) {
1806 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1809 ret = real_close(fd);
1811 if (si->myname && si->peername) {
1812 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1813 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1816 if (si->path) free(si->path);
1817 if (si->myname) free(si->myname);
1818 if (si->peername) free(si->peername);
1820 unlink(si->tmp_path);