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);
209 struct sockaddr *myname;
210 socklen_t myname_len;
212 struct sockaddr *peername;
213 socklen_t peername_len;
216 unsigned long pck_snd;
217 unsigned long pck_rcv;
220 struct socket_info *prev, *next;
223 static struct socket_info *sockets;
225 const char *socket_wrapper_dir(void)
227 const char *s = getenv("SOCKET_WRAPPER_DIR");
231 if (strncmp(s, "./", 2) == 0) {
237 unsigned int socket_wrapper_default_iface(void)
239 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
242 if (sscanf(s, "%u", &iface) == 1) {
243 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
249 return 1;/* 127.0.0.1 */
252 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
259 p = strrchr(un->sun_path, '/');
260 if (p) p++; else p = un->sun_path;
262 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
267 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
278 case SOCKET_TYPE_CHAR_TCP:
279 case SOCKET_TYPE_CHAR_UDP: {
280 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
282 if ((*len) < sizeof(*in2)) {
287 memset(in2, 0, sizeof(*in2));
288 in2->sin_family = AF_INET;
289 in2->sin_addr.s_addr = htonl((127<<24) | iface);
290 in2->sin_port = htons(prt);
296 case SOCKET_TYPE_CHAR_TCP_V6:
297 case SOCKET_TYPE_CHAR_UDP_V6: {
298 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
300 if ((*len) < sizeof(*in2)) {
305 memset(in2, 0, sizeof(*in2));
306 in2->sin6_family = AF_INET6;
307 in2->sin6_addr = swrap_ipv6;
308 in2->sin6_addr.s6_addr[15] = iface;
309 in2->sin6_port = htons(prt);
323 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
331 if (bcast) *bcast = 0;
333 switch (si->family) {
335 const struct sockaddr_in *in =
336 (const struct sockaddr_in *)inaddr;
337 unsigned int addr = ntohl(in->sin_addr.s_addr);
344 u_type = SOCKET_TYPE_CHAR_TCP;
347 u_type = SOCKET_TYPE_CHAR_UDP;
348 a_type = SOCKET_TYPE_CHAR_UDP;
349 b_type = SOCKET_TYPE_CHAR_UDP;
353 prt = ntohs(in->sin_port);
354 if (a_type && addr == 0xFFFFFFFF) {
355 /* 255.255.255.255 only udp */
358 iface = socket_wrapper_default_iface();
359 } else if (b_type && addr == 0x7FFFFFFF) {
360 /* 127.255.255.255 only udp */
363 iface = socket_wrapper_default_iface();
364 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
368 iface = (addr & 0x000000FF);
373 if (bcast) *bcast = is_bcast;
378 const struct sockaddr_in6 *in =
379 (const struct sockaddr_in6 *)inaddr;
384 type = SOCKET_TYPE_CHAR_TCP_V6;
387 type = SOCKET_TYPE_CHAR_UDP_V6;
391 /* XXX no multicast/broadcast */
393 prt = ntohs(in->sin6_port);
397 if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) {
398 iface = in->sin6_addr.s6_addr[15];
418 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
419 socket_wrapper_dir());
420 /* the caller need to do more processing */
424 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
425 socket_wrapper_dir(), type, iface, prt);
430 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
439 if (bcast) *bcast = 0;
441 switch (si->family) {
443 const struct sockaddr_in *in =
444 (const struct sockaddr_in *)inaddr;
445 unsigned int addr = ntohl(in->sin_addr.s_addr);
451 prt = ntohs(in->sin_port);
455 u_type = SOCKET_TYPE_CHAR_TCP;
456 d_type = SOCKET_TYPE_CHAR_TCP;
459 u_type = SOCKET_TYPE_CHAR_UDP;
460 d_type = SOCKET_TYPE_CHAR_UDP;
461 a_type = SOCKET_TYPE_CHAR_UDP;
462 b_type = SOCKET_TYPE_CHAR_UDP;
470 iface = socket_wrapper_default_iface();
471 } else if (a_type && addr == 0xFFFFFFFF) {
472 /* 255.255.255.255 only udp */
475 iface = socket_wrapper_default_iface();
476 } else if (b_type && addr == 0x7FFFFFFF) {
477 /* 127.255.255.255 only udp */
480 iface = socket_wrapper_default_iface();
481 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
485 iface = (addr & 0x000000FF);
487 errno = EADDRNOTAVAIL;
494 const struct sockaddr_in6 *in =
495 (const struct sockaddr_in6 *)inaddr;
500 type = SOCKET_TYPE_CHAR_TCP_V6;
503 type = SOCKET_TYPE_CHAR_UDP_V6;
507 /* XXX no multicast/broadcast */
509 prt = ntohs(in->sin6_port);
513 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
514 iface = socket_wrapper_default_iface();
515 } else if (IN6_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) {
516 iface = in->sin6_addr.s6_addr[15];
518 errno = EADDRNOTAVAIL;
526 errno = EADDRNOTAVAIL;
531 if (bcast) *bcast = is_bcast;
534 /* handle auto-allocation of ephemeral ports */
535 for (prt = 5001; prt < 10000; prt++) {
536 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
537 socket_wrapper_dir(), type, iface, prt);
538 if (stat(un->sun_path, &st) == 0) continue;
540 set_port(si->family, prt, si->myname);
549 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
550 socket_wrapper_dir(), type, iface, prt);
554 static struct socket_info *find_socket_info(int fd)
556 struct socket_info *i;
557 for (i = sockets; i; i = i->next) {
565 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
566 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
571 out_addr->sun_family = AF_UNIX;
573 switch (in_addr->sa_family) {
583 errno = ESOCKTNOSUPPORT;
587 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
589 return convert_in_un_remote(si, in_addr, out_addr, bcast);
595 errno = EAFNOSUPPORT;
599 static int sockaddr_convert_from_un(const struct socket_info *si,
600 const struct sockaddr_un *in_addr,
601 socklen_t un_addrlen,
603 struct sockaddr *out_addr,
604 socklen_t *out_addrlen)
606 if (out_addr == NULL || out_addrlen == NULL)
609 if (un_addrlen == 0) {
624 errno = ESOCKTNOSUPPORT;
627 return convert_un_in(in_addr, out_addr, out_addrlen);
632 errno = EAFNOSUPPORT;
636 enum swrap_packet_type {
638 SWRAP_CONNECT_UNREACH,
646 SWRAP_SENDTO_UNREACH,
657 struct swrap_file_hdr {
659 uint16_t version_major;
660 uint16_t version_minor;
663 uint32_t frame_max_len;
664 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
667 #define SWRAP_FILE_HDR_SIZE 24
669 struct swrap_packet_frame {
671 uint32_t micro_seconds;
672 uint32_t recorded_length;
673 uint32_t full_length;
675 #define SWRAP_PACKET_FRAME_SIZE 16
677 union swrap_packet_ip {
681 uint16_t packet_length;
682 uint16_t identification;
687 uint16_t hdr_checksum;
691 #define SWRAP_PACKET_IP_V4_SIZE 20
694 uint8_t flow_label_high;
695 uint16_t flow_label_low;
696 uint16_t payload_length;
699 uint8_t src_addr[16];
700 uint8_t dest_addr[16];
702 #define SWRAP_PACKET_IP_V6_SIZE 40
704 #define SWRAP_PACKET_IP_SIZE 40
706 union swrap_packet_payload {
708 uint16_t source_port;
718 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
720 uint16_t source_port;
725 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
732 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
739 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
741 #define SWRAP_PACKET_PAYLOAD_SIZE 20
743 #define SWRAP_PACKET_MIN_ALLOC \
744 (SWRAP_PACKET_FRAME_SIZE + \
745 SWRAP_PACKET_IP_SIZE + \
746 SWRAP_PACKET_PAYLOAD_SIZE)
748 static const char *socket_wrapper_pcap_file(void)
750 static int initialized = 0;
751 static const char *s = NULL;
752 static const struct swrap_file_hdr h;
753 static const struct swrap_packet_frame f;
754 static const union swrap_packet_ip i;
755 static const union swrap_packet_payload p;
757 if (initialized == 1) {
763 * TODO: don't use the structs use plain buffer offsets
764 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
766 * for now make sure we disable PCAP support
767 * if the struct has alignment!
769 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
772 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
775 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
778 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
781 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
784 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
787 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
790 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
793 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
796 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
800 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
804 if (strncmp(s, "./", 2) == 0) {
810 static uint8_t *swrap_packet_init(struct timeval *tval,
811 const struct sockaddr *src,
812 const struct sockaddr *dest,
814 const uint8_t *payload,
816 unsigned long tcp_seqno,
817 unsigned long tcp_ack,
818 unsigned char tcp_ctl,
824 struct swrap_packet_frame *frame;
825 union swrap_packet_ip *ip;
826 union swrap_packet_payload *pay;
829 size_t nonwire_len = sizeof(*frame);
830 size_t wire_hdr_len = 0;
832 size_t ip_hdr_len = 0;
833 size_t icmp_hdr_len = 0;
834 size_t icmp_truncate_len = 0;
835 uint8_t protocol = 0, icmp_protocol = 0;
836 const struct sockaddr_in *src_in = NULL;
837 const struct sockaddr_in *dest_in = NULL;
839 const struct sockaddr_in6 *src_in6 = NULL;
840 const struct sockaddr_in6 *dest_in6 = NULL;
845 switch (src->sa_family) {
847 src_in = (const struct sockaddr_in *)src;
848 dest_in = (const struct sockaddr_in *)dest;
849 src_port = src_in->sin_port;
850 dest_port = dest_in->sin_port;
851 ip_hdr_len = sizeof(ip->v4);
855 src_in6 = (const struct sockaddr_in6 *)src;
856 dest_in6 = (const struct sockaddr_in6 *)dest;
857 src_port = src_in6->sin6_port;
858 dest_port = dest_in6->sin6_port;
859 ip_hdr_len = sizeof(ip->v6);
866 switch (socket_type) {
868 protocol = 0x06; /* TCP */
869 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
870 wire_len = wire_hdr_len + payload_len;
874 protocol = 0x11; /* UDP */
875 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
876 wire_len = wire_hdr_len + payload_len;
884 icmp_protocol = protocol;
885 switch (src->sa_family) {
887 protocol = 0x01; /* ICMPv4 */
888 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
892 protocol = 0x3A; /* ICMPv6 */
893 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
897 if (wire_len > 64 ) {
898 icmp_truncate_len = wire_len - 64;
900 wire_hdr_len += icmp_hdr_len;
901 wire_len += icmp_hdr_len;
904 packet_len = nonwire_len + wire_len;
905 alloc_len = packet_len;
906 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
907 alloc_len = SWRAP_PACKET_MIN_ALLOC;
910 base = (uint8_t *)malloc(alloc_len);
911 if (!base) return NULL;
915 frame = (struct swrap_packet_frame *)buf;
916 frame->seconds = tval->tv_sec;
917 frame->micro_seconds = tval->tv_usec;
918 frame->recorded_length = wire_len - icmp_truncate_len;
919 frame->full_length = wire_len - icmp_truncate_len;
920 buf += SWRAP_PACKET_FRAME_SIZE;
922 ip = (union swrap_packet_ip *)buf;
923 switch (src->sa_family) {
925 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
927 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
928 ip->v4.identification = htons(0xFFFF);
929 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
930 ip->v4.fragment = htons(0x0000);
932 ip->v4.protocol = protocol;
933 ip->v4.hdr_checksum = htons(0x0000);
934 ip->v4.src_addr = src_in->sin_addr.s_addr;
935 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
936 buf += SWRAP_PACKET_IP_V4_SIZE;
940 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
941 ip->v6.flow_label_high = 0x00;
942 ip->v6.flow_label_low = 0x0000;
943 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
944 ip->v6.next_header = protocol;
945 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
946 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
947 buf += SWRAP_PACKET_IP_V6_SIZE;
953 pay = (union swrap_packet_payload *)buf;
954 switch (src->sa_family) {
956 pay->icmp4.type = 0x03; /* destination unreachable */
957 pay->icmp4.code = 0x01; /* host unreachable */
958 pay->icmp4.checksum = htons(0x0000);
959 pay->icmp4.unused = htonl(0x00000000);
960 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
962 /* set the ip header in the ICMP payload */
963 ip = (union swrap_packet_ip *)buf;
964 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
966 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
967 ip->v4.identification = htons(0xFFFF);
968 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
969 ip->v4.fragment = htons(0x0000);
971 ip->v4.protocol = icmp_protocol;
972 ip->v4.hdr_checksum = htons(0x0000);
973 ip->v4.src_addr = dest_in->sin_addr.s_addr;
974 ip->v4.dest_addr = src_in->sin_addr.s_addr;
975 buf += SWRAP_PACKET_IP_V4_SIZE;
977 src_port = dest_in->sin_port;
978 dest_port = src_in->sin_port;
982 pay->icmp6.type = 0x01; /* destination unreachable */
983 pay->icmp6.code = 0x03; /* address unreachable */
984 pay->icmp6.checksum = htons(0x0000);
985 pay->icmp6.unused = htonl(0x00000000);
986 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
988 /* set the ip header in the ICMP payload */
989 ip = (union swrap_packet_ip *)buf;
990 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
991 ip->v6.flow_label_high = 0x00;
992 ip->v6.flow_label_low = 0x0000;
993 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
994 ip->v6.next_header = protocol;
995 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
996 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
997 buf += SWRAP_PACKET_IP_V6_SIZE;
999 src_port = dest_in6->sin6_port;
1000 dest_port = src_in6->sin6_port;
1006 pay = (union swrap_packet_payload *)buf;
1008 switch (socket_type) {
1010 pay->tcp.source_port = src_port;
1011 pay->tcp.dest_port = dest_port;
1012 pay->tcp.seq_num = htonl(tcp_seqno);
1013 pay->tcp.ack_num = htonl(tcp_ack);
1014 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1015 pay->tcp.control = tcp_ctl;
1016 pay->tcp.window = htons(0x7FFF);
1017 pay->tcp.checksum = htons(0x0000);
1018 pay->tcp.urg = htons(0x0000);
1019 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1024 pay->udp.source_port = src_port;
1025 pay->udp.dest_port = dest_port;
1026 pay->udp.length = htons(8 + payload_len);
1027 pay->udp.checksum = htons(0x0000);
1028 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1033 if (payload && payload_len > 0) {
1034 memcpy(buf, payload, payload_len);
1037 *_packet_len = packet_len - icmp_truncate_len;
1041 static int swrap_get_pcap_fd(const char *fname)
1045 if (fd != -1) return fd;
1047 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1049 struct swrap_file_hdr file_hdr;
1050 file_hdr.magic = 0xA1B2C3D4;
1051 file_hdr.version_major = 0x0002;
1052 file_hdr.version_minor = 0x0004;
1053 file_hdr.timezone = 0x00000000;
1054 file_hdr.sigfigs = 0x00000000;
1055 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1056 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1058 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1065 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1070 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1071 const struct sockaddr *addr,
1072 enum swrap_packet_type type,
1073 const void *buf, size_t len,
1076 const struct sockaddr *src_addr;
1077 const struct sockaddr *dest_addr;
1078 unsigned long tcp_seqno = 0;
1079 unsigned long tcp_ack = 0;
1080 unsigned char tcp_ctl = 0;
1081 int unreachable = 0;
1085 switch (si->family) {
1095 case SWRAP_CONNECT_SEND:
1096 if (si->type != SOCK_STREAM) return NULL;
1098 src_addr = si->myname;
1101 tcp_seqno = si->io.pck_snd;
1102 tcp_ack = si->io.pck_rcv;
1103 tcp_ctl = 0x02; /* SYN */
1105 si->io.pck_snd += 1;
1109 case SWRAP_CONNECT_RECV:
1110 if (si->type != SOCK_STREAM) return NULL;
1112 dest_addr = si->myname;
1115 tcp_seqno = si->io.pck_rcv;
1116 tcp_ack = si->io.pck_snd;
1117 tcp_ctl = 0x12; /** SYN,ACK */
1119 si->io.pck_rcv += 1;
1123 case SWRAP_CONNECT_UNREACH:
1124 if (si->type != SOCK_STREAM) return NULL;
1126 dest_addr = si->myname;
1129 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1130 tcp_seqno = si->io.pck_snd - 1;
1131 tcp_ack = si->io.pck_rcv;
1132 tcp_ctl = 0x02; /* SYN */
1137 case SWRAP_CONNECT_ACK:
1138 if (si->type != SOCK_STREAM) return NULL;
1140 src_addr = si->myname;
1143 tcp_seqno = si->io.pck_snd;
1144 tcp_ack = si->io.pck_rcv;
1145 tcp_ctl = 0x10; /* ACK */
1149 case SWRAP_ACCEPT_SEND:
1150 if (si->type != SOCK_STREAM) return NULL;
1152 dest_addr = si->myname;
1155 tcp_seqno = si->io.pck_rcv;
1156 tcp_ack = si->io.pck_snd;
1157 tcp_ctl = 0x02; /* SYN */
1159 si->io.pck_rcv += 1;
1163 case SWRAP_ACCEPT_RECV:
1164 if (si->type != SOCK_STREAM) return NULL;
1166 src_addr = si->myname;
1169 tcp_seqno = si->io.pck_snd;
1170 tcp_ack = si->io.pck_rcv;
1171 tcp_ctl = 0x12; /* SYN,ACK */
1173 si->io.pck_snd += 1;
1177 case SWRAP_ACCEPT_ACK:
1178 if (si->type != SOCK_STREAM) return NULL;
1180 dest_addr = si->myname;
1183 tcp_seqno = si->io.pck_rcv;
1184 tcp_ack = si->io.pck_snd;
1185 tcp_ctl = 0x10; /* ACK */
1190 src_addr = si->myname;
1191 dest_addr = si->peername;
1193 tcp_seqno = si->io.pck_snd;
1194 tcp_ack = si->io.pck_rcv;
1195 tcp_ctl = 0x18; /* PSH,ACK */
1197 si->io.pck_snd += len;
1201 case SWRAP_SEND_RST:
1202 dest_addr = si->myname;
1203 src_addr = si->peername;
1205 if (si->type == SOCK_DGRAM) {
1206 return swrap_marshall_packet(si, si->peername,
1207 SWRAP_SENDTO_UNREACH,
1208 buf, len, packet_len);
1211 tcp_seqno = si->io.pck_rcv;
1212 tcp_ack = si->io.pck_snd;
1213 tcp_ctl = 0x14; /** RST,ACK */
1217 case SWRAP_PENDING_RST:
1218 dest_addr = si->myname;
1219 src_addr = si->peername;
1221 if (si->type == SOCK_DGRAM) {
1225 tcp_seqno = si->io.pck_rcv;
1226 tcp_ack = si->io.pck_snd;
1227 tcp_ctl = 0x14; /* RST,ACK */
1232 dest_addr = si->myname;
1233 src_addr = si->peername;
1235 tcp_seqno = si->io.pck_rcv;
1236 tcp_ack = si->io.pck_snd;
1237 tcp_ctl = 0x18; /* PSH,ACK */
1239 si->io.pck_rcv += len;
1243 case SWRAP_RECV_RST:
1244 dest_addr = si->myname;
1245 src_addr = si->peername;
1247 if (si->type == SOCK_DGRAM) {
1251 tcp_seqno = si->io.pck_rcv;
1252 tcp_ack = si->io.pck_snd;
1253 tcp_ctl = 0x14; /* RST,ACK */
1258 src_addr = si->myname;
1261 si->io.pck_snd += len;
1265 case SWRAP_SENDTO_UNREACH:
1266 dest_addr = si->myname;
1273 case SWRAP_RECVFROM:
1274 dest_addr = si->myname;
1277 si->io.pck_rcv += len;
1281 case SWRAP_CLOSE_SEND:
1282 if (si->type != SOCK_STREAM) return NULL;
1284 src_addr = si->myname;
1285 dest_addr = si->peername;
1287 tcp_seqno = si->io.pck_snd;
1288 tcp_ack = si->io.pck_rcv;
1289 tcp_ctl = 0x11; /* FIN, ACK */
1291 si->io.pck_snd += 1;
1295 case SWRAP_CLOSE_RECV:
1296 if (si->type != SOCK_STREAM) return NULL;
1298 dest_addr = si->myname;
1299 src_addr = si->peername;
1301 tcp_seqno = si->io.pck_rcv;
1302 tcp_ack = si->io.pck_snd;
1303 tcp_ctl = 0x11; /* FIN,ACK */
1305 si->io.pck_rcv += 1;
1309 case SWRAP_CLOSE_ACK:
1310 if (si->type != SOCK_STREAM) return NULL;
1312 src_addr = si->myname;
1313 dest_addr = si->peername;
1315 tcp_seqno = si->io.pck_snd;
1316 tcp_ack = si->io.pck_rcv;
1317 tcp_ctl = 0x10; /* ACK */
1324 swrapGetTimeOfDay(&tv);
1326 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1327 (const uint8_t *)buf, len,
1328 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1332 static void swrap_dump_packet(struct socket_info *si,
1333 const struct sockaddr *addr,
1334 enum swrap_packet_type type,
1335 const void *buf, size_t len)
1337 const char *file_name;
1339 size_t packet_len = 0;
1342 file_name = socket_wrapper_pcap_file();
1347 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1352 fd = swrap_get_pcap_fd(file_name);
1354 if (write(fd, packet, packet_len) != packet_len) {
1363 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1365 struct socket_info *si;
1368 if (!socket_wrapper_dir()) {
1369 return real_socket(family, type, protocol);
1379 return real_socket(family, type, protocol);
1381 errno = EAFNOSUPPORT;
1391 errno = EPROTONOSUPPORT;
1399 if (type == SOCK_STREAM) {
1404 if (type == SOCK_DGRAM) {
1409 errno = EPROTONOSUPPORT;
1413 fd = real_socket(AF_UNIX, type, 0);
1415 if (fd == -1) return -1;
1417 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1419 si->family = family;
1421 si->protocol = protocol;
1424 SWRAP_DLIST_ADD(sockets, si);
1429 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1431 struct socket_info *parent_si, *child_si;
1433 struct sockaddr_un un_addr;
1434 socklen_t un_addrlen = sizeof(un_addr);
1435 struct sockaddr_un un_my_addr;
1436 socklen_t un_my_addrlen = sizeof(un_my_addr);
1437 struct sockaddr *my_addr;
1438 socklen_t my_addrlen, len;
1441 parent_si = find_socket_info(s);
1443 return real_accept(s, addr, addrlen);
1447 * assume out sockaddr have the same size as the in parent
1450 my_addrlen = socket_length(parent_si->family);
1451 if (my_addrlen <= 0) {
1456 my_addr = (struct sockaddr *)malloc(my_addrlen);
1457 if (my_addr == NULL) {
1461 memset(&un_addr, 0, sizeof(un_addr));
1462 memset(&un_my_addr, 0, sizeof(un_my_addr));
1464 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1473 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1474 parent_si->family, my_addr, &len);
1481 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1482 memset(child_si, 0, sizeof(*child_si));
1485 child_si->family = parent_si->family;
1486 child_si->type = parent_si->type;
1487 child_si->protocol = parent_si->protocol;
1488 child_si->bound = 1;
1489 child_si->is_server = 1;
1491 child_si->peername_len = len;
1492 child_si->peername = sockaddr_dup(my_addr, len);
1494 if (addr != NULL && addrlen != NULL) {
1496 if (*addrlen >= len)
1497 memcpy(addr, my_addr, len);
1501 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1509 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1510 child_si->family, my_addr, &len);
1518 child_si->myname_len = len;
1519 child_si->myname = sockaddr_dup(my_addr, len);
1522 SWRAP_DLIST_ADD(sockets, child_si);
1524 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1525 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1526 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1531 static int autobind_start_init;
1532 static int autobind_start;
1534 /* using sendto() or connect() on an unbound socket would give the
1535 recipient no way to reply, as unlike UDP and TCP, a unix domain
1536 socket can't auto-assign emphemeral port numbers, so we need to
1538 static int swrap_auto_bind(struct socket_info *si)
1540 struct sockaddr_un un_addr;
1547 if (autobind_start_init != 1) {
1548 autobind_start_init = 1;
1549 autobind_start = getpid();
1550 autobind_start %= 50000;
1551 autobind_start += 10000;
1554 un_addr.sun_family = AF_UNIX;
1556 switch (si->family) {
1558 struct sockaddr_in in;
1562 type = SOCKET_TYPE_CHAR_TCP;
1565 type = SOCKET_TYPE_CHAR_UDP;
1568 errno = ESOCKTNOSUPPORT;
1572 memset(&in, 0, sizeof(in));
1573 in.sin_family = AF_INET;
1574 in.sin_addr.s_addr = htonl(127<<24 |
1575 socket_wrapper_default_iface());
1577 si->myname_len = sizeof(in);
1578 si->myname = sockaddr_dup(&in, si->myname_len);
1583 struct sockaddr_in6 in6;
1587 type = SOCKET_TYPE_CHAR_TCP_V6;
1590 type = SOCKET_TYPE_CHAR_UDP_V6;
1593 errno = ESOCKTNOSUPPORT;
1597 memset(&in6, 0, sizeof(in6));
1598 in6.sin6_family = AF_INET6;
1599 in6.sin6_addr = swrap_ipv6;
1600 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1601 si->myname_len = sizeof(in6);
1602 si->myname = sockaddr_dup(&in6, si->myname_len);
1607 errno = ESOCKTNOSUPPORT;
1611 if (autobind_start > 60000) {
1612 autobind_start = 10000;
1615 for (i=0;i<1000;i++) {
1616 port = autobind_start + i;
1617 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1618 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1619 type, socket_wrapper_default_iface(), port);
1620 if (stat(un_addr.sun_path, &st) == 0) continue;
1622 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1623 if (ret == -1) return ret;
1625 si->tmp_path = strdup(un_addr.sun_path);
1627 autobind_start = port + 1;
1635 set_port(si->family, port, si->myname);
1641 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1644 struct sockaddr_un un_addr;
1645 struct socket_info *si = find_socket_info(s);
1648 return real_connect(s, serv_addr, addrlen);
1651 if (si->bound == 0) {
1652 ret = swrap_auto_bind(si);
1653 if (ret == -1) return -1;
1656 if (si->family != serv_addr->sa_family) {
1661 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1662 if (ret == -1) return -1;
1664 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1666 ret = real_connect(s, (struct sockaddr *)&un_addr,
1667 sizeof(struct sockaddr_un));
1669 /* to give better errors */
1670 if (ret == -1 && errno == ENOENT) {
1671 errno = EHOSTUNREACH;
1675 si->peername_len = addrlen;
1676 si->peername = sockaddr_dup(serv_addr, addrlen);
1678 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1679 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1681 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1687 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1690 struct sockaddr_un un_addr;
1691 struct socket_info *si = find_socket_info(s);
1694 return real_bind(s, myaddr, addrlen);
1697 si->myname_len = addrlen;
1698 si->myname = sockaddr_dup(myaddr, addrlen);
1700 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1701 if (ret == -1) return -1;
1703 unlink(un_addr.sun_path);
1705 ret = real_bind(s, (struct sockaddr *)&un_addr,
1706 sizeof(struct sockaddr_un));
1715 _PUBLIC_ int swrap_listen(int s, int backlog)
1718 struct socket_info *si = find_socket_info(s);
1721 return real_listen(s, backlog);
1724 ret = real_listen(s, backlog);
1729 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1731 struct socket_info *si = find_socket_info(s);
1734 return real_getpeername(s, name, addrlen);
1743 memcpy(name, si->peername, si->peername_len);
1744 *addrlen = si->peername_len;
1749 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1751 struct socket_info *si = find_socket_info(s);
1754 return real_getsockname(s, name, addrlen);
1757 memcpy(name, si->myname, si->myname_len);
1758 *addrlen = si->myname_len;
1763 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1765 struct socket_info *si = find_socket_info(s);
1768 return real_getsockopt(s, level, optname, optval, optlen);
1771 if (level == SOL_SOCKET) {
1772 return real_getsockopt(s, level, optname, optval, optlen);
1775 errno = ENOPROTOOPT;
1779 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1781 struct socket_info *si = find_socket_info(s);
1784 return real_setsockopt(s, level, optname, optval, optlen);
1787 if (level == SOL_SOCKET) {
1788 return real_setsockopt(s, level, optname, optval, optlen);
1791 switch (si->family) {
1795 errno = ENOPROTOOPT;
1800 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1802 struct sockaddr_un un_addr;
1803 socklen_t un_addrlen = sizeof(un_addr);
1805 struct socket_info *si = find_socket_info(s);
1808 return real_recvfrom(s, buf, len, flags, from, fromlen);
1811 len = MIN(len, 1500);
1813 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1814 memset(&un_addr, 0, sizeof(un_addr));
1815 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1819 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1820 si->family, from, fromlen) == -1) {
1824 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1830 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1832 struct sockaddr_un un_addr;
1834 struct socket_info *si = find_socket_info(s);
1838 return real_sendto(s, buf, len, flags, to, tolen);
1841 len = MIN(len, 1500);
1845 ret = real_send(s, buf, len, flags);
1848 if (si->bound == 0) {
1849 ret = swrap_auto_bind(si);
1850 if (ret == -1) return -1;
1853 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1854 if (ret == -1) return -1;
1859 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1862 type = SOCKET_TYPE_CHAR_UDP;
1864 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1865 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1866 socket_wrapper_dir(), type, iface, prt);
1867 if (stat(un_addr.sun_path, &st) != 0) continue;
1869 /* ignore the any errors in broadcast sends */
1870 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1873 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1878 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1882 errno = EHOSTUNREACH;
1886 /* to give better errors */
1887 if (ret == -1 && errno == ENOENT) {
1888 errno = EHOSTUNREACH;
1892 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1893 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1895 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1901 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1904 struct socket_info *si = find_socket_info(s);
1908 return real_ioctl(s, r, p);
1911 ret = real_ioctl(s, r, p);
1915 value = *((int *)p);
1916 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1917 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1918 } else if (value == 0) { /* END OF FILE */
1919 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1927 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1930 struct socket_info *si = find_socket_info(s);
1933 return real_recv(s, buf, len, flags);
1936 len = MIN(len, 1500);
1938 ret = real_recv(s, buf, len, flags);
1939 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1940 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1941 } else if (ret == 0) { /* END OF FILE */
1942 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1943 } else if (ret > 0) {
1944 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1951 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1954 struct socket_info *si = find_socket_info(s);
1957 return real_send(s, buf, len, flags);
1960 len = MIN(len, 1500);
1962 ret = real_send(s, buf, len, flags);
1965 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1966 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1968 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1974 _PUBLIC_ int swrap_close(int fd)
1976 struct socket_info *si = find_socket_info(fd);
1980 return real_close(fd);
1983 SWRAP_DLIST_REMOVE(sockets, si);
1985 if (si->myname && si->peername) {
1986 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1989 ret = real_close(fd);
1991 if (si->myname && si->peername) {
1992 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1993 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1996 if (si->path) free(si->path);
1997 if (si->myname) free(si->myname);
1998 if (si->peername) free(si->peername);
2000 unlink(si->tmp_path);