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
152 static const struct in6_addr swrap_ipv6 =
154 0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
155 0x00,0x00,0x00,0x00,0x53,0x57,0x5F,0x00
159 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
161 struct sockaddr *ret = (struct sockaddr *)malloc(len);
162 memcpy(ret, data, len);
166 static void set_port(int family, int prt, struct sockaddr *addr)
170 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
174 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
180 static size_t socket_length(int family)
184 return sizeof(struct sockaddr_in);
187 return sizeof(struct sockaddr_in6);
210 struct sockaddr *myname;
211 socklen_t myname_len;
213 struct sockaddr *peername;
214 socklen_t peername_len;
217 unsigned long pck_snd;
218 unsigned long pck_rcv;
221 struct socket_info *prev, *next;
224 static struct socket_info *sockets;
226 const char *socket_wrapper_dir(void)
228 const char *s = getenv("SOCKET_WRAPPER_DIR");
232 if (strncmp(s, "./", 2) == 0) {
238 unsigned int socket_wrapper_default_iface(void)
240 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
243 if (sscanf(s, "%u", &iface) == 1) {
244 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
250 return 1;/* 127.0.0.1 */
253 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
260 p = strrchr(un->sun_path, '/');
261 if (p) p++; else p = un->sun_path;
263 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
268 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
279 case SOCKET_TYPE_CHAR_TCP:
280 case SOCKET_TYPE_CHAR_UDP: {
281 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
283 if ((*len) < sizeof(*in2)) {
288 memset(in2, 0, sizeof(*in2));
289 in2->sin_family = AF_INET;
290 in2->sin_addr.s_addr = htonl((127<<24) | iface);
291 in2->sin_port = htons(prt);
297 case SOCKET_TYPE_CHAR_TCP_V6:
298 case SOCKET_TYPE_CHAR_UDP_V6: {
299 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
301 if ((*len) < sizeof(*in2)) {
306 memset(in2, 0, sizeof(*in2));
307 in2->sin6_family = AF_INET6;
308 in2->sin6_addr = swrap_ipv6;
309 in2->sin6_addr.s6_addr[15] = iface;
310 in2->sin6_port = htons(prt);
324 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
332 if (bcast) *bcast = 0;
334 switch (si->family) {
336 const struct sockaddr_in *in =
337 (const struct sockaddr_in *)inaddr;
338 unsigned int addr = ntohl(in->sin_addr.s_addr);
345 u_type = SOCKET_TYPE_CHAR_TCP;
348 u_type = SOCKET_TYPE_CHAR_UDP;
349 a_type = SOCKET_TYPE_CHAR_UDP;
350 b_type = SOCKET_TYPE_CHAR_UDP;
354 prt = ntohs(in->sin_port);
355 if (a_type && addr == 0xFFFFFFFF) {
356 /* 255.255.255.255 only udp */
359 iface = socket_wrapper_default_iface();
360 } else if (b_type && addr == 0x7FFFFFFF) {
361 /* 127.255.255.255 only udp */
364 iface = socket_wrapper_default_iface();
365 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
369 iface = (addr & 0x000000FF);
374 if (bcast) *bcast = is_bcast;
379 const struct sockaddr_in6 *in =
380 (const struct sockaddr_in6 *)inaddr;
385 type = SOCKET_TYPE_CHAR_TCP_V6;
388 type = SOCKET_TYPE_CHAR_UDP_V6;
392 /* XXX no multicast/broadcast */
394 prt = ntohs(in->sin6_port);
398 if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) {
399 iface = in->sin6_addr.s6_addr[15];
419 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
420 socket_wrapper_dir());
421 /* the caller need to do more processing */
425 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
426 socket_wrapper_dir(), type, iface, prt);
431 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
440 if (bcast) *bcast = 0;
442 switch (si->family) {
444 const struct sockaddr_in *in =
445 (const struct sockaddr_in *)inaddr;
446 unsigned int addr = ntohl(in->sin_addr.s_addr);
452 prt = ntohs(in->sin_port);
456 u_type = SOCKET_TYPE_CHAR_TCP;
457 d_type = SOCKET_TYPE_CHAR_TCP;
460 u_type = SOCKET_TYPE_CHAR_UDP;
461 d_type = SOCKET_TYPE_CHAR_UDP;
462 a_type = SOCKET_TYPE_CHAR_UDP;
463 b_type = SOCKET_TYPE_CHAR_UDP;
471 iface = socket_wrapper_default_iface();
472 } else if (a_type && addr == 0xFFFFFFFF) {
473 /* 255.255.255.255 only udp */
476 iface = socket_wrapper_default_iface();
477 } else if (b_type && addr == 0x7FFFFFFF) {
478 /* 127.255.255.255 only udp */
481 iface = socket_wrapper_default_iface();
482 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
486 iface = (addr & 0x000000FF);
488 errno = EADDRNOTAVAIL;
495 const struct sockaddr_in6 *in =
496 (const struct sockaddr_in6 *)inaddr;
501 type = SOCKET_TYPE_CHAR_TCP_V6;
504 type = SOCKET_TYPE_CHAR_UDP_V6;
508 /* XXX no multicast/broadcast */
510 prt = ntohs(in->sin6_port);
514 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
515 iface = socket_wrapper_default_iface();
516 } else if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) {
517 iface = in->sin6_addr.s6_addr[15];
519 errno = EADDRNOTAVAIL;
527 errno = EADDRNOTAVAIL;
532 if (bcast) *bcast = is_bcast;
535 /* handle auto-allocation of ephemeral ports */
536 for (prt = 5001; prt < 10000; prt++) {
537 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
538 socket_wrapper_dir(), type, iface, prt);
539 if (stat(un->sun_path, &st) == 0) continue;
541 set_port(si->family, prt, si->myname);
550 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
551 socket_wrapper_dir(), type, iface, prt);
555 static struct socket_info *find_socket_info(int fd)
557 struct socket_info *i;
558 for (i = sockets; i; i = i->next) {
566 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
567 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
572 out_addr->sun_family = AF_UNIX;
574 switch (in_addr->sa_family) {
584 errno = ESOCKTNOSUPPORT;
588 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
590 return convert_in_un_remote(si, in_addr, out_addr, bcast);
596 errno = EAFNOSUPPORT;
600 static int sockaddr_convert_from_un(const struct socket_info *si,
601 const struct sockaddr_un *in_addr,
602 socklen_t un_addrlen,
604 struct sockaddr *out_addr,
605 socklen_t *out_addrlen)
607 if (out_addr == NULL || out_addrlen == NULL)
610 if (un_addrlen == 0) {
625 errno = ESOCKTNOSUPPORT;
628 return convert_un_in(in_addr, out_addr, out_addrlen);
633 errno = EAFNOSUPPORT;
637 enum swrap_packet_type {
639 SWRAP_CONNECT_UNREACH,
647 SWRAP_SENDTO_UNREACH,
658 struct swrap_file_hdr {
660 uint16_t version_major;
661 uint16_t version_minor;
664 uint32_t frame_max_len;
665 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
668 #define SWRAP_FILE_HDR_SIZE 24
670 struct swrap_packet_frame {
672 uint32_t micro_seconds;
673 uint32_t recorded_length;
674 uint32_t full_length;
676 #define SWRAP_PACKET_FRAME_SIZE 16
678 union swrap_packet_ip {
682 uint16_t packet_length;
683 uint16_t identification;
688 uint16_t hdr_checksum;
692 #define SWRAP_PACKET_IP_V4_SIZE 20
695 uint8_t flow_label_high;
696 uint16_t flow_label_low;
697 uint16_t payload_length;
700 uint8_t src_addr[16];
701 uint8_t dest_addr[16];
703 #define SWRAP_PACKET_IP_V6_SIZE 40
705 #define SWRAP_PACKET_IP_SIZE 40
707 union swrap_packet_payload {
709 uint16_t source_port;
719 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
721 uint16_t source_port;
726 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
733 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
740 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
742 #define SWRAP_PACKET_PAYLOAD_SIZE 20
744 #define SWRAP_PACKET_MIN_ALLOC \
745 (SWRAP_PACKET_FRAME_SIZE + \
746 SWRAP_PACKET_IP_SIZE + \
747 SWRAP_PACKET_PAYLOAD_SIZE)
749 static const char *socket_wrapper_pcap_file(void)
751 static int initialized = 0;
752 static const char *s = NULL;
753 static const struct swrap_file_hdr h;
754 static const struct swrap_packet_frame f;
755 static const union swrap_packet_ip i;
756 static const union swrap_packet_payload p;
758 if (initialized == 1) {
764 * TODO: don't use the structs use plain buffer offsets
765 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
767 * for now make sure we disable PCAP support
768 * if the struct has alignment!
770 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
773 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
776 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
779 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
782 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
785 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
788 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
791 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
794 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
797 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
801 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
805 if (strncmp(s, "./", 2) == 0) {
811 static uint8_t *swrap_packet_init(struct timeval *tval,
812 const struct sockaddr *src,
813 const struct sockaddr *dest,
815 const uint8_t *payload,
817 unsigned long tcp_seqno,
818 unsigned long tcp_ack,
819 unsigned char tcp_ctl,
825 struct swrap_packet_frame *frame;
826 union swrap_packet_ip *ip;
827 union swrap_packet_payload *pay;
830 size_t nonwire_len = sizeof(*frame);
831 size_t wire_hdr_len = 0;
833 size_t ip_hdr_len = 0;
834 size_t icmp_hdr_len = 0;
835 size_t icmp_truncate_len = 0;
836 uint8_t protocol = 0, icmp_protocol = 0;
837 const struct sockaddr_in *src_in = NULL;
838 const struct sockaddr_in *dest_in = NULL;
840 const struct sockaddr_in6 *src_in6 = NULL;
841 const struct sockaddr_in6 *dest_in6 = NULL;
846 switch (src->sa_family) {
848 src_in = (const struct sockaddr_in *)src;
849 dest_in = (const struct sockaddr_in *)dest;
850 src_port = src_in->sin_port;
851 dest_port = dest_in->sin_port;
852 ip_hdr_len = sizeof(ip->v4);
856 src_in6 = (const struct sockaddr_in6 *)src;
857 dest_in6 = (const struct sockaddr_in6 *)dest;
858 src_port = src_in6->sin6_port;
859 dest_port = dest_in6->sin6_port;
860 ip_hdr_len = sizeof(ip->v6);
867 switch (socket_type) {
869 protocol = 0x06; /* TCP */
870 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
871 wire_len = wire_hdr_len + payload_len;
875 protocol = 0x11; /* UDP */
876 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
877 wire_len = wire_hdr_len + payload_len;
885 icmp_protocol = protocol;
886 switch (src->sa_family) {
888 protocol = 0x01; /* ICMPv4 */
889 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
893 protocol = 0x3A; /* ICMPv6 */
894 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
898 if (wire_len > 64 ) {
899 icmp_truncate_len = wire_len - 64;
901 wire_hdr_len += icmp_hdr_len;
902 wire_len += icmp_hdr_len;
905 packet_len = nonwire_len + wire_len;
906 alloc_len = packet_len;
907 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
908 alloc_len = SWRAP_PACKET_MIN_ALLOC;
911 base = (uint8_t *)malloc(alloc_len);
912 if (!base) return NULL;
916 frame = (struct swrap_packet_frame *)buf;
917 frame->seconds = tval->tv_sec;
918 frame->micro_seconds = tval->tv_usec;
919 frame->recorded_length = wire_len - icmp_truncate_len;
920 frame->full_length = wire_len - icmp_truncate_len;
921 buf += SWRAP_PACKET_FRAME_SIZE;
923 ip = (union swrap_packet_ip *)buf;
924 switch (src->sa_family) {
926 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
928 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
929 ip->v4.identification = htons(0xFFFF);
930 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
931 ip->v4.fragment = htons(0x0000);
933 ip->v4.protocol = protocol;
934 ip->v4.hdr_checksum = htons(0x0000);
935 ip->v4.src_addr = src_in->sin_addr.s_addr;
936 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
937 buf += SWRAP_PACKET_IP_V4_SIZE;
941 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
942 ip->v6.flow_label_high = 0x00;
943 ip->v6.flow_label_low = 0x0000;
944 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
945 ip->v6.next_header = protocol;
946 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
947 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
948 buf += SWRAP_PACKET_IP_V6_SIZE;
954 pay = (union swrap_packet_payload *)buf;
955 switch (src->sa_family) {
957 pay->icmp4.type = 0x03; /* destination unreachable */
958 pay->icmp4.code = 0x01; /* host unreachable */
959 pay->icmp4.checksum = htons(0x0000);
960 pay->icmp4.unused = htonl(0x00000000);
961 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
963 /* set the ip header in the ICMP payload */
964 ip = (union swrap_packet_ip *)buf;
965 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
967 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
968 ip->v4.identification = htons(0xFFFF);
969 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
970 ip->v4.fragment = htons(0x0000);
972 ip->v4.protocol = icmp_protocol;
973 ip->v4.hdr_checksum = htons(0x0000);
974 ip->v4.src_addr = dest_in->sin_addr.s_addr;
975 ip->v4.dest_addr = src_in->sin_addr.s_addr;
976 buf += SWRAP_PACKET_IP_V4_SIZE;
978 src_port = dest_in->sin_port;
979 dest_port = src_in->sin_port;
983 pay->icmp6.type = 0x01; /* destination unreachable */
984 pay->icmp6.code = 0x03; /* address unreachable */
985 pay->icmp6.checksum = htons(0x0000);
986 pay->icmp6.unused = htonl(0x00000000);
987 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
989 /* set the ip header in the ICMP payload */
990 ip = (union swrap_packet_ip *)buf;
991 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
992 ip->v6.flow_label_high = 0x00;
993 ip->v6.flow_label_low = 0x0000;
994 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
995 ip->v6.next_header = protocol;
996 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
997 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
998 buf += SWRAP_PACKET_IP_V6_SIZE;
1000 src_port = dest_in6->sin6_port;
1001 dest_port = src_in6->sin6_port;
1007 pay = (union swrap_packet_payload *)buf;
1009 switch (socket_type) {
1011 pay->tcp.source_port = src_port;
1012 pay->tcp.dest_port = dest_port;
1013 pay->tcp.seq_num = htonl(tcp_seqno);
1014 pay->tcp.ack_num = htonl(tcp_ack);
1015 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1016 pay->tcp.control = tcp_ctl;
1017 pay->tcp.window = htons(0x7FFF);
1018 pay->tcp.checksum = htons(0x0000);
1019 pay->tcp.urg = htons(0x0000);
1020 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1025 pay->udp.source_port = src_port;
1026 pay->udp.dest_port = dest_port;
1027 pay->udp.length = htons(8 + payload_len);
1028 pay->udp.checksum = htons(0x0000);
1029 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1034 if (payload && payload_len > 0) {
1035 memcpy(buf, payload, payload_len);
1038 *_packet_len = packet_len - icmp_truncate_len;
1042 static int swrap_get_pcap_fd(const char *fname)
1046 if (fd != -1) return fd;
1048 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1050 struct swrap_file_hdr file_hdr;
1051 file_hdr.magic = 0xA1B2C3D4;
1052 file_hdr.version_major = 0x0002;
1053 file_hdr.version_minor = 0x0004;
1054 file_hdr.timezone = 0x00000000;
1055 file_hdr.sigfigs = 0x00000000;
1056 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1057 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1059 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1066 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1071 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1072 const struct sockaddr *addr,
1073 enum swrap_packet_type type,
1074 const void *buf, size_t len,
1077 const struct sockaddr *src_addr;
1078 const struct sockaddr *dest_addr;
1079 unsigned long tcp_seqno = 0;
1080 unsigned long tcp_ack = 0;
1081 unsigned char tcp_ctl = 0;
1082 int unreachable = 0;
1086 switch (si->family) {
1096 case SWRAP_CONNECT_SEND:
1097 if (si->type != SOCK_STREAM) return NULL;
1099 src_addr = si->myname;
1102 tcp_seqno = si->io.pck_snd;
1103 tcp_ack = si->io.pck_rcv;
1104 tcp_ctl = 0x02; /* SYN */
1106 si->io.pck_snd += 1;
1110 case SWRAP_CONNECT_RECV:
1111 if (si->type != SOCK_STREAM) return NULL;
1113 dest_addr = si->myname;
1116 tcp_seqno = si->io.pck_rcv;
1117 tcp_ack = si->io.pck_snd;
1118 tcp_ctl = 0x12; /** SYN,ACK */
1120 si->io.pck_rcv += 1;
1124 case SWRAP_CONNECT_UNREACH:
1125 if (si->type != SOCK_STREAM) return NULL;
1127 dest_addr = si->myname;
1130 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1131 tcp_seqno = si->io.pck_snd - 1;
1132 tcp_ack = si->io.pck_rcv;
1133 tcp_ctl = 0x02; /* SYN */
1138 case SWRAP_CONNECT_ACK:
1139 if (si->type != SOCK_STREAM) return NULL;
1141 src_addr = si->myname;
1144 tcp_seqno = si->io.pck_snd;
1145 tcp_ack = si->io.pck_rcv;
1146 tcp_ctl = 0x10; /* ACK */
1150 case SWRAP_ACCEPT_SEND:
1151 if (si->type != SOCK_STREAM) return NULL;
1153 dest_addr = si->myname;
1156 tcp_seqno = si->io.pck_rcv;
1157 tcp_ack = si->io.pck_snd;
1158 tcp_ctl = 0x02; /* SYN */
1160 si->io.pck_rcv += 1;
1164 case SWRAP_ACCEPT_RECV:
1165 if (si->type != SOCK_STREAM) return NULL;
1167 src_addr = si->myname;
1170 tcp_seqno = si->io.pck_snd;
1171 tcp_ack = si->io.pck_rcv;
1172 tcp_ctl = 0x12; /* SYN,ACK */
1174 si->io.pck_snd += 1;
1178 case SWRAP_ACCEPT_ACK:
1179 if (si->type != SOCK_STREAM) return NULL;
1181 dest_addr = si->myname;
1184 tcp_seqno = si->io.pck_rcv;
1185 tcp_ack = si->io.pck_snd;
1186 tcp_ctl = 0x10; /* ACK */
1191 src_addr = si->myname;
1192 dest_addr = si->peername;
1194 tcp_seqno = si->io.pck_snd;
1195 tcp_ack = si->io.pck_rcv;
1196 tcp_ctl = 0x18; /* PSH,ACK */
1198 si->io.pck_snd += len;
1202 case SWRAP_SEND_RST:
1203 dest_addr = si->myname;
1204 src_addr = si->peername;
1206 if (si->type == SOCK_DGRAM) {
1207 return swrap_marshall_packet(si, si->peername,
1208 SWRAP_SENDTO_UNREACH,
1209 buf, len, packet_len);
1212 tcp_seqno = si->io.pck_rcv;
1213 tcp_ack = si->io.pck_snd;
1214 tcp_ctl = 0x14; /** RST,ACK */
1218 case SWRAP_PENDING_RST:
1219 dest_addr = si->myname;
1220 src_addr = si->peername;
1222 if (si->type == SOCK_DGRAM) {
1226 tcp_seqno = si->io.pck_rcv;
1227 tcp_ack = si->io.pck_snd;
1228 tcp_ctl = 0x14; /* RST,ACK */
1233 dest_addr = si->myname;
1234 src_addr = si->peername;
1236 tcp_seqno = si->io.pck_rcv;
1237 tcp_ack = si->io.pck_snd;
1238 tcp_ctl = 0x18; /* PSH,ACK */
1240 si->io.pck_rcv += len;
1244 case SWRAP_RECV_RST:
1245 dest_addr = si->myname;
1246 src_addr = si->peername;
1248 if (si->type == SOCK_DGRAM) {
1252 tcp_seqno = si->io.pck_rcv;
1253 tcp_ack = si->io.pck_snd;
1254 tcp_ctl = 0x14; /* RST,ACK */
1259 src_addr = si->myname;
1262 si->io.pck_snd += len;
1266 case SWRAP_SENDTO_UNREACH:
1267 dest_addr = si->myname;
1274 case SWRAP_RECVFROM:
1275 dest_addr = si->myname;
1278 si->io.pck_rcv += len;
1282 case SWRAP_CLOSE_SEND:
1283 if (si->type != SOCK_STREAM) return NULL;
1285 src_addr = si->myname;
1286 dest_addr = si->peername;
1288 tcp_seqno = si->io.pck_snd;
1289 tcp_ack = si->io.pck_rcv;
1290 tcp_ctl = 0x11; /* FIN, ACK */
1292 si->io.pck_snd += 1;
1296 case SWRAP_CLOSE_RECV:
1297 if (si->type != SOCK_STREAM) return NULL;
1299 dest_addr = si->myname;
1300 src_addr = si->peername;
1302 tcp_seqno = si->io.pck_rcv;
1303 tcp_ack = si->io.pck_snd;
1304 tcp_ctl = 0x11; /* FIN,ACK */
1306 si->io.pck_rcv += 1;
1310 case SWRAP_CLOSE_ACK:
1311 if (si->type != SOCK_STREAM) return NULL;
1313 src_addr = si->myname;
1314 dest_addr = si->peername;
1316 tcp_seqno = si->io.pck_snd;
1317 tcp_ack = si->io.pck_rcv;
1318 tcp_ctl = 0x10; /* ACK */
1325 swrapGetTimeOfDay(&tv);
1327 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1328 (const uint8_t *)buf, len,
1329 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1333 static void swrap_dump_packet(struct socket_info *si,
1334 const struct sockaddr *addr,
1335 enum swrap_packet_type type,
1336 const void *buf, size_t len)
1338 const char *file_name;
1340 size_t packet_len = 0;
1343 file_name = socket_wrapper_pcap_file();
1348 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1353 fd = swrap_get_pcap_fd(file_name);
1355 if (write(fd, packet, packet_len) != packet_len) {
1364 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1366 struct socket_info *si;
1369 if (!socket_wrapper_dir()) {
1370 return real_socket(family, type, protocol);
1380 return real_socket(family, type, protocol);
1382 errno = EAFNOSUPPORT;
1392 errno = EPROTONOSUPPORT;
1400 if (type == SOCK_STREAM) {
1405 if (type == SOCK_DGRAM) {
1410 errno = EPROTONOSUPPORT;
1414 fd = real_socket(AF_UNIX, type, 0);
1416 if (fd == -1) return -1;
1418 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1420 si->family = family;
1422 si->protocol = protocol;
1425 SWRAP_DLIST_ADD(sockets, si);
1430 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1432 struct socket_info *parent_si, *child_si;
1434 struct sockaddr_un un_addr;
1435 socklen_t un_addrlen = sizeof(un_addr);
1436 struct sockaddr_un un_my_addr;
1437 socklen_t un_my_addrlen = sizeof(un_my_addr);
1438 struct sockaddr *my_addr;
1439 socklen_t my_addrlen, len;
1442 parent_si = find_socket_info(s);
1444 return real_accept(s, addr, addrlen);
1448 * assume out sockaddr have the same size as the in parent
1451 my_addrlen = socket_length(parent_si->family);
1452 if (my_addrlen <= 0) {
1457 my_addr = (struct sockaddr *)malloc(my_addrlen);
1458 if (my_addr == NULL) {
1462 memset(&un_addr, 0, sizeof(un_addr));
1463 memset(&un_my_addr, 0, sizeof(un_my_addr));
1465 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1474 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1475 parent_si->family, my_addr, &len);
1482 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1483 memset(child_si, 0, sizeof(*child_si));
1486 child_si->family = parent_si->family;
1487 child_si->type = parent_si->type;
1488 child_si->protocol = parent_si->protocol;
1489 child_si->bound = 1;
1490 child_si->is_server = 1;
1491 child_si->connected = 1;
1493 child_si->peername_len = len;
1494 child_si->peername = sockaddr_dup(my_addr, len);
1496 if (addr != NULL && addrlen != NULL) {
1498 if (*addrlen >= len)
1499 memcpy(addr, my_addr, len);
1503 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1511 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1512 child_si->family, my_addr, &len);
1520 child_si->myname_len = len;
1521 child_si->myname = sockaddr_dup(my_addr, len);
1524 SWRAP_DLIST_ADD(sockets, child_si);
1526 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1527 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1528 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1533 static int autobind_start_init;
1534 static int autobind_start;
1536 /* using sendto() or connect() on an unbound socket would give the
1537 recipient no way to reply, as unlike UDP and TCP, a unix domain
1538 socket can't auto-assign emphemeral port numbers, so we need to
1540 static int swrap_auto_bind(struct socket_info *si)
1542 struct sockaddr_un un_addr;
1549 if (autobind_start_init != 1) {
1550 autobind_start_init = 1;
1551 autobind_start = getpid();
1552 autobind_start %= 50000;
1553 autobind_start += 10000;
1556 un_addr.sun_family = AF_UNIX;
1558 switch (si->family) {
1560 struct sockaddr_in in;
1564 type = SOCKET_TYPE_CHAR_TCP;
1567 type = SOCKET_TYPE_CHAR_UDP;
1570 errno = ESOCKTNOSUPPORT;
1574 memset(&in, 0, sizeof(in));
1575 in.sin_family = AF_INET;
1576 in.sin_addr.s_addr = htonl(127<<24 |
1577 socket_wrapper_default_iface());
1579 si->myname_len = sizeof(in);
1580 si->myname = sockaddr_dup(&in, si->myname_len);
1585 struct sockaddr_in6 in6;
1589 type = SOCKET_TYPE_CHAR_TCP_V6;
1592 type = SOCKET_TYPE_CHAR_UDP_V6;
1595 errno = ESOCKTNOSUPPORT;
1599 memset(&in6, 0, sizeof(in6));
1600 in6.sin6_family = AF_INET6;
1601 in6.sin6_addr = swrap_ipv6;
1602 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1603 si->myname_len = sizeof(in6);
1604 si->myname = sockaddr_dup(&in6, si->myname_len);
1609 errno = ESOCKTNOSUPPORT;
1613 if (autobind_start > 60000) {
1614 autobind_start = 10000;
1617 for (i=0;i<1000;i++) {
1618 port = autobind_start + i;
1619 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1620 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1621 type, socket_wrapper_default_iface(), port);
1622 if (stat(un_addr.sun_path, &st) == 0) continue;
1624 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1625 if (ret == -1) return ret;
1627 si->tmp_path = strdup(un_addr.sun_path);
1629 autobind_start = port + 1;
1637 set_port(si->family, port, si->myname);
1643 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1646 struct sockaddr_un un_addr;
1647 struct socket_info *si = find_socket_info(s);
1650 return real_connect(s, serv_addr, addrlen);
1653 if (si->bound == 0) {
1654 ret = swrap_auto_bind(si);
1655 if (ret == -1) return -1;
1658 if (si->family != serv_addr->sa_family) {
1663 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1664 if (ret == -1) return -1;
1666 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1668 ret = real_connect(s, (struct sockaddr *)&un_addr,
1669 sizeof(struct sockaddr_un));
1671 /* to give better errors */
1672 if (ret == -1 && errno == ENOENT) {
1673 errno = EHOSTUNREACH;
1677 si->peername_len = addrlen;
1678 si->peername = sockaddr_dup(serv_addr, addrlen);
1682 if (si->type != SOCK_STREAM) {
1687 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1688 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1690 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1696 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1699 struct sockaddr_un un_addr;
1700 struct socket_info *si = find_socket_info(s);
1703 return real_bind(s, myaddr, addrlen);
1706 si->myname_len = addrlen;
1707 si->myname = sockaddr_dup(myaddr, addrlen);
1709 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1710 if (ret == -1) return -1;
1712 unlink(un_addr.sun_path);
1714 ret = real_bind(s, (struct sockaddr *)&un_addr,
1715 sizeof(struct sockaddr_un));
1724 _PUBLIC_ int swrap_listen(int s, int backlog)
1727 struct socket_info *si = find_socket_info(s);
1730 return real_listen(s, backlog);
1733 ret = real_listen(s, backlog);
1738 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1740 struct socket_info *si = find_socket_info(s);
1743 return real_getpeername(s, name, addrlen);
1752 memcpy(name, si->peername, si->peername_len);
1753 *addrlen = si->peername_len;
1758 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1760 struct socket_info *si = find_socket_info(s);
1763 return real_getsockname(s, name, addrlen);
1766 memcpy(name, si->myname, si->myname_len);
1767 *addrlen = si->myname_len;
1772 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1774 struct socket_info *si = find_socket_info(s);
1777 return real_getsockopt(s, level, optname, optval, optlen);
1780 if (level == SOL_SOCKET) {
1781 return real_getsockopt(s, level, optname, optval, optlen);
1784 errno = ENOPROTOOPT;
1788 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1790 struct socket_info *si = find_socket_info(s);
1793 return real_setsockopt(s, level, optname, optval, optlen);
1796 if (level == SOL_SOCKET) {
1797 return real_setsockopt(s, level, optname, optval, optlen);
1800 switch (si->family) {
1804 errno = ENOPROTOOPT;
1809 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1811 struct sockaddr_un un_addr;
1812 socklen_t un_addrlen = sizeof(un_addr);
1814 struct socket_info *si = find_socket_info(s);
1815 struct sockaddr_storage ss;
1816 socklen_t ss_len = sizeof(ss);
1819 return real_recvfrom(s, buf, len, flags, from, fromlen);
1823 from = (struct sockaddr *)&ss;
1827 len = MIN(len, 1500);
1829 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1830 memset(&un_addr, 0, sizeof(un_addr));
1831 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1835 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1836 si->family, from, fromlen) == -1) {
1840 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1846 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1848 struct sockaddr_un un_addr;
1850 struct socket_info *si = find_socket_info(s);
1854 return real_sendto(s, buf, len, flags, to, tolen);
1857 if (si->connected) {
1864 tolen = si->peername_len;
1867 len = MIN(len, 1500);
1871 ret = real_send(s, buf, len, flags);
1874 if (si->bound == 0) {
1875 ret = swrap_auto_bind(si);
1876 if (ret == -1) return -1;
1879 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1880 if (ret == -1) return -1;
1885 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1888 type = SOCKET_TYPE_CHAR_UDP;
1890 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1891 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1892 socket_wrapper_dir(), type, iface, prt);
1893 if (stat(un_addr.sun_path, &st) != 0) continue;
1895 /* ignore the any errors in broadcast sends */
1896 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1899 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1904 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1908 errno = EHOSTUNREACH;
1912 /* to give better errors */
1913 if (ret == -1 && errno == ENOENT) {
1914 errno = EHOSTUNREACH;
1918 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1919 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1921 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1927 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1930 struct socket_info *si = find_socket_info(s);
1934 return real_ioctl(s, r, p);
1937 ret = real_ioctl(s, r, p);
1941 value = *((int *)p);
1942 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1943 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1944 } else if (value == 0) { /* END OF FILE */
1945 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1953 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1956 struct socket_info *si = find_socket_info(s);
1959 return real_recv(s, buf, len, flags);
1962 len = MIN(len, 1500);
1964 ret = real_recv(s, buf, len, flags);
1965 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1966 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1967 } else if (ret == 0) { /* END OF FILE */
1968 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1969 } else if (ret > 0) {
1970 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1977 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1980 struct socket_info *si = find_socket_info(s);
1983 return real_send(s, buf, len, flags);
1986 len = MIN(len, 1500);
1988 ret = real_send(s, buf, len, flags);
1991 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1992 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1994 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2000 _PUBLIC_ int swrap_close(int fd)
2002 struct socket_info *si = find_socket_info(fd);
2006 return real_close(fd);
2009 SWRAP_DLIST_REMOVE(sockets, si);
2011 if (si->myname && si->peername) {
2012 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2015 ret = real_close(fd);
2017 if (si->myname && si->peername) {
2018 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2019 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2022 if (si->path) free(si->path);
2023 if (si->myname) free(si->myname);
2024 if (si->peername) free(si->peername);
2026 unlink(si->tmp_path);