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_ARE_ADDR_EQUAL(&swrap_ipv6, &cmp)) {
514 iface = in->sin6_addr.s6_addr[15];
516 errno = EADDRNOTAVAIL;
524 errno = EADDRNOTAVAIL;
529 if (bcast) *bcast = is_bcast;
532 /* handle auto-allocation of ephemeral ports */
533 for (prt = 5001; prt < 10000; prt++) {
534 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
535 socket_wrapper_dir(), type, iface, prt);
536 if (stat(un->sun_path, &st) == 0) continue;
538 set_port(si->family, prt, si->myname);
547 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
548 socket_wrapper_dir(), type, iface, prt);
552 static struct socket_info *find_socket_info(int fd)
554 struct socket_info *i;
555 for (i = sockets; i; i = i->next) {
563 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
564 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
569 out_addr->sun_family = AF_UNIX;
571 switch (in_addr->sa_family) {
581 errno = ESOCKTNOSUPPORT;
585 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
587 return convert_in_un_remote(si, in_addr, out_addr, bcast);
593 errno = EAFNOSUPPORT;
597 static int sockaddr_convert_from_un(const struct socket_info *si,
598 const struct sockaddr_un *in_addr,
599 socklen_t un_addrlen,
601 struct sockaddr *out_addr,
602 socklen_t *out_addrlen)
604 if (out_addr == NULL || out_addrlen == NULL)
607 if (un_addrlen == 0) {
622 errno = ESOCKTNOSUPPORT;
625 return convert_un_in(in_addr, out_addr, out_addrlen);
630 errno = EAFNOSUPPORT;
634 enum swrap_packet_type {
636 SWRAP_CONNECT_UNREACH,
644 SWRAP_SENDTO_UNREACH,
655 struct swrap_file_hdr {
657 uint16_t version_major;
658 uint16_t version_minor;
661 uint32_t frame_max_len;
662 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
665 #define SWRAP_FILE_HDR_SIZE 24
667 struct swrap_packet_frame {
669 uint32_t micro_seconds;
670 uint32_t recorded_length;
671 uint32_t full_length;
673 #define SWRAP_PACKET_FRAME_SIZE 16
675 union swrap_packet_ip {
679 uint16_t packet_length;
680 uint16_t identification;
685 uint16_t hdr_checksum;
689 #define SWRAP_PACKET_IP_V4_SIZE 20
692 uint8_t flow_label_high;
693 uint16_t flow_label_low;
694 uint16_t payload_length;
697 uint8_t src_addr[16];
698 uint8_t dest_addr[16];
700 #define SWRAP_PACKET_IP_V6_SIZE 40
702 #define SWRAP_PACKET_IP_SIZE 40
704 union swrap_packet_payload {
706 uint16_t source_port;
716 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
718 uint16_t source_port;
723 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
730 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
737 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
739 #define SWRAP_PACKET_PAYLOAD_SIZE 20
741 #define SWRAP_PACKET_MIN_ALLOC \
742 (SWRAP_PACKET_FRAME_SIZE + \
743 SWRAP_PACKET_IP_SIZE + \
744 SWRAP_PACKET_PAYLOAD_SIZE)
746 static const char *socket_wrapper_pcap_file(void)
748 static int initialized = 0;
749 static const char *s = NULL;
750 static const struct swrap_file_hdr h;
751 static const struct swrap_packet_frame f;
752 static const union swrap_packet_ip i;
753 static const union swrap_packet_payload p;
755 if (initialized == 1) {
761 * TODO: don't use the structs use plain buffer offsets
762 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
764 * for now make sure we disable PCAP support
765 * if the struct has alignment!
767 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
770 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
773 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
776 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
779 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
782 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
785 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
788 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
791 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
794 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
798 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
802 if (strncmp(s, "./", 2) == 0) {
808 static uint8_t *swrap_packet_init(struct timeval *tval,
809 const struct sockaddr *src,
810 const struct sockaddr *dest,
812 const uint8_t *payload,
814 unsigned long tcp_seqno,
815 unsigned long tcp_ack,
816 unsigned char tcp_ctl,
822 struct swrap_packet_frame *frame;
823 union swrap_packet_ip *ip;
824 union swrap_packet_payload *pay;
827 size_t nonwire_len = sizeof(*frame);
828 size_t wire_hdr_len = 0;
830 size_t ip_hdr_len = 0;
831 size_t icmp_hdr_len = 0;
832 size_t icmp_truncate_len = 0;
833 uint8_t protocol = 0, icmp_protocol = 0;
834 const struct sockaddr_in *src_in = NULL;
835 const struct sockaddr_in *dest_in = NULL;
837 const struct sockaddr_in6 *src_in6 = NULL;
838 const struct sockaddr_in6 *dest_in6 = NULL;
843 switch (src->sa_family) {
845 src_in = (const struct sockaddr_in *)src;
846 dest_in = (const struct sockaddr_in *)dest;
847 src_port = src_in->sin_port;
848 dest_port = dest_in->sin_port;
849 ip_hdr_len = sizeof(ip->v4);
853 src_in6 = (const struct sockaddr_in6 *)src;
854 dest_in6 = (const struct sockaddr_in6 *)dest;
855 src_port = src_in6->sin6_port;
856 dest_port = dest_in6->sin6_port;
857 ip_hdr_len = sizeof(ip->v6);
864 switch (socket_type) {
866 protocol = 0x06; /* TCP */
867 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
868 wire_len = wire_hdr_len + payload_len;
872 protocol = 0x11; /* UDP */
873 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
874 wire_len = wire_hdr_len + payload_len;
882 icmp_protocol = protocol;
883 switch (src->sa_family) {
885 protocol = 0x01; /* ICMPv4 */
886 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
890 protocol = 0x3A; /* ICMPv6 */
891 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
895 if (wire_len > 64 ) {
896 icmp_truncate_len = wire_len - 64;
898 wire_hdr_len += icmp_hdr_len;
899 wire_len += icmp_hdr_len;
902 packet_len = nonwire_len + wire_len;
903 alloc_len = packet_len;
904 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
905 alloc_len = SWRAP_PACKET_MIN_ALLOC;
908 base = (uint8_t *)malloc(alloc_len);
909 if (!base) return NULL;
913 frame = (struct swrap_packet_frame *)buf;
914 frame->seconds = tval->tv_sec;
915 frame->micro_seconds = tval->tv_usec;
916 frame->recorded_length = wire_len - icmp_truncate_len;
917 frame->full_length = wire_len - icmp_truncate_len;
918 buf += SWRAP_PACKET_FRAME_SIZE;
920 ip = (union swrap_packet_ip *)buf;
921 switch (src->sa_family) {
923 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
925 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
926 ip->v4.identification = htons(0xFFFF);
927 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
928 ip->v4.fragment = htons(0x0000);
930 ip->v4.protocol = protocol;
931 ip->v4.hdr_checksum = htons(0x0000);
932 ip->v4.src_addr = src_in->sin_addr.s_addr;
933 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
934 buf += SWRAP_PACKET_IP_V4_SIZE;
938 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
939 ip->v6.flow_label_high = 0x00;
940 ip->v6.flow_label_low = 0x0000;
941 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
942 ip->v6.next_header = protocol;
943 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
944 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
945 buf += SWRAP_PACKET_IP_V6_SIZE;
951 pay = (union swrap_packet_payload *)buf;
952 switch (src->sa_family) {
954 pay->icmp4.type = 0x03; /* destination unreachable */
955 pay->icmp4.code = 0x01; /* host unreachable */
956 pay->icmp4.checksum = htons(0x0000);
957 pay->icmp4.unused = htonl(0x00000000);
958 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
960 /* set the ip header in the ICMP payload */
961 ip = (union swrap_packet_ip *)buf;
962 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
964 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
965 ip->v4.identification = htons(0xFFFF);
966 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
967 ip->v4.fragment = htons(0x0000);
969 ip->v4.protocol = icmp_protocol;
970 ip->v4.hdr_checksum = htons(0x0000);
971 ip->v4.src_addr = dest_in->sin_addr.s_addr;
972 ip->v4.dest_addr = src_in->sin_addr.s_addr;
973 buf += SWRAP_PACKET_IP_V4_SIZE;
975 src_port = dest_in->sin_port;
976 dest_port = src_in->sin_port;
980 pay->icmp6.type = 0x01; /* destination unreachable */
981 pay->icmp6.code = 0x03; /* address unreachable */
982 pay->icmp6.checksum = htons(0x0000);
983 pay->icmp6.unused = htonl(0x00000000);
984 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
986 /* set the ip header in the ICMP payload */
987 ip = (union swrap_packet_ip *)buf;
988 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
989 ip->v6.flow_label_high = 0x00;
990 ip->v6.flow_label_low = 0x0000;
991 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
992 ip->v6.next_header = protocol;
993 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
994 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
995 buf += SWRAP_PACKET_IP_V6_SIZE;
997 src_port = dest_in6->sin6_port;
998 dest_port = src_in6->sin6_port;
1004 pay = (union swrap_packet_payload *)buf;
1006 switch (socket_type) {
1008 pay->tcp.source_port = src_port;
1009 pay->tcp.dest_port = dest_port;
1010 pay->tcp.seq_num = htonl(tcp_seqno);
1011 pay->tcp.ack_num = htonl(tcp_ack);
1012 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1013 pay->tcp.control = tcp_ctl;
1014 pay->tcp.window = htons(0x7FFF);
1015 pay->tcp.checksum = htons(0x0000);
1016 pay->tcp.urg = htons(0x0000);
1017 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1022 pay->udp.source_port = src_port;
1023 pay->udp.dest_port = dest_port;
1024 pay->udp.length = htons(8 + payload_len);
1025 pay->udp.checksum = htons(0x0000);
1026 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1031 if (payload && payload_len > 0) {
1032 memcpy(buf, payload, payload_len);
1035 *_packet_len = packet_len - icmp_truncate_len;
1039 static int swrap_get_pcap_fd(const char *fname)
1043 if (fd != -1) return fd;
1045 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1047 struct swrap_file_hdr file_hdr;
1048 file_hdr.magic = 0xA1B2C3D4;
1049 file_hdr.version_major = 0x0002;
1050 file_hdr.version_minor = 0x0004;
1051 file_hdr.timezone = 0x00000000;
1052 file_hdr.sigfigs = 0x00000000;
1053 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1054 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1056 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1063 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1068 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1069 const struct sockaddr *addr,
1070 enum swrap_packet_type type,
1071 const void *buf, size_t len,
1074 const struct sockaddr *src_addr;
1075 const struct sockaddr *dest_addr;
1076 unsigned long tcp_seqno = 0;
1077 unsigned long tcp_ack = 0;
1078 unsigned char tcp_ctl = 0;
1079 int unreachable = 0;
1083 switch (si->family) {
1093 case SWRAP_CONNECT_SEND:
1094 if (si->type != SOCK_STREAM) return NULL;
1096 src_addr = si->myname;
1099 tcp_seqno = si->io.pck_snd;
1100 tcp_ack = si->io.pck_rcv;
1101 tcp_ctl = 0x02; /* SYN */
1103 si->io.pck_snd += 1;
1107 case SWRAP_CONNECT_RECV:
1108 if (si->type != SOCK_STREAM) return NULL;
1110 dest_addr = si->myname;
1113 tcp_seqno = si->io.pck_rcv;
1114 tcp_ack = si->io.pck_snd;
1115 tcp_ctl = 0x12; /** SYN,ACK */
1117 si->io.pck_rcv += 1;
1121 case SWRAP_CONNECT_UNREACH:
1122 if (si->type != SOCK_STREAM) return NULL;
1124 dest_addr = si->myname;
1127 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1128 tcp_seqno = si->io.pck_snd - 1;
1129 tcp_ack = si->io.pck_rcv;
1130 tcp_ctl = 0x02; /* SYN */
1135 case SWRAP_CONNECT_ACK:
1136 if (si->type != SOCK_STREAM) return NULL;
1138 src_addr = si->myname;
1141 tcp_seqno = si->io.pck_snd;
1142 tcp_ack = si->io.pck_rcv;
1143 tcp_ctl = 0x10; /* ACK */
1147 case SWRAP_ACCEPT_SEND:
1148 if (si->type != SOCK_STREAM) return NULL;
1150 dest_addr = si->myname;
1153 tcp_seqno = si->io.pck_rcv;
1154 tcp_ack = si->io.pck_snd;
1155 tcp_ctl = 0x02; /* SYN */
1157 si->io.pck_rcv += 1;
1161 case SWRAP_ACCEPT_RECV:
1162 if (si->type != SOCK_STREAM) return NULL;
1164 src_addr = si->myname;
1167 tcp_seqno = si->io.pck_snd;
1168 tcp_ack = si->io.pck_rcv;
1169 tcp_ctl = 0x12; /* SYN,ACK */
1171 si->io.pck_snd += 1;
1175 case SWRAP_ACCEPT_ACK:
1176 if (si->type != SOCK_STREAM) return NULL;
1178 dest_addr = si->myname;
1181 tcp_seqno = si->io.pck_rcv;
1182 tcp_ack = si->io.pck_snd;
1183 tcp_ctl = 0x10; /* ACK */
1188 src_addr = si->myname;
1189 dest_addr = si->peername;
1191 tcp_seqno = si->io.pck_snd;
1192 tcp_ack = si->io.pck_rcv;
1193 tcp_ctl = 0x18; /* PSH,ACK */
1195 si->io.pck_snd += len;
1199 case SWRAP_SEND_RST:
1200 dest_addr = si->myname;
1201 src_addr = si->peername;
1203 if (si->type == SOCK_DGRAM) {
1204 return swrap_marshall_packet(si, si->peername,
1205 SWRAP_SENDTO_UNREACH,
1206 buf, len, packet_len);
1209 tcp_seqno = si->io.pck_rcv;
1210 tcp_ack = si->io.pck_snd;
1211 tcp_ctl = 0x14; /** RST,ACK */
1215 case SWRAP_PENDING_RST:
1216 dest_addr = si->myname;
1217 src_addr = si->peername;
1219 if (si->type == SOCK_DGRAM) {
1223 tcp_seqno = si->io.pck_rcv;
1224 tcp_ack = si->io.pck_snd;
1225 tcp_ctl = 0x14; /* RST,ACK */
1230 dest_addr = si->myname;
1231 src_addr = si->peername;
1233 tcp_seqno = si->io.pck_rcv;
1234 tcp_ack = si->io.pck_snd;
1235 tcp_ctl = 0x18; /* PSH,ACK */
1237 si->io.pck_rcv += len;
1241 case SWRAP_RECV_RST:
1242 dest_addr = si->myname;
1243 src_addr = si->peername;
1245 if (si->type == SOCK_DGRAM) {
1249 tcp_seqno = si->io.pck_rcv;
1250 tcp_ack = si->io.pck_snd;
1251 tcp_ctl = 0x14; /* RST,ACK */
1256 src_addr = si->myname;
1259 si->io.pck_snd += len;
1263 case SWRAP_SENDTO_UNREACH:
1264 dest_addr = si->myname;
1271 case SWRAP_RECVFROM:
1272 dest_addr = si->myname;
1275 si->io.pck_rcv += len;
1279 case SWRAP_CLOSE_SEND:
1280 if (si->type != SOCK_STREAM) return NULL;
1282 src_addr = si->myname;
1283 dest_addr = si->peername;
1285 tcp_seqno = si->io.pck_snd;
1286 tcp_ack = si->io.pck_rcv;
1287 tcp_ctl = 0x11; /* FIN, ACK */
1289 si->io.pck_snd += 1;
1293 case SWRAP_CLOSE_RECV:
1294 if (si->type != SOCK_STREAM) return NULL;
1296 dest_addr = si->myname;
1297 src_addr = si->peername;
1299 tcp_seqno = si->io.pck_rcv;
1300 tcp_ack = si->io.pck_snd;
1301 tcp_ctl = 0x11; /* FIN,ACK */
1303 si->io.pck_rcv += 1;
1307 case SWRAP_CLOSE_ACK:
1308 if (si->type != SOCK_STREAM) return NULL;
1310 src_addr = si->myname;
1311 dest_addr = si->peername;
1313 tcp_seqno = si->io.pck_snd;
1314 tcp_ack = si->io.pck_rcv;
1315 tcp_ctl = 0x10; /* ACK */
1322 swrapGetTimeOfDay(&tv);
1324 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1325 (const uint8_t *)buf, len,
1326 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1330 static void swrap_dump_packet(struct socket_info *si,
1331 const struct sockaddr *addr,
1332 enum swrap_packet_type type,
1333 const void *buf, size_t len)
1335 const char *file_name;
1337 size_t packet_len = 0;
1340 file_name = socket_wrapper_pcap_file();
1345 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1350 fd = swrap_get_pcap_fd(file_name);
1352 if (write(fd, packet, packet_len) != packet_len) {
1361 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1363 struct socket_info *si;
1366 if (!socket_wrapper_dir()) {
1367 return real_socket(family, type, protocol);
1377 return real_socket(family, type, protocol);
1379 errno = EAFNOSUPPORT;
1389 errno = EPROTONOSUPPORT;
1397 if (type == SOCK_STREAM) {
1402 if (type == SOCK_DGRAM) {
1407 errno = EPROTONOSUPPORT;
1411 fd = real_socket(AF_UNIX, type, 0);
1413 if (fd == -1) return -1;
1415 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1417 si->family = family;
1419 si->protocol = protocol;
1422 SWRAP_DLIST_ADD(sockets, si);
1427 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1429 struct socket_info *parent_si, *child_si;
1431 struct sockaddr_un un_addr;
1432 socklen_t un_addrlen = sizeof(un_addr);
1433 struct sockaddr_un un_my_addr;
1434 socklen_t un_my_addrlen = sizeof(un_my_addr);
1435 struct sockaddr *my_addr;
1436 socklen_t my_addrlen, len;
1439 parent_si = find_socket_info(s);
1441 return real_accept(s, addr, addrlen);
1445 * assume out sockaddr have the same size as the in parent
1448 my_addrlen = socket_length(parent_si->family);
1449 if (my_addrlen <= 0) {
1454 my_addr = (struct sockaddr *)malloc(my_addrlen);
1455 if (my_addr == NULL) {
1459 memset(&un_addr, 0, sizeof(un_addr));
1460 memset(&un_my_addr, 0, sizeof(un_my_addr));
1462 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1471 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1472 parent_si->family, my_addr, &len);
1479 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1480 memset(child_si, 0, sizeof(*child_si));
1483 child_si->family = parent_si->family;
1484 child_si->type = parent_si->type;
1485 child_si->protocol = parent_si->protocol;
1486 child_si->bound = 1;
1487 child_si->is_server = 1;
1489 child_si->peername_len = len;
1490 child_si->peername = sockaddr_dup(my_addr, len);
1492 if (addr != NULL && addrlen != NULL) {
1494 if (*addrlen >= len)
1495 memcpy(addr, my_addr, len);
1499 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1507 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1508 child_si->family, my_addr, &len);
1516 child_si->myname_len = len;
1517 child_si->myname = sockaddr_dup(my_addr, len);
1520 SWRAP_DLIST_ADD(sockets, child_si);
1522 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1523 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1524 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1529 static int autobind_start_init;
1530 static int autobind_start;
1532 /* using sendto() or connect() on an unbound socket would give the
1533 recipient no way to reply, as unlike UDP and TCP, a unix domain
1534 socket can't auto-assign emphemeral port numbers, so we need to
1536 static int swrap_auto_bind(struct socket_info *si)
1538 struct sockaddr_un un_addr;
1545 if (autobind_start_init != 1) {
1546 autobind_start_init = 1;
1547 autobind_start = getpid();
1548 autobind_start %= 50000;
1549 autobind_start += 10000;
1552 un_addr.sun_family = AF_UNIX;
1554 switch (si->family) {
1556 struct sockaddr_in in;
1560 type = SOCKET_TYPE_CHAR_TCP;
1563 type = SOCKET_TYPE_CHAR_UDP;
1566 errno = ESOCKTNOSUPPORT;
1570 memset(&in, 0, sizeof(in));
1571 in.sin_family = AF_INET;
1572 in.sin_addr.s_addr = htonl(127<<24 |
1573 socket_wrapper_default_iface());
1575 si->myname_len = sizeof(in);
1576 si->myname = sockaddr_dup(&in, si->myname_len);
1581 struct sockaddr_in6 in6;
1585 type = SOCKET_TYPE_CHAR_TCP_V6;
1588 type = SOCKET_TYPE_CHAR_UDP_V6;
1591 errno = ESOCKTNOSUPPORT;
1595 memset(&in6, 0, sizeof(in6));
1596 in6.sin6_family = AF_INET6;
1597 in6.sin6_addr = swrap_ipv6;
1598 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1599 si->myname_len = sizeof(in6);
1600 si->myname = sockaddr_dup(&in6, si->myname_len);
1605 errno = ESOCKTNOSUPPORT;
1609 if (autobind_start > 60000) {
1610 autobind_start = 10000;
1613 for (i=0;i<1000;i++) {
1614 port = autobind_start + i;
1615 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1616 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1617 type, socket_wrapper_default_iface(), port);
1618 if (stat(un_addr.sun_path, &st) == 0) continue;
1620 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1621 if (ret == -1) return ret;
1623 si->tmp_path = strdup(un_addr.sun_path);
1625 autobind_start = port + 1;
1633 set_port(si->family, port, si->myname);
1639 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1642 struct sockaddr_un un_addr;
1643 struct socket_info *si = find_socket_info(s);
1646 return real_connect(s, serv_addr, addrlen);
1649 if (si->bound == 0) {
1650 ret = swrap_auto_bind(si);
1651 if (ret == -1) return -1;
1654 if (si->family != serv_addr->sa_family) {
1659 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1660 if (ret == -1) return -1;
1662 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1664 ret = real_connect(s, (struct sockaddr *)&un_addr,
1665 sizeof(struct sockaddr_un));
1667 /* to give better errors */
1668 if (ret == -1 && errno == ENOENT) {
1669 errno = EHOSTUNREACH;
1673 si->peername_len = addrlen;
1674 si->peername = sockaddr_dup(serv_addr, addrlen);
1676 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1677 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1679 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1685 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1688 struct sockaddr_un un_addr;
1689 struct socket_info *si = find_socket_info(s);
1692 return real_bind(s, myaddr, addrlen);
1695 si->myname_len = addrlen;
1696 si->myname = sockaddr_dup(myaddr, addrlen);
1698 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1699 if (ret == -1) return -1;
1701 unlink(un_addr.sun_path);
1703 ret = real_bind(s, (struct sockaddr *)&un_addr,
1704 sizeof(struct sockaddr_un));
1713 _PUBLIC_ int swrap_listen(int s, int backlog)
1716 struct socket_info *si = find_socket_info(s);
1719 return real_listen(s, backlog);
1722 ret = real_listen(s, backlog);
1727 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1729 struct socket_info *si = find_socket_info(s);
1732 return real_getpeername(s, name, addrlen);
1741 memcpy(name, si->peername, si->peername_len);
1742 *addrlen = si->peername_len;
1747 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1749 struct socket_info *si = find_socket_info(s);
1752 return real_getsockname(s, name, addrlen);
1755 memcpy(name, si->myname, si->myname_len);
1756 *addrlen = si->myname_len;
1761 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1763 struct socket_info *si = find_socket_info(s);
1766 return real_getsockopt(s, level, optname, optval, optlen);
1769 if (level == SOL_SOCKET) {
1770 return real_getsockopt(s, level, optname, optval, optlen);
1773 errno = ENOPROTOOPT;
1777 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1779 struct socket_info *si = find_socket_info(s);
1782 return real_setsockopt(s, level, optname, optval, optlen);
1785 if (level == SOL_SOCKET) {
1786 return real_setsockopt(s, level, optname, optval, optlen);
1789 switch (si->family) {
1793 errno = ENOPROTOOPT;
1798 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1800 struct sockaddr_un un_addr;
1801 socklen_t un_addrlen = sizeof(un_addr);
1803 struct socket_info *si = find_socket_info(s);
1806 return real_recvfrom(s, buf, len, flags, from, fromlen);
1809 len = MIN(len, 1500);
1811 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1812 memset(&un_addr, 0, sizeof(un_addr));
1813 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1817 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1818 si->family, from, fromlen) == -1) {
1822 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1828 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1830 struct sockaddr_un un_addr;
1832 struct socket_info *si = find_socket_info(s);
1836 return real_sendto(s, buf, len, flags, to, tolen);
1839 len = MIN(len, 1500);
1843 ret = real_send(s, buf, len, flags);
1846 if (si->bound == 0) {
1847 ret = swrap_auto_bind(si);
1848 if (ret == -1) return -1;
1851 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1852 if (ret == -1) return -1;
1857 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1860 type = SOCKET_TYPE_CHAR_UDP;
1862 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1863 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1864 socket_wrapper_dir(), type, iface, prt);
1865 if (stat(un_addr.sun_path, &st) != 0) continue;
1867 /* ignore the any errors in broadcast sends */
1868 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1871 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1876 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1880 errno = EHOSTUNREACH;
1884 /* to give better errors */
1885 if (ret == -1 && errno == ENOENT) {
1886 errno = EHOSTUNREACH;
1890 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1891 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1893 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1899 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1902 struct socket_info *si = find_socket_info(s);
1906 return real_ioctl(s, r, p);
1909 ret = real_ioctl(s, r, p);
1913 value = *((int *)p);
1914 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1915 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1916 } else if (value == 0) { /* END OF FILE */
1917 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1925 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1928 struct socket_info *si = find_socket_info(s);
1931 return real_recv(s, buf, len, flags);
1934 len = MIN(len, 1500);
1936 ret = real_recv(s, buf, len, flags);
1937 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1938 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1939 } else if (ret == 0) { /* END OF FILE */
1940 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1941 } else if (ret > 0) {
1942 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1949 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1952 struct socket_info *si = find_socket_info(s);
1955 return real_send(s, buf, len, flags);
1958 len = MIN(len, 1500);
1960 ret = real_send(s, buf, len, flags);
1963 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1964 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1966 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1972 _PUBLIC_ int swrap_close(int fd)
1974 struct socket_info *si = find_socket_info(fd);
1978 return real_close(fd);
1981 SWRAP_DLIST_REMOVE(sockets, si);
1983 if (si->myname && si->peername) {
1984 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1987 ret = real_close(fd);
1989 if (si->myname && si->peername) {
1990 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1991 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1994 if (si->path) free(si->path);
1995 if (si->myname) free(si->myname);
1996 if (si->peername) free(si->peername);
1998 unlink(si->tmp_path);