2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <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_sendmsg sendmsg
122 #define real_ioctl ioctl
123 #define real_recv recv
124 #define real_read read
125 #define real_send send
126 #define real_readv readv
127 #define real_writev writev
128 #define real_socket socket
129 #define real_close close
132 #ifdef HAVE_GETTIMEOFDAY_TZ
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 /* we need to use a very terse format here as IRIX 6.4 silently
139 truncates names to 16 chars, so if we use a longer name then we
140 can't tell which port a packet came from with recvfrom()
142 with this format we have 8 chars left for the directory name
144 #define SOCKET_FORMAT "%c%02X%04X"
145 #define SOCKET_TYPE_CHAR_TCP 'T'
146 #define SOCKET_TYPE_CHAR_UDP 'U'
147 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
148 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
150 #define MAX_WRAPPED_INTERFACES 16
156 static const struct in6_addr *swrap_ipv6(void)
158 static struct in6_addr v;
159 static int initialized;
167 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
176 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
178 struct sockaddr *ret = (struct sockaddr *)malloc(len);
179 memcpy(ret, data, len);
183 static void set_port(int family, int prt, struct sockaddr *addr)
187 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
191 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
197 static size_t socket_length(int family)
201 return sizeof(struct sockaddr_in);
204 return sizeof(struct sockaddr_in6);
228 struct sockaddr *myname;
229 socklen_t myname_len;
231 struct sockaddr *peername;
232 socklen_t peername_len;
235 unsigned long pck_snd;
236 unsigned long pck_rcv;
239 struct socket_info *prev, *next;
242 static struct socket_info *sockets;
244 const char *socket_wrapper_dir(void)
246 const char *s = getenv("SOCKET_WRAPPER_DIR");
250 if (strncmp(s, "./", 2) == 0) {
256 unsigned int socket_wrapper_default_iface(void)
258 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
261 if (sscanf(s, "%u", &iface) == 1) {
262 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
268 return 1;/* 127.0.0.1 */
271 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
278 p = strrchr(un->sun_path, '/');
279 if (p) p++; else p = un->sun_path;
281 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
286 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
297 case SOCKET_TYPE_CHAR_TCP:
298 case SOCKET_TYPE_CHAR_UDP: {
299 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
301 if ((*len) < sizeof(*in2)) {
306 memset(in2, 0, sizeof(*in2));
307 in2->sin_family = AF_INET;
308 in2->sin_addr.s_addr = htonl((127<<24) | iface);
309 in2->sin_port = htons(prt);
315 case SOCKET_TYPE_CHAR_TCP_V6:
316 case SOCKET_TYPE_CHAR_UDP_V6: {
317 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
319 if ((*len) < sizeof(*in2)) {
324 memset(in2, 0, sizeof(*in2));
325 in2->sin6_family = AF_INET6;
326 in2->sin6_addr = *swrap_ipv6();
327 in2->sin6_addr.s6_addr[15] = iface;
328 in2->sin6_port = htons(prt);
342 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
350 if (bcast) *bcast = 0;
352 switch (inaddr->sa_family) {
354 const struct sockaddr_in *in =
355 (const struct sockaddr_in *)(const void *)inaddr;
356 unsigned int addr = ntohl(in->sin_addr.s_addr);
363 u_type = SOCKET_TYPE_CHAR_TCP;
366 u_type = SOCKET_TYPE_CHAR_UDP;
367 a_type = SOCKET_TYPE_CHAR_UDP;
368 b_type = SOCKET_TYPE_CHAR_UDP;
372 prt = ntohs(in->sin_port);
373 if (a_type && addr == 0xFFFFFFFF) {
374 /* 255.255.255.255 only udp */
377 iface = socket_wrapper_default_iface();
378 } else if (b_type && addr == 0x7FFFFFFF) {
379 /* 127.255.255.255 only udp */
382 iface = socket_wrapper_default_iface();
383 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
387 iface = (addr & 0x000000FF);
392 if (bcast) *bcast = is_bcast;
397 const struct sockaddr_in6 *in =
398 (const struct sockaddr_in6 *)(const void *)inaddr;
399 struct in6_addr cmp1, cmp2;
403 type = SOCKET_TYPE_CHAR_TCP_V6;
406 type = SOCKET_TYPE_CHAR_UDP_V6;
410 /* XXX no multicast/broadcast */
412 prt = ntohs(in->sin6_port);
414 cmp1 = *swrap_ipv6();
415 cmp2 = in->sin6_addr;
416 cmp2.s6_addr[15] = 0;
417 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
418 iface = in->sin6_addr.s6_addr[15];
438 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
439 socket_wrapper_dir());
440 /* the caller need to do more processing */
444 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
445 socket_wrapper_dir(), type, iface, prt);
450 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
459 if (bcast) *bcast = 0;
461 switch (si->family) {
463 const struct sockaddr_in *in =
464 (const struct sockaddr_in *)(const void *)inaddr;
465 unsigned int addr = ntohl(in->sin_addr.s_addr);
471 prt = ntohs(in->sin_port);
475 u_type = SOCKET_TYPE_CHAR_TCP;
476 d_type = SOCKET_TYPE_CHAR_TCP;
479 u_type = SOCKET_TYPE_CHAR_UDP;
480 d_type = SOCKET_TYPE_CHAR_UDP;
481 a_type = SOCKET_TYPE_CHAR_UDP;
482 b_type = SOCKET_TYPE_CHAR_UDP;
490 iface = socket_wrapper_default_iface();
491 } else if (a_type && addr == 0xFFFFFFFF) {
492 /* 255.255.255.255 only udp */
495 iface = socket_wrapper_default_iface();
496 } else if (b_type && addr == 0x7FFFFFFF) {
497 /* 127.255.255.255 only udp */
500 iface = socket_wrapper_default_iface();
501 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
505 iface = (addr & 0x000000FF);
507 errno = EADDRNOTAVAIL;
514 const struct sockaddr_in6 *in =
515 (const struct sockaddr_in6 *)(const void *)inaddr;
516 struct in6_addr cmp1, cmp2;
520 type = SOCKET_TYPE_CHAR_TCP_V6;
523 type = SOCKET_TYPE_CHAR_UDP_V6;
527 /* XXX no multicast/broadcast */
529 prt = ntohs(in->sin6_port);
531 cmp1 = *swrap_ipv6();
532 cmp2 = in->sin6_addr;
533 cmp2.s6_addr[15] = 0;
534 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
535 iface = socket_wrapper_default_iface();
536 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
537 iface = in->sin6_addr.s6_addr[15];
539 errno = EADDRNOTAVAIL;
547 errno = EADDRNOTAVAIL;
552 if (bcast) *bcast = is_bcast;
555 /* handle auto-allocation of ephemeral ports */
556 for (prt = 5001; prt < 10000; prt++) {
557 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
558 socket_wrapper_dir(), type, iface, prt);
559 if (stat(un->sun_path, &st) == 0) continue;
561 set_port(si->family, prt, si->myname);
570 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
571 socket_wrapper_dir(), type, iface, prt);
575 static struct socket_info *find_socket_info(int fd)
577 struct socket_info *i;
578 for (i = sockets; i; i = i->next) {
586 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
587 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
589 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
593 out->sa_family = AF_UNIX;
594 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
595 out->sa_len = sizeof(*out_addr);
598 switch (in_addr->sa_family) {
608 errno = ESOCKTNOSUPPORT;
612 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
614 return convert_in_un_remote(si, in_addr, out_addr, bcast);
620 errno = EAFNOSUPPORT;
624 static int sockaddr_convert_from_un(const struct socket_info *si,
625 const struct sockaddr_un *in_addr,
626 socklen_t un_addrlen,
628 struct sockaddr *out_addr,
629 socklen_t *out_addrlen)
633 if (out_addr == NULL || out_addrlen == NULL)
636 if (un_addrlen == 0) {
651 errno = ESOCKTNOSUPPORT;
654 ret = convert_un_in(in_addr, out_addr, out_addrlen);
655 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
656 out_addr->sa_len = *out_addrlen;
663 errno = EAFNOSUPPORT;
667 enum swrap_packet_type {
669 SWRAP_CONNECT_UNREACH,
677 SWRAP_SENDTO_UNREACH,
688 struct swrap_file_hdr {
690 uint16_t version_major;
691 uint16_t version_minor;
694 uint32_t frame_max_len;
695 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
698 #define SWRAP_FILE_HDR_SIZE 24
700 struct swrap_packet_frame {
702 uint32_t micro_seconds;
703 uint32_t recorded_length;
704 uint32_t full_length;
706 #define SWRAP_PACKET_FRAME_SIZE 16
708 union swrap_packet_ip {
712 uint16_t packet_length;
713 uint16_t identification;
718 uint16_t hdr_checksum;
722 #define SWRAP_PACKET_IP_V4_SIZE 20
725 uint8_t flow_label_high;
726 uint16_t flow_label_low;
727 uint16_t payload_length;
730 uint8_t src_addr[16];
731 uint8_t dest_addr[16];
733 #define SWRAP_PACKET_IP_V6_SIZE 40
735 #define SWRAP_PACKET_IP_SIZE 40
737 union swrap_packet_payload {
739 uint16_t source_port;
749 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
751 uint16_t source_port;
756 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
763 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
770 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
772 #define SWRAP_PACKET_PAYLOAD_SIZE 20
774 #define SWRAP_PACKET_MIN_ALLOC \
775 (SWRAP_PACKET_FRAME_SIZE + \
776 SWRAP_PACKET_IP_SIZE + \
777 SWRAP_PACKET_PAYLOAD_SIZE)
779 static const char *socket_wrapper_pcap_file(void)
781 static int initialized = 0;
782 static const char *s = NULL;
783 static const struct swrap_file_hdr h;
784 static const struct swrap_packet_frame f;
785 static const union swrap_packet_ip i;
786 static const union swrap_packet_payload p;
788 if (initialized == 1) {
794 * TODO: don't use the structs use plain buffer offsets
795 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
797 * for now make sure we disable PCAP support
798 * if the struct has alignment!
800 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
803 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
806 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
809 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
812 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
815 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
818 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
821 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
824 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
827 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
831 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
835 if (strncmp(s, "./", 2) == 0) {
841 static uint8_t *swrap_packet_init(struct timeval *tval,
842 const struct sockaddr *src,
843 const struct sockaddr *dest,
845 const uint8_t *payload,
847 unsigned long tcp_seqno,
848 unsigned long tcp_ack,
849 unsigned char tcp_ctl,
855 struct swrap_packet_frame *frame;
856 union swrap_packet_ip *ip;
857 union swrap_packet_payload *pay;
860 size_t nonwire_len = sizeof(*frame);
861 size_t wire_hdr_len = 0;
863 size_t ip_hdr_len = 0;
864 size_t icmp_hdr_len = 0;
865 size_t icmp_truncate_len = 0;
866 uint8_t protocol = 0, icmp_protocol = 0;
867 const struct sockaddr_in *src_in = NULL;
868 const struct sockaddr_in *dest_in = NULL;
870 const struct sockaddr_in6 *src_in6 = NULL;
871 const struct sockaddr_in6 *dest_in6 = NULL;
876 switch (src->sa_family) {
878 src_in = (const struct sockaddr_in *)src;
879 dest_in = (const struct sockaddr_in *)dest;
880 src_port = src_in->sin_port;
881 dest_port = dest_in->sin_port;
882 ip_hdr_len = sizeof(ip->v4);
886 src_in6 = (const struct sockaddr_in6 *)src;
887 dest_in6 = (const struct sockaddr_in6 *)dest;
888 src_port = src_in6->sin6_port;
889 dest_port = dest_in6->sin6_port;
890 ip_hdr_len = sizeof(ip->v6);
897 switch (socket_type) {
899 protocol = 0x06; /* TCP */
900 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
901 wire_len = wire_hdr_len + payload_len;
905 protocol = 0x11; /* UDP */
906 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
907 wire_len = wire_hdr_len + payload_len;
915 icmp_protocol = protocol;
916 switch (src->sa_family) {
918 protocol = 0x01; /* ICMPv4 */
919 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
923 protocol = 0x3A; /* ICMPv6 */
924 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
928 if (wire_len > 64 ) {
929 icmp_truncate_len = wire_len - 64;
931 wire_hdr_len += icmp_hdr_len;
932 wire_len += icmp_hdr_len;
935 packet_len = nonwire_len + wire_len;
936 alloc_len = packet_len;
937 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
938 alloc_len = SWRAP_PACKET_MIN_ALLOC;
941 base = (uint8_t *)malloc(alloc_len);
942 if (!base) return NULL;
946 frame = (struct swrap_packet_frame *)buf;
947 frame->seconds = tval->tv_sec;
948 frame->micro_seconds = tval->tv_usec;
949 frame->recorded_length = wire_len - icmp_truncate_len;
950 frame->full_length = wire_len - icmp_truncate_len;
951 buf += SWRAP_PACKET_FRAME_SIZE;
953 ip = (union swrap_packet_ip *)buf;
954 switch (src->sa_family) {
956 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
958 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
959 ip->v4.identification = htons(0xFFFF);
960 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
961 ip->v4.fragment = htons(0x0000);
963 ip->v4.protocol = protocol;
964 ip->v4.hdr_checksum = htons(0x0000);
965 ip->v4.src_addr = src_in->sin_addr.s_addr;
966 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
967 buf += SWRAP_PACKET_IP_V4_SIZE;
971 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
972 ip->v6.flow_label_high = 0x00;
973 ip->v6.flow_label_low = 0x0000;
974 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
975 ip->v6.next_header = protocol;
976 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
977 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
978 buf += SWRAP_PACKET_IP_V6_SIZE;
984 pay = (union swrap_packet_payload *)buf;
985 switch (src->sa_family) {
987 pay->icmp4.type = 0x03; /* destination unreachable */
988 pay->icmp4.code = 0x01; /* host unreachable */
989 pay->icmp4.checksum = htons(0x0000);
990 pay->icmp4.unused = htonl(0x00000000);
991 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
993 /* set the ip header in the ICMP payload */
994 ip = (union swrap_packet_ip *)buf;
995 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
997 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
998 ip->v4.identification = htons(0xFFFF);
999 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1000 ip->v4.fragment = htons(0x0000);
1002 ip->v4.protocol = icmp_protocol;
1003 ip->v4.hdr_checksum = htons(0x0000);
1004 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1005 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1006 buf += SWRAP_PACKET_IP_V4_SIZE;
1008 src_port = dest_in->sin_port;
1009 dest_port = src_in->sin_port;
1013 pay->icmp6.type = 0x01; /* destination unreachable */
1014 pay->icmp6.code = 0x03; /* address unreachable */
1015 pay->icmp6.checksum = htons(0x0000);
1016 pay->icmp6.unused = htonl(0x00000000);
1017 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1019 /* set the ip header in the ICMP payload */
1020 ip = (union swrap_packet_ip *)buf;
1021 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1022 ip->v6.flow_label_high = 0x00;
1023 ip->v6.flow_label_low = 0x0000;
1024 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1025 ip->v6.next_header = protocol;
1026 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1027 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1028 buf += SWRAP_PACKET_IP_V6_SIZE;
1030 src_port = dest_in6->sin6_port;
1031 dest_port = src_in6->sin6_port;
1037 pay = (union swrap_packet_payload *)buf;
1039 switch (socket_type) {
1041 pay->tcp.source_port = src_port;
1042 pay->tcp.dest_port = dest_port;
1043 pay->tcp.seq_num = htonl(tcp_seqno);
1044 pay->tcp.ack_num = htonl(tcp_ack);
1045 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1046 pay->tcp.control = tcp_ctl;
1047 pay->tcp.window = htons(0x7FFF);
1048 pay->tcp.checksum = htons(0x0000);
1049 pay->tcp.urg = htons(0x0000);
1050 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1055 pay->udp.source_port = src_port;
1056 pay->udp.dest_port = dest_port;
1057 pay->udp.length = htons(8 + payload_len);
1058 pay->udp.checksum = htons(0x0000);
1059 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1064 if (payload && payload_len > 0) {
1065 memcpy(buf, payload, payload_len);
1068 *_packet_len = packet_len - icmp_truncate_len;
1072 static int swrap_get_pcap_fd(const char *fname)
1076 if (fd != -1) return fd;
1078 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1080 struct swrap_file_hdr file_hdr;
1081 file_hdr.magic = 0xA1B2C3D4;
1082 file_hdr.version_major = 0x0002;
1083 file_hdr.version_minor = 0x0004;
1084 file_hdr.timezone = 0x00000000;
1085 file_hdr.sigfigs = 0x00000000;
1086 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1087 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1089 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1096 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1101 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1102 const struct sockaddr *addr,
1103 enum swrap_packet_type type,
1104 const void *buf, size_t len,
1107 const struct sockaddr *src_addr;
1108 const struct sockaddr *dest_addr;
1109 unsigned long tcp_seqno = 0;
1110 unsigned long tcp_ack = 0;
1111 unsigned char tcp_ctl = 0;
1112 int unreachable = 0;
1116 switch (si->family) {
1128 case SWRAP_CONNECT_SEND:
1129 if (si->type != SOCK_STREAM) return NULL;
1131 src_addr = si->myname;
1134 tcp_seqno = si->io.pck_snd;
1135 tcp_ack = si->io.pck_rcv;
1136 tcp_ctl = 0x02; /* SYN */
1138 si->io.pck_snd += 1;
1142 case SWRAP_CONNECT_RECV:
1143 if (si->type != SOCK_STREAM) return NULL;
1145 dest_addr = si->myname;
1148 tcp_seqno = si->io.pck_rcv;
1149 tcp_ack = si->io.pck_snd;
1150 tcp_ctl = 0x12; /** SYN,ACK */
1152 si->io.pck_rcv += 1;
1156 case SWRAP_CONNECT_UNREACH:
1157 if (si->type != SOCK_STREAM) return NULL;
1159 dest_addr = si->myname;
1162 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1163 tcp_seqno = si->io.pck_snd - 1;
1164 tcp_ack = si->io.pck_rcv;
1165 tcp_ctl = 0x02; /* SYN */
1170 case SWRAP_CONNECT_ACK:
1171 if (si->type != SOCK_STREAM) return NULL;
1173 src_addr = si->myname;
1176 tcp_seqno = si->io.pck_snd;
1177 tcp_ack = si->io.pck_rcv;
1178 tcp_ctl = 0x10; /* ACK */
1182 case SWRAP_ACCEPT_SEND:
1183 if (si->type != SOCK_STREAM) return NULL;
1185 dest_addr = si->myname;
1188 tcp_seqno = si->io.pck_rcv;
1189 tcp_ack = si->io.pck_snd;
1190 tcp_ctl = 0x02; /* SYN */
1192 si->io.pck_rcv += 1;
1196 case SWRAP_ACCEPT_RECV:
1197 if (si->type != SOCK_STREAM) return NULL;
1199 src_addr = si->myname;
1202 tcp_seqno = si->io.pck_snd;
1203 tcp_ack = si->io.pck_rcv;
1204 tcp_ctl = 0x12; /* SYN,ACK */
1206 si->io.pck_snd += 1;
1210 case SWRAP_ACCEPT_ACK:
1211 if (si->type != SOCK_STREAM) return NULL;
1213 dest_addr = si->myname;
1216 tcp_seqno = si->io.pck_rcv;
1217 tcp_ack = si->io.pck_snd;
1218 tcp_ctl = 0x10; /* ACK */
1223 src_addr = si->myname;
1224 dest_addr = si->peername;
1226 tcp_seqno = si->io.pck_snd;
1227 tcp_ack = si->io.pck_rcv;
1228 tcp_ctl = 0x18; /* PSH,ACK */
1230 si->io.pck_snd += len;
1234 case SWRAP_SEND_RST:
1235 dest_addr = si->myname;
1236 src_addr = si->peername;
1238 if (si->type == SOCK_DGRAM) {
1239 return swrap_marshall_packet(si, si->peername,
1240 SWRAP_SENDTO_UNREACH,
1241 buf, len, packet_len);
1244 tcp_seqno = si->io.pck_rcv;
1245 tcp_ack = si->io.pck_snd;
1246 tcp_ctl = 0x14; /** RST,ACK */
1250 case SWRAP_PENDING_RST:
1251 dest_addr = si->myname;
1252 src_addr = si->peername;
1254 if (si->type == SOCK_DGRAM) {
1258 tcp_seqno = si->io.pck_rcv;
1259 tcp_ack = si->io.pck_snd;
1260 tcp_ctl = 0x14; /* RST,ACK */
1265 dest_addr = si->myname;
1266 src_addr = si->peername;
1268 tcp_seqno = si->io.pck_rcv;
1269 tcp_ack = si->io.pck_snd;
1270 tcp_ctl = 0x18; /* PSH,ACK */
1272 si->io.pck_rcv += len;
1276 case SWRAP_RECV_RST:
1277 dest_addr = si->myname;
1278 src_addr = si->peername;
1280 if (si->type == SOCK_DGRAM) {
1284 tcp_seqno = si->io.pck_rcv;
1285 tcp_ack = si->io.pck_snd;
1286 tcp_ctl = 0x14; /* RST,ACK */
1291 src_addr = si->myname;
1294 si->io.pck_snd += len;
1298 case SWRAP_SENDTO_UNREACH:
1299 dest_addr = si->myname;
1306 case SWRAP_RECVFROM:
1307 dest_addr = si->myname;
1310 si->io.pck_rcv += len;
1314 case SWRAP_CLOSE_SEND:
1315 if (si->type != SOCK_STREAM) return NULL;
1317 src_addr = si->myname;
1318 dest_addr = si->peername;
1320 tcp_seqno = si->io.pck_snd;
1321 tcp_ack = si->io.pck_rcv;
1322 tcp_ctl = 0x11; /* FIN, ACK */
1324 si->io.pck_snd += 1;
1328 case SWRAP_CLOSE_RECV:
1329 if (si->type != SOCK_STREAM) return NULL;
1331 dest_addr = si->myname;
1332 src_addr = si->peername;
1334 tcp_seqno = si->io.pck_rcv;
1335 tcp_ack = si->io.pck_snd;
1336 tcp_ctl = 0x11; /* FIN,ACK */
1338 si->io.pck_rcv += 1;
1342 case SWRAP_CLOSE_ACK:
1343 if (si->type != SOCK_STREAM) return NULL;
1345 src_addr = si->myname;
1346 dest_addr = si->peername;
1348 tcp_seqno = si->io.pck_snd;
1349 tcp_ack = si->io.pck_rcv;
1350 tcp_ctl = 0x10; /* ACK */
1357 swrapGetTimeOfDay(&tv);
1359 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1360 (const uint8_t *)buf, len,
1361 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1365 static void swrap_dump_packet(struct socket_info *si,
1366 const struct sockaddr *addr,
1367 enum swrap_packet_type type,
1368 const void *buf, size_t len)
1370 const char *file_name;
1372 size_t packet_len = 0;
1375 file_name = socket_wrapper_pcap_file();
1380 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1385 fd = swrap_get_pcap_fd(file_name);
1387 if (write(fd, packet, packet_len) != packet_len) {
1396 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1398 struct socket_info *si;
1400 int real_type = type;
1402 real_type &= ~SOCK_CLOEXEC;
1404 #ifdef SOCK_NONBLOCK
1405 real_type &= ~SOCK_NONBLOCK;
1408 if (!socket_wrapper_dir()) {
1409 return real_socket(family, type, protocol);
1419 return real_socket(family, type, protocol);
1421 errno = EAFNOSUPPORT;
1425 switch (real_type) {
1431 errno = EPROTONOSUPPORT;
1439 if (real_type == SOCK_STREAM) {
1444 if (real_type == SOCK_DGRAM) {
1449 errno = EPROTONOSUPPORT;
1453 /* We must call real_socket with type, from the caller, not the version we removed
1454 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1455 fd = real_socket(AF_UNIX, type, 0);
1457 if (fd == -1) return -1;
1459 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1461 si->family = family;
1463 /* however, the rest of the socket_wrapper code expects just
1464 * the type, not the flags */
1465 si->type = real_type;
1466 si->protocol = protocol;
1469 SWRAP_DLIST_ADD(sockets, si);
1474 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1476 struct socket_info *parent_si, *child_si;
1478 struct sockaddr_un un_addr;
1479 socklen_t un_addrlen = sizeof(un_addr);
1480 struct sockaddr_un un_my_addr;
1481 socklen_t un_my_addrlen = sizeof(un_my_addr);
1482 struct sockaddr *my_addr;
1483 socklen_t my_addrlen, len;
1486 parent_si = find_socket_info(s);
1488 return real_accept(s, addr, addrlen);
1492 * assume out sockaddr have the same size as the in parent
1495 my_addrlen = socket_length(parent_si->family);
1496 if (my_addrlen <= 0) {
1501 my_addr = (struct sockaddr *)malloc(my_addrlen);
1502 if (my_addr == NULL) {
1506 memset(&un_addr, 0, sizeof(un_addr));
1507 memset(&un_my_addr, 0, sizeof(un_my_addr));
1509 ret = real_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
1518 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1519 parent_si->family, my_addr, &len);
1526 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1527 memset(child_si, 0, sizeof(*child_si));
1530 child_si->family = parent_si->family;
1531 child_si->type = parent_si->type;
1532 child_si->protocol = parent_si->protocol;
1533 child_si->bound = 1;
1534 child_si->is_server = 1;
1535 child_si->connected = 1;
1537 child_si->peername_len = len;
1538 child_si->peername = sockaddr_dup(my_addr, len);
1540 if (addr != NULL && addrlen != NULL) {
1542 if (*addrlen >= len)
1543 memcpy(addr, my_addr, len);
1547 ret = real_getsockname(fd, (struct sockaddr *)(void *)&un_my_addr,
1556 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1557 child_si->family, my_addr, &len);
1565 child_si->myname_len = len;
1566 child_si->myname = sockaddr_dup(my_addr, len);
1569 SWRAP_DLIST_ADD(sockets, child_si);
1571 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1572 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1573 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1578 static int autobind_start_init;
1579 static int autobind_start;
1581 /* using sendto() or connect() on an unbound socket would give the
1582 recipient no way to reply, as unlike UDP and TCP, a unix domain
1583 socket can't auto-assign emphemeral port numbers, so we need to
1585 Note: this might change the family from ipv6 to ipv4
1587 static int swrap_auto_bind(struct socket_info *si, int family)
1589 struct sockaddr_un un_addr;
1596 if (autobind_start_init != 1) {
1597 autobind_start_init = 1;
1598 autobind_start = getpid();
1599 autobind_start %= 50000;
1600 autobind_start += 10000;
1603 un_addr.sun_family = AF_UNIX;
1607 struct sockaddr_in in;
1611 type = SOCKET_TYPE_CHAR_TCP;
1614 type = SOCKET_TYPE_CHAR_UDP;
1617 errno = ESOCKTNOSUPPORT;
1621 memset(&in, 0, sizeof(in));
1622 in.sin_family = AF_INET;
1623 in.sin_addr.s_addr = htonl(127<<24 |
1624 socket_wrapper_default_iface());
1626 si->myname_len = sizeof(in);
1627 si->myname = sockaddr_dup(&in, si->myname_len);
1632 struct sockaddr_in6 in6;
1634 if (si->family != family) {
1635 errno = ENETUNREACH;
1641 type = SOCKET_TYPE_CHAR_TCP_V6;
1644 type = SOCKET_TYPE_CHAR_UDP_V6;
1647 errno = ESOCKTNOSUPPORT;
1651 memset(&in6, 0, sizeof(in6));
1652 in6.sin6_family = AF_INET6;
1653 in6.sin6_addr = *swrap_ipv6();
1654 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1655 si->myname_len = sizeof(in6);
1656 si->myname = sockaddr_dup(&in6, si->myname_len);
1661 errno = ESOCKTNOSUPPORT;
1665 if (autobind_start > 60000) {
1666 autobind_start = 10000;
1669 for (i=0;i<1000;i++) {
1670 port = autobind_start + i;
1671 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1672 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1673 type, socket_wrapper_default_iface(), port);
1674 if (stat(un_addr.sun_path, &st) == 0) continue;
1676 ret = real_bind(si->fd, (struct sockaddr *)(void *)&un_addr,
1678 if (ret == -1) return ret;
1680 si->tmp_path = strdup(un_addr.sun_path);
1682 autobind_start = port + 1;
1690 si->family = family;
1691 set_port(si->family, port, si->myname);
1697 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1700 struct sockaddr_un un_addr;
1701 struct socket_info *si = find_socket_info(s);
1705 return real_connect(s, serv_addr, addrlen);
1708 if (si->bound == 0) {
1709 ret = swrap_auto_bind(si, serv_addr->sa_family);
1710 if (ret == -1) return -1;
1713 if (si->family != serv_addr->sa_family) {
1718 ret = sockaddr_convert_to_un(si, serv_addr,
1719 addrlen, &un_addr, 0, &bcast);
1720 if (ret == -1) return -1;
1723 errno = ENETUNREACH;
1727 if (si->type == SOCK_DGRAM) {
1728 si->defer_connect = 1;
1731 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1733 ret = real_connect(s, (struct sockaddr *)(void *)&un_addr,
1734 sizeof(struct sockaddr_un));
1737 /* to give better errors */
1738 if (ret == -1 && errno == ENOENT) {
1739 errno = EHOSTUNREACH;
1743 si->peername_len = addrlen;
1744 si->peername = sockaddr_dup(serv_addr, addrlen);
1747 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1748 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1750 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1756 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1759 struct sockaddr_un un_addr;
1760 struct socket_info *si = find_socket_info(s);
1763 return real_bind(s, myaddr, addrlen);
1766 si->myname_len = addrlen;
1767 si->myname = sockaddr_dup(myaddr, addrlen);
1769 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
1770 if (ret == -1) return -1;
1772 unlink(un_addr.sun_path);
1774 ret = real_bind(s, (struct sockaddr *)(void *)&un_addr,
1775 sizeof(struct sockaddr_un));
1784 _PUBLIC_ int swrap_listen(int s, int backlog)
1787 struct socket_info *si = find_socket_info(s);
1790 return real_listen(s, backlog);
1793 ret = real_listen(s, backlog);
1798 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1800 struct socket_info *si = find_socket_info(s);
1803 return real_getpeername(s, name, addrlen);
1812 memcpy(name, si->peername, si->peername_len);
1813 *addrlen = si->peername_len;
1818 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1820 struct socket_info *si = find_socket_info(s);
1823 return real_getsockname(s, name, addrlen);
1826 memcpy(name, si->myname, si->myname_len);
1827 *addrlen = si->myname_len;
1832 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1834 struct socket_info *si = find_socket_info(s);
1837 return real_getsockopt(s, level, optname, optval, optlen);
1840 if (level == SOL_SOCKET) {
1841 return real_getsockopt(s, level, optname, optval, optlen);
1844 errno = ENOPROTOOPT;
1848 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1850 struct socket_info *si = find_socket_info(s);
1853 return real_setsockopt(s, level, optname, optval, optlen);
1856 if (level == SOL_SOCKET) {
1857 return real_setsockopt(s, level, optname, optval, optlen);
1860 switch (si->family) {
1868 errno = ENOPROTOOPT;
1873 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1876 struct socket_info *si = find_socket_info(s);
1880 return real_ioctl(s, r, p);
1883 ret = real_ioctl(s, r, p);
1887 value = *((int *)p);
1888 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1889 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1890 } else if (value == 0) { /* END OF FILE */
1891 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1899 static ssize_t swrap_sendmsg_before(struct socket_info *si,
1901 struct iovec *tmp_iov,
1902 struct sockaddr_un *tmp_un,
1903 const struct sockaddr_un **to_un,
1904 const struct sockaddr **to,
1922 if (!si->connected) {
1927 if (msg->msg_iovlen == 0) {
1932 * cut down to 1500 byte packets for stream sockets,
1933 * which makes it easier to format PCAP capture files
1934 * (as the caller will simply continue from here)
1937 for (i=0; i < msg->msg_iovlen; i++) {
1939 nlen = len + msg->msg_iov[i].iov_len;
1944 msg->msg_iovlen = i;
1945 if (msg->msg_iovlen == 0) {
1946 *tmp_iov = msg->msg_iov[0];
1947 tmp_iov->iov_len = MIN(tmp_iov->iov_len, 1500);
1948 msg->msg_iov = tmp_iov;
1949 msg->msg_iovlen = 1;
1954 if (si->connected) {
1955 if (msg->msg_name) {
1960 const struct sockaddr *msg_name;
1961 msg_name = (const struct sockaddr *)msg->msg_name;
1963 if (msg_name == NULL) {
1969 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
1971 if (ret == -1) return -1;
1979 msg->msg_name = tmp_un;
1980 msg->msg_namelen = sizeof(*tmp_un);
1983 if (si->bound == 0) {
1984 ret = swrap_auto_bind(si, si->family);
1985 if (ret == -1) return -1;
1988 if (!si->defer_connect) {
1992 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
1994 if (ret == -1) return -1;
1996 ret = real_connect(si->fd, (struct sockaddr *)(void *)tmp_un,
1999 /* to give better errors */
2000 if (ret == -1 && errno == ENOENT) {
2001 errno = EHOSTUNREACH;
2008 si->defer_connect = 0;
2011 errno = EHOSTUNREACH;
2018 static void swrap_sendmsg_after(struct socket_info *si,
2020 const struct sockaddr *to,
2023 int saved_errno = errno;
2030 /* to give better errors */
2031 if (ret == -1 && saved_errno == ENOENT) {
2032 saved_errno = EHOSTUNREACH;
2035 for (i=0; i < msg->msg_iovlen; i++) {
2036 avail += msg->msg_iov[i].iov_len;
2040 remain = MIN(80, avail);
2045 /* we capture it as one single packet */
2046 buf = (uint8_t *)malloc(remain);
2048 /* we just not capture the packet */
2049 errno = saved_errno;
2053 for (i=0; i < msg->msg_iovlen; i++) {
2054 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2056 msg->msg_iov[i].iov_base,
2059 remain -= this_time;
2066 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2067 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2069 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2074 if (si->connected) {
2078 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2079 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
2081 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2087 errno = saved_errno;
2090 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
2092 struct sockaddr_un un_addr;
2093 socklen_t un_addrlen = sizeof(un_addr);
2095 struct socket_info *si = find_socket_info(s);
2096 struct sockaddr_storage ss;
2097 socklen_t ss_len = sizeof(ss);
2100 return real_recvfrom(s, buf, len, flags, from, fromlen);
2104 from = (struct sockaddr *)(void *)&ss;
2108 if (si->type == SOCK_STREAM) {
2109 /* cut down to 1500 byte packets for stream sockets,
2110 * which makes it easier to format PCAP capture files
2111 * (as the caller will simply continue from here) */
2112 len = MIN(len, 1500);
2115 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2116 memset(&un_addr, 0, sizeof(un_addr));
2117 ret = real_recvfrom(s, buf, len, flags,
2118 (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2122 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
2123 si->family, from, fromlen) == -1) {
2127 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
2133 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
2137 struct sockaddr_un un_addr;
2138 const struct sockaddr_un *to_un = NULL;
2140 struct socket_info *si = find_socket_info(s);
2144 return real_sendto(s, buf, len, flags, to, tolen);
2147 tmp.iov_base = discard_const_p(char, buf);
2150 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
2151 msg.msg_namelen = tolen; /* size of address */
2152 msg.msg_iov = &tmp; /* scatter/gather array */
2153 msg.msg_iovlen = 1; /* # elements in msg_iov */
2154 msg.msg_control = NULL; /* ancillary data, see below */
2155 msg.msg_controllen = 0; /* ancillary data buffer len */
2156 msg.msg_flags = 0; /* flags on received message */
2158 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2159 if (ret == -1) return -1;
2161 buf = msg.msg_iov[0].iov_base;
2162 len = msg.msg_iov[0].iov_len;
2167 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2170 type = SOCKET_TYPE_CHAR_UDP;
2172 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2173 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2174 socket_wrapper_dir(), type, iface, prt);
2175 if (stat(un_addr.sun_path, &st) != 0) continue;
2177 /* ignore the any errors in broadcast sends */
2178 real_sendto(s, buf, len, flags,
2179 (struct sockaddr *)(void *)&un_addr,
2183 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2188 ret = real_sendto(s, buf, len, flags, msg.msg_name, msg.msg_namelen);
2190 swrap_sendmsg_after(si, &msg, to, ret);
2195 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
2198 struct socket_info *si = find_socket_info(s);
2201 return real_recv(s, buf, len, flags);
2204 if (si->type == SOCK_STREAM) {
2205 /* cut down to 1500 byte packets for stream sockets,
2206 * which makes it easier to format PCAP capture files
2207 * (as the caller will simply continue from here) */
2208 len = MIN(len, 1500);
2211 ret = real_recv(s, buf, len, flags);
2212 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2213 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2214 } else if (ret == 0) { /* END OF FILE */
2215 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2216 } else if (ret > 0) {
2217 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2223 _PUBLIC_ ssize_t swrap_read(int s, void *buf, size_t len)
2226 struct socket_info *si = find_socket_info(s);
2229 return real_read(s, buf, len);
2232 if (si->type == SOCK_STREAM) {
2233 /* cut down to 1500 byte packets for stream sockets,
2234 * which makes it easier to format PCAP capture files
2235 * (as the caller will simply continue from here) */
2236 len = MIN(len, 1500);
2239 ret = real_read(s, buf, len);
2240 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2241 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2242 } else if (ret == 0) { /* END OF FILE */
2243 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2244 } else if (ret > 0) {
2245 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2252 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2256 struct sockaddr_un un_addr;
2258 struct socket_info *si = find_socket_info(s);
2261 return real_send(s, buf, len, flags);
2264 tmp.iov_base = discard_const_p(char, buf);
2267 msg.msg_name = NULL; /* optional address */
2268 msg.msg_namelen = 0; /* size of address */
2269 msg.msg_iov = &tmp; /* scatter/gather array */
2270 msg.msg_iovlen = 1; /* # elements in msg_iov */
2271 msg.msg_control = NULL; /* ancillary data, see below */
2272 msg.msg_controllen = 0; /* ancillary data buffer len */
2273 msg.msg_flags = 0; /* flags on received message */
2275 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2276 if (ret == -1) return -1;
2278 buf = msg.msg_iov[0].iov_base;
2279 len = msg.msg_iov[0].iov_len;
2281 ret = real_send(s, buf, len, flags);
2283 swrap_sendmsg_after(si, &msg, NULL, ret);
2288 _PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
2292 struct sockaddr_un un_addr;
2293 const struct sockaddr_un *to_un = NULL;
2294 const struct sockaddr *to = NULL;
2296 struct socket_info *si = find_socket_info(s);
2300 return real_sendmsg(s, omsg, flags);
2303 tmp.iov_base = NULL;
2306 msg.msg_name = omsg->msg_name; /* optional address */
2307 msg.msg_namelen = omsg->msg_namelen; /* size of address */
2308 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
2309 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
2310 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
2311 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
2312 msg.msg_flags = omsg->msg_flags; /* flags on received message */
2314 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
2315 if (ret == -1) return -1;
2320 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
2328 for (i=0; i < msg.msg_iovlen; i++) {
2329 avail += msg.msg_iov[i].iov_len;
2335 /* we capture it as one single packet */
2336 buf = (uint8_t *)malloc(remain);
2341 for (i=0; i < msg.msg_iovlen; i++) {
2342 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
2344 msg.msg_iov[i].iov_base,
2347 remain -= this_time;
2350 type = SOCKET_TYPE_CHAR_UDP;
2352 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
2353 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
2354 socket_wrapper_dir(), type, iface, prt);
2355 if (stat(un_addr.sun_path, &st) != 0) continue;
2357 msg.msg_name = &un_addr; /* optional address */
2358 msg.msg_namelen = sizeof(un_addr); /* size of address */
2360 /* ignore the any errors in broadcast sends */
2361 real_sendmsg(s, &msg, flags);
2364 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2370 ret = real_sendmsg(s, &msg, flags);
2372 swrap_sendmsg_after(si, &msg, to, ret);
2377 int swrap_readv(int s, const struct iovec *vector, size_t count)
2380 struct socket_info *si = find_socket_info(s);
2384 return real_readv(s, vector, count);
2387 if (!si->connected) {
2392 if (si->type == SOCK_STREAM && count > 0) {
2393 /* cut down to 1500 byte packets for stream sockets,
2394 * which makes it easier to format PCAP capture files
2395 * (as the caller will simply continue from here) */
2398 for (i=0; i < count; i++) {
2400 nlen = len + vector[i].iov_len;
2408 v.iov_len = MIN(v.iov_len, 1500);
2414 ret = real_readv(s, vector, count);
2415 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2416 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2417 } else if (ret == 0) { /* END OF FILE */
2418 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2419 } else if (ret > 0) {
2423 size_t remain = ret;
2425 /* we capture it as one single packet */
2426 buf = (uint8_t *)malloc(ret);
2428 /* we just not capture the packet */
2433 for (i=0; i < count; i++) {
2434 size_t this_time = MIN(remain, vector[i].iov_len);
2439 remain -= this_time;
2442 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2449 int swrap_writev(int s, const struct iovec *vector, size_t count)
2453 struct sockaddr_un un_addr;
2455 struct socket_info *si = find_socket_info(s);
2458 return real_writev(s, vector, count);
2461 tmp.iov_base = NULL;
2464 msg.msg_name = NULL; /* optional address */
2465 msg.msg_namelen = 0; /* size of address */
2466 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
2467 msg.msg_iovlen = count; /* # elements in msg_iov */
2468 msg.msg_control = NULL; /* ancillary data, see below */
2469 msg.msg_controllen = 0; /* ancillary data buffer len */
2470 msg.msg_flags = 0; /* flags on received message */
2472 ret = swrap_sendmsg_before(si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
2473 if (ret == -1) return -1;
2475 ret = real_writev(s, msg.msg_iov, msg.msg_iovlen);
2477 swrap_sendmsg_after(si, &msg, NULL, ret);
2482 _PUBLIC_ int swrap_close(int fd)
2484 struct socket_info *si = find_socket_info(fd);
2488 return real_close(fd);
2491 SWRAP_DLIST_REMOVE(sockets, si);
2493 if (si->myname && si->peername) {
2494 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2497 ret = real_close(fd);
2499 if (si->myname && si->peername) {
2500 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2501 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2504 if (si->path) free(si->path);
2505 if (si->myname) free(si->myname);
2506 if (si->peername) free(si->peername);
2508 unlink(si->tmp_path);