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_ioctl ioctl
122 #define real_recv recv
123 #define real_send send
124 #define real_readv readv
125 #define real_writev writev
126 #define real_socket socket
127 #define real_close close
130 #ifdef HAVE_GETTIMEOFDAY_TZ
131 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
136 /* we need to use a very terse format here as IRIX 6.4 silently
137 truncates names to 16 chars, so if we use a longer name then we
138 can't tell which port a packet came from with recvfrom()
140 with this format we have 8 chars left for the directory name
142 #define SOCKET_FORMAT "%c%02X%04X"
143 #define SOCKET_TYPE_CHAR_TCP 'T'
144 #define SOCKET_TYPE_CHAR_UDP 'U'
145 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
146 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
148 #define MAX_WRAPPED_INTERFACES 16
154 static const struct in6_addr *swrap_ipv6(void)
156 static struct in6_addr v;
157 static int initialized;
165 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
174 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
176 struct sockaddr *ret = (struct sockaddr *)malloc(len);
177 memcpy(ret, data, len);
181 static void set_port(int family, int prt, struct sockaddr *addr)
185 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
189 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
195 static size_t socket_length(int family)
199 return sizeof(struct sockaddr_in);
202 return sizeof(struct sockaddr_in6);
226 struct sockaddr *myname;
227 socklen_t myname_len;
229 struct sockaddr *peername;
230 socklen_t peername_len;
233 unsigned long pck_snd;
234 unsigned long pck_rcv;
237 struct socket_info *prev, *next;
240 static struct socket_info *sockets;
242 const char *socket_wrapper_dir(void)
244 const char *s = getenv("SOCKET_WRAPPER_DIR");
248 if (strncmp(s, "./", 2) == 0) {
254 unsigned int socket_wrapper_default_iface(void)
256 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
259 if (sscanf(s, "%u", &iface) == 1) {
260 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
266 return 1;/* 127.0.0.1 */
269 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
276 p = strrchr(un->sun_path, '/');
277 if (p) p++; else p = un->sun_path;
279 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
284 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
295 case SOCKET_TYPE_CHAR_TCP:
296 case SOCKET_TYPE_CHAR_UDP: {
297 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
299 if ((*len) < sizeof(*in2)) {
304 memset(in2, 0, sizeof(*in2));
305 in2->sin_family = AF_INET;
306 in2->sin_addr.s_addr = htonl((127<<24) | iface);
307 in2->sin_port = htons(prt);
313 case SOCKET_TYPE_CHAR_TCP_V6:
314 case SOCKET_TYPE_CHAR_UDP_V6: {
315 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
317 if ((*len) < sizeof(*in2)) {
322 memset(in2, 0, sizeof(*in2));
323 in2->sin6_family = AF_INET6;
324 in2->sin6_addr = *swrap_ipv6();
325 in2->sin6_addr.s6_addr[15] = iface;
326 in2->sin6_port = htons(prt);
340 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
348 if (bcast) *bcast = 0;
350 switch (si->family) {
352 const struct sockaddr_in *in =
353 (const struct sockaddr_in *)inaddr;
354 unsigned int addr = ntohl(in->sin_addr.s_addr);
361 u_type = SOCKET_TYPE_CHAR_TCP;
364 u_type = SOCKET_TYPE_CHAR_UDP;
365 a_type = SOCKET_TYPE_CHAR_UDP;
366 b_type = SOCKET_TYPE_CHAR_UDP;
370 prt = ntohs(in->sin_port);
371 if (a_type && addr == 0xFFFFFFFF) {
372 /* 255.255.255.255 only udp */
375 iface = socket_wrapper_default_iface();
376 } else if (b_type && addr == 0x7FFFFFFF) {
377 /* 127.255.255.255 only udp */
380 iface = socket_wrapper_default_iface();
381 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
385 iface = (addr & 0x000000FF);
390 if (bcast) *bcast = is_bcast;
395 const struct sockaddr_in6 *in =
396 (const struct sockaddr_in6 *)inaddr;
401 type = SOCKET_TYPE_CHAR_TCP_V6;
404 type = SOCKET_TYPE_CHAR_UDP_V6;
408 /* XXX no multicast/broadcast */
410 prt = ntohs(in->sin6_port);
414 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
415 iface = in->sin6_addr.s6_addr[15];
435 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
436 socket_wrapper_dir());
437 /* the caller need to do more processing */
441 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
442 socket_wrapper_dir(), type, iface, prt);
447 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
456 if (bcast) *bcast = 0;
458 switch (si->family) {
460 const struct sockaddr_in *in =
461 (const struct sockaddr_in *)inaddr;
462 unsigned int addr = ntohl(in->sin_addr.s_addr);
468 prt = ntohs(in->sin_port);
472 u_type = SOCKET_TYPE_CHAR_TCP;
473 d_type = SOCKET_TYPE_CHAR_TCP;
476 u_type = SOCKET_TYPE_CHAR_UDP;
477 d_type = SOCKET_TYPE_CHAR_UDP;
478 a_type = SOCKET_TYPE_CHAR_UDP;
479 b_type = SOCKET_TYPE_CHAR_UDP;
487 iface = socket_wrapper_default_iface();
488 } else if (a_type && addr == 0xFFFFFFFF) {
489 /* 255.255.255.255 only udp */
492 iface = socket_wrapper_default_iface();
493 } else if (b_type && addr == 0x7FFFFFFF) {
494 /* 127.255.255.255 only udp */
497 iface = socket_wrapper_default_iface();
498 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
502 iface = (addr & 0x000000FF);
504 errno = EADDRNOTAVAIL;
511 const struct sockaddr_in6 *in =
512 (const struct sockaddr_in6 *)inaddr;
517 type = SOCKET_TYPE_CHAR_TCP_V6;
520 type = SOCKET_TYPE_CHAR_UDP_V6;
524 /* XXX no multicast/broadcast */
526 prt = ntohs(in->sin6_port);
530 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
531 iface = socket_wrapper_default_iface();
532 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
533 iface = in->sin6_addr.s6_addr[15];
535 errno = EADDRNOTAVAIL;
543 errno = EADDRNOTAVAIL;
548 if (bcast) *bcast = is_bcast;
551 /* handle auto-allocation of ephemeral ports */
552 for (prt = 5001; prt < 10000; prt++) {
553 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
554 socket_wrapper_dir(), type, iface, prt);
555 if (stat(un->sun_path, &st) == 0) continue;
557 set_port(si->family, prt, si->myname);
566 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
567 socket_wrapper_dir(), type, iface, prt);
571 static struct socket_info *find_socket_info(int fd)
573 struct socket_info *i;
574 for (i = sockets; i; i = i->next) {
582 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
583 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
588 out_addr->sun_family = AF_UNIX;
590 switch (in_addr->sa_family) {
600 errno = ESOCKTNOSUPPORT;
604 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
606 return convert_in_un_remote(si, in_addr, out_addr, bcast);
612 errno = EAFNOSUPPORT;
616 static int sockaddr_convert_from_un(const struct socket_info *si,
617 const struct sockaddr_un *in_addr,
618 socklen_t un_addrlen,
620 struct sockaddr *out_addr,
621 socklen_t *out_addrlen)
623 if (out_addr == NULL || out_addrlen == NULL)
626 if (un_addrlen == 0) {
641 errno = ESOCKTNOSUPPORT;
644 return convert_un_in(in_addr, out_addr, out_addrlen);
649 errno = EAFNOSUPPORT;
653 enum swrap_packet_type {
655 SWRAP_CONNECT_UNREACH,
663 SWRAP_SENDTO_UNREACH,
674 struct swrap_file_hdr {
676 uint16_t version_major;
677 uint16_t version_minor;
680 uint32_t frame_max_len;
681 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
684 #define SWRAP_FILE_HDR_SIZE 24
686 struct swrap_packet_frame {
688 uint32_t micro_seconds;
689 uint32_t recorded_length;
690 uint32_t full_length;
692 #define SWRAP_PACKET_FRAME_SIZE 16
694 union swrap_packet_ip {
698 uint16_t packet_length;
699 uint16_t identification;
704 uint16_t hdr_checksum;
708 #define SWRAP_PACKET_IP_V4_SIZE 20
711 uint8_t flow_label_high;
712 uint16_t flow_label_low;
713 uint16_t payload_length;
716 uint8_t src_addr[16];
717 uint8_t dest_addr[16];
719 #define SWRAP_PACKET_IP_V6_SIZE 40
721 #define SWRAP_PACKET_IP_SIZE 40
723 union swrap_packet_payload {
725 uint16_t source_port;
735 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
737 uint16_t source_port;
742 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
749 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
756 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
758 #define SWRAP_PACKET_PAYLOAD_SIZE 20
760 #define SWRAP_PACKET_MIN_ALLOC \
761 (SWRAP_PACKET_FRAME_SIZE + \
762 SWRAP_PACKET_IP_SIZE + \
763 SWRAP_PACKET_PAYLOAD_SIZE)
765 static const char *socket_wrapper_pcap_file(void)
767 static int initialized = 0;
768 static const char *s = NULL;
769 static const struct swrap_file_hdr h;
770 static const struct swrap_packet_frame f;
771 static const union swrap_packet_ip i;
772 static const union swrap_packet_payload p;
774 if (initialized == 1) {
780 * TODO: don't use the structs use plain buffer offsets
781 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
783 * for now make sure we disable PCAP support
784 * if the struct has alignment!
786 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
789 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
792 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
795 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
798 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
801 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
804 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
807 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
810 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
813 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
817 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
821 if (strncmp(s, "./", 2) == 0) {
827 static uint8_t *swrap_packet_init(struct timeval *tval,
828 const struct sockaddr *src,
829 const struct sockaddr *dest,
831 const uint8_t *payload,
833 unsigned long tcp_seqno,
834 unsigned long tcp_ack,
835 unsigned char tcp_ctl,
841 struct swrap_packet_frame *frame;
842 union swrap_packet_ip *ip;
843 union swrap_packet_payload *pay;
846 size_t nonwire_len = sizeof(*frame);
847 size_t wire_hdr_len = 0;
849 size_t ip_hdr_len = 0;
850 size_t icmp_hdr_len = 0;
851 size_t icmp_truncate_len = 0;
852 uint8_t protocol = 0, icmp_protocol = 0;
853 const struct sockaddr_in *src_in = NULL;
854 const struct sockaddr_in *dest_in = NULL;
856 const struct sockaddr_in6 *src_in6 = NULL;
857 const struct sockaddr_in6 *dest_in6 = NULL;
862 switch (src->sa_family) {
864 src_in = (const struct sockaddr_in *)src;
865 dest_in = (const struct sockaddr_in *)dest;
866 src_port = src_in->sin_port;
867 dest_port = dest_in->sin_port;
868 ip_hdr_len = sizeof(ip->v4);
872 src_in6 = (const struct sockaddr_in6 *)src;
873 dest_in6 = (const struct sockaddr_in6 *)dest;
874 src_port = src_in6->sin6_port;
875 dest_port = dest_in6->sin6_port;
876 ip_hdr_len = sizeof(ip->v6);
883 switch (socket_type) {
885 protocol = 0x06; /* TCP */
886 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
887 wire_len = wire_hdr_len + payload_len;
891 protocol = 0x11; /* UDP */
892 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
893 wire_len = wire_hdr_len + payload_len;
901 icmp_protocol = protocol;
902 switch (src->sa_family) {
904 protocol = 0x01; /* ICMPv4 */
905 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
909 protocol = 0x3A; /* ICMPv6 */
910 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
914 if (wire_len > 64 ) {
915 icmp_truncate_len = wire_len - 64;
917 wire_hdr_len += icmp_hdr_len;
918 wire_len += icmp_hdr_len;
921 packet_len = nonwire_len + wire_len;
922 alloc_len = packet_len;
923 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
924 alloc_len = SWRAP_PACKET_MIN_ALLOC;
927 base = (uint8_t *)malloc(alloc_len);
928 if (!base) return NULL;
932 frame = (struct swrap_packet_frame *)buf;
933 frame->seconds = tval->tv_sec;
934 frame->micro_seconds = tval->tv_usec;
935 frame->recorded_length = wire_len - icmp_truncate_len;
936 frame->full_length = wire_len - icmp_truncate_len;
937 buf += SWRAP_PACKET_FRAME_SIZE;
939 ip = (union swrap_packet_ip *)buf;
940 switch (src->sa_family) {
942 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
944 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
945 ip->v4.identification = htons(0xFFFF);
946 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
947 ip->v4.fragment = htons(0x0000);
949 ip->v4.protocol = protocol;
950 ip->v4.hdr_checksum = htons(0x0000);
951 ip->v4.src_addr = src_in->sin_addr.s_addr;
952 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
953 buf += SWRAP_PACKET_IP_V4_SIZE;
957 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
958 ip->v6.flow_label_high = 0x00;
959 ip->v6.flow_label_low = 0x0000;
960 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
961 ip->v6.next_header = protocol;
962 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
963 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
964 buf += SWRAP_PACKET_IP_V6_SIZE;
970 pay = (union swrap_packet_payload *)buf;
971 switch (src->sa_family) {
973 pay->icmp4.type = 0x03; /* destination unreachable */
974 pay->icmp4.code = 0x01; /* host unreachable */
975 pay->icmp4.checksum = htons(0x0000);
976 pay->icmp4.unused = htonl(0x00000000);
977 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
979 /* set the ip header in the ICMP payload */
980 ip = (union swrap_packet_ip *)buf;
981 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
983 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
984 ip->v4.identification = htons(0xFFFF);
985 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
986 ip->v4.fragment = htons(0x0000);
988 ip->v4.protocol = icmp_protocol;
989 ip->v4.hdr_checksum = htons(0x0000);
990 ip->v4.src_addr = dest_in->sin_addr.s_addr;
991 ip->v4.dest_addr = src_in->sin_addr.s_addr;
992 buf += SWRAP_PACKET_IP_V4_SIZE;
994 src_port = dest_in->sin_port;
995 dest_port = src_in->sin_port;
999 pay->icmp6.type = 0x01; /* destination unreachable */
1000 pay->icmp6.code = 0x03; /* address unreachable */
1001 pay->icmp6.checksum = htons(0x0000);
1002 pay->icmp6.unused = htonl(0x00000000);
1003 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1005 /* set the ip header in the ICMP payload */
1006 ip = (union swrap_packet_ip *)buf;
1007 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1008 ip->v6.flow_label_high = 0x00;
1009 ip->v6.flow_label_low = 0x0000;
1010 ip->v6.payload_length = htons(wire_len - icmp_truncate_len);//TODO
1011 ip->v6.next_header = protocol;
1012 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1013 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1014 buf += SWRAP_PACKET_IP_V6_SIZE;
1016 src_port = dest_in6->sin6_port;
1017 dest_port = src_in6->sin6_port;
1023 pay = (union swrap_packet_payload *)buf;
1025 switch (socket_type) {
1027 pay->tcp.source_port = src_port;
1028 pay->tcp.dest_port = dest_port;
1029 pay->tcp.seq_num = htonl(tcp_seqno);
1030 pay->tcp.ack_num = htonl(tcp_ack);
1031 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1032 pay->tcp.control = tcp_ctl;
1033 pay->tcp.window = htons(0x7FFF);
1034 pay->tcp.checksum = htons(0x0000);
1035 pay->tcp.urg = htons(0x0000);
1036 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1041 pay->udp.source_port = src_port;
1042 pay->udp.dest_port = dest_port;
1043 pay->udp.length = htons(8 + payload_len);
1044 pay->udp.checksum = htons(0x0000);
1045 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1050 if (payload && payload_len > 0) {
1051 memcpy(buf, payload, payload_len);
1054 *_packet_len = packet_len - icmp_truncate_len;
1058 static int swrap_get_pcap_fd(const char *fname)
1062 if (fd != -1) return fd;
1064 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1066 struct swrap_file_hdr file_hdr;
1067 file_hdr.magic = 0xA1B2C3D4;
1068 file_hdr.version_major = 0x0002;
1069 file_hdr.version_minor = 0x0004;
1070 file_hdr.timezone = 0x00000000;
1071 file_hdr.sigfigs = 0x00000000;
1072 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1073 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1075 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1082 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1087 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1088 const struct sockaddr *addr,
1089 enum swrap_packet_type type,
1090 const void *buf, size_t len,
1093 const struct sockaddr *src_addr;
1094 const struct sockaddr *dest_addr;
1095 unsigned long tcp_seqno = 0;
1096 unsigned long tcp_ack = 0;
1097 unsigned char tcp_ctl = 0;
1098 int unreachable = 0;
1102 switch (si->family) {
1112 case SWRAP_CONNECT_SEND:
1113 if (si->type != SOCK_STREAM) return NULL;
1115 src_addr = si->myname;
1118 tcp_seqno = si->io.pck_snd;
1119 tcp_ack = si->io.pck_rcv;
1120 tcp_ctl = 0x02; /* SYN */
1122 si->io.pck_snd += 1;
1126 case SWRAP_CONNECT_RECV:
1127 if (si->type != SOCK_STREAM) return NULL;
1129 dest_addr = si->myname;
1132 tcp_seqno = si->io.pck_rcv;
1133 tcp_ack = si->io.pck_snd;
1134 tcp_ctl = 0x12; /** SYN,ACK */
1136 si->io.pck_rcv += 1;
1140 case SWRAP_CONNECT_UNREACH:
1141 if (si->type != SOCK_STREAM) return NULL;
1143 dest_addr = si->myname;
1146 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1147 tcp_seqno = si->io.pck_snd - 1;
1148 tcp_ack = si->io.pck_rcv;
1149 tcp_ctl = 0x02; /* SYN */
1154 case SWRAP_CONNECT_ACK:
1155 if (si->type != SOCK_STREAM) return NULL;
1157 src_addr = si->myname;
1160 tcp_seqno = si->io.pck_snd;
1161 tcp_ack = si->io.pck_rcv;
1162 tcp_ctl = 0x10; /* ACK */
1166 case SWRAP_ACCEPT_SEND:
1167 if (si->type != SOCK_STREAM) return NULL;
1169 dest_addr = si->myname;
1172 tcp_seqno = si->io.pck_rcv;
1173 tcp_ack = si->io.pck_snd;
1174 tcp_ctl = 0x02; /* SYN */
1176 si->io.pck_rcv += 1;
1180 case SWRAP_ACCEPT_RECV:
1181 if (si->type != SOCK_STREAM) return NULL;
1183 src_addr = si->myname;
1186 tcp_seqno = si->io.pck_snd;
1187 tcp_ack = si->io.pck_rcv;
1188 tcp_ctl = 0x12; /* SYN,ACK */
1190 si->io.pck_snd += 1;
1194 case SWRAP_ACCEPT_ACK:
1195 if (si->type != SOCK_STREAM) return NULL;
1197 dest_addr = si->myname;
1200 tcp_seqno = si->io.pck_rcv;
1201 tcp_ack = si->io.pck_snd;
1202 tcp_ctl = 0x10; /* ACK */
1207 src_addr = si->myname;
1208 dest_addr = si->peername;
1210 tcp_seqno = si->io.pck_snd;
1211 tcp_ack = si->io.pck_rcv;
1212 tcp_ctl = 0x18; /* PSH,ACK */
1214 si->io.pck_snd += len;
1218 case SWRAP_SEND_RST:
1219 dest_addr = si->myname;
1220 src_addr = si->peername;
1222 if (si->type == SOCK_DGRAM) {
1223 return swrap_marshall_packet(si, si->peername,
1224 SWRAP_SENDTO_UNREACH,
1225 buf, len, packet_len);
1228 tcp_seqno = si->io.pck_rcv;
1229 tcp_ack = si->io.pck_snd;
1230 tcp_ctl = 0x14; /** RST,ACK */
1234 case SWRAP_PENDING_RST:
1235 dest_addr = si->myname;
1236 src_addr = si->peername;
1238 if (si->type == SOCK_DGRAM) {
1242 tcp_seqno = si->io.pck_rcv;
1243 tcp_ack = si->io.pck_snd;
1244 tcp_ctl = 0x14; /* RST,ACK */
1249 dest_addr = si->myname;
1250 src_addr = si->peername;
1252 tcp_seqno = si->io.pck_rcv;
1253 tcp_ack = si->io.pck_snd;
1254 tcp_ctl = 0x18; /* PSH,ACK */
1256 si->io.pck_rcv += len;
1260 case SWRAP_RECV_RST:
1261 dest_addr = si->myname;
1262 src_addr = si->peername;
1264 if (si->type == SOCK_DGRAM) {
1268 tcp_seqno = si->io.pck_rcv;
1269 tcp_ack = si->io.pck_snd;
1270 tcp_ctl = 0x14; /* RST,ACK */
1275 src_addr = si->myname;
1278 si->io.pck_snd += len;
1282 case SWRAP_SENDTO_UNREACH:
1283 dest_addr = si->myname;
1290 case SWRAP_RECVFROM:
1291 dest_addr = si->myname;
1294 si->io.pck_rcv += len;
1298 case SWRAP_CLOSE_SEND:
1299 if (si->type != SOCK_STREAM) return NULL;
1301 src_addr = si->myname;
1302 dest_addr = si->peername;
1304 tcp_seqno = si->io.pck_snd;
1305 tcp_ack = si->io.pck_rcv;
1306 tcp_ctl = 0x11; /* FIN, ACK */
1308 si->io.pck_snd += 1;
1312 case SWRAP_CLOSE_RECV:
1313 if (si->type != SOCK_STREAM) return NULL;
1315 dest_addr = si->myname;
1316 src_addr = si->peername;
1318 tcp_seqno = si->io.pck_rcv;
1319 tcp_ack = si->io.pck_snd;
1320 tcp_ctl = 0x11; /* FIN,ACK */
1322 si->io.pck_rcv += 1;
1326 case SWRAP_CLOSE_ACK:
1327 if (si->type != SOCK_STREAM) return NULL;
1329 src_addr = si->myname;
1330 dest_addr = si->peername;
1332 tcp_seqno = si->io.pck_snd;
1333 tcp_ack = si->io.pck_rcv;
1334 tcp_ctl = 0x10; /* ACK */
1341 swrapGetTimeOfDay(&tv);
1343 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1344 (const uint8_t *)buf, len,
1345 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1349 static void swrap_dump_packet(struct socket_info *si,
1350 const struct sockaddr *addr,
1351 enum swrap_packet_type type,
1352 const void *buf, size_t len)
1354 const char *file_name;
1356 size_t packet_len = 0;
1359 file_name = socket_wrapper_pcap_file();
1364 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1369 fd = swrap_get_pcap_fd(file_name);
1371 if (write(fd, packet, packet_len) != packet_len) {
1380 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1382 struct socket_info *si;
1385 if (!socket_wrapper_dir()) {
1386 return real_socket(family, type, protocol);
1396 return real_socket(family, type, protocol);
1398 errno = EAFNOSUPPORT;
1408 errno = EPROTONOSUPPORT;
1416 if (type == SOCK_STREAM) {
1421 if (type == SOCK_DGRAM) {
1426 errno = EPROTONOSUPPORT;
1430 fd = real_socket(AF_UNIX, type, 0);
1432 if (fd == -1) return -1;
1434 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1436 si->family = family;
1438 si->protocol = protocol;
1441 SWRAP_DLIST_ADD(sockets, si);
1446 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1448 struct socket_info *parent_si, *child_si;
1450 struct sockaddr_un un_addr;
1451 socklen_t un_addrlen = sizeof(un_addr);
1452 struct sockaddr_un un_my_addr;
1453 socklen_t un_my_addrlen = sizeof(un_my_addr);
1454 struct sockaddr *my_addr;
1455 socklen_t my_addrlen, len;
1458 parent_si = find_socket_info(s);
1460 return real_accept(s, addr, addrlen);
1464 * assume out sockaddr have the same size as the in parent
1467 my_addrlen = socket_length(parent_si->family);
1468 if (my_addrlen <= 0) {
1473 my_addr = (struct sockaddr *)malloc(my_addrlen);
1474 if (my_addr == NULL) {
1478 memset(&un_addr, 0, sizeof(un_addr));
1479 memset(&un_my_addr, 0, sizeof(un_my_addr));
1481 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1490 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1491 parent_si->family, my_addr, &len);
1498 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1499 memset(child_si, 0, sizeof(*child_si));
1502 child_si->family = parent_si->family;
1503 child_si->type = parent_si->type;
1504 child_si->protocol = parent_si->protocol;
1505 child_si->bound = 1;
1506 child_si->is_server = 1;
1507 child_si->connected = 1;
1509 child_si->peername_len = len;
1510 child_si->peername = sockaddr_dup(my_addr, len);
1512 if (addr != NULL && addrlen != NULL) {
1514 if (*addrlen >= len)
1515 memcpy(addr, my_addr, len);
1519 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1527 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1528 child_si->family, my_addr, &len);
1536 child_si->myname_len = len;
1537 child_si->myname = sockaddr_dup(my_addr, len);
1540 SWRAP_DLIST_ADD(sockets, child_si);
1542 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1543 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1544 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1549 static int autobind_start_init;
1550 static int autobind_start;
1552 /* using sendto() or connect() on an unbound socket would give the
1553 recipient no way to reply, as unlike UDP and TCP, a unix domain
1554 socket can't auto-assign emphemeral port numbers, so we need to
1556 Note: this might change the family from ipv6 to ipv4
1558 static int swrap_auto_bind(struct socket_info *si, int family)
1560 struct sockaddr_un un_addr;
1567 if (autobind_start_init != 1) {
1568 autobind_start_init = 1;
1569 autobind_start = getpid();
1570 autobind_start %= 50000;
1571 autobind_start += 10000;
1574 un_addr.sun_family = AF_UNIX;
1578 struct sockaddr_in in;
1582 type = SOCKET_TYPE_CHAR_TCP;
1585 type = SOCKET_TYPE_CHAR_UDP;
1588 errno = ESOCKTNOSUPPORT;
1592 memset(&in, 0, sizeof(in));
1593 in.sin_family = AF_INET;
1594 in.sin_addr.s_addr = htonl(127<<24 |
1595 socket_wrapper_default_iface());
1597 si->myname_len = sizeof(in);
1598 si->myname = sockaddr_dup(&in, si->myname_len);
1603 struct sockaddr_in6 in6;
1605 if (si->family != family) {
1606 errno = ENETUNREACH;
1612 type = SOCKET_TYPE_CHAR_TCP_V6;
1615 type = SOCKET_TYPE_CHAR_UDP_V6;
1618 errno = ESOCKTNOSUPPORT;
1622 memset(&in6, 0, sizeof(in6));
1623 in6.sin6_family = AF_INET6;
1624 in6.sin6_addr = *swrap_ipv6();
1625 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1626 si->myname_len = sizeof(in6);
1627 si->myname = sockaddr_dup(&in6, si->myname_len);
1632 errno = ESOCKTNOSUPPORT;
1636 if (autobind_start > 60000) {
1637 autobind_start = 10000;
1640 for (i=0;i<1000;i++) {
1641 port = autobind_start + i;
1642 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1643 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1644 type, socket_wrapper_default_iface(), port);
1645 if (stat(un_addr.sun_path, &st) == 0) continue;
1647 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1648 if (ret == -1) return ret;
1650 si->tmp_path = strdup(un_addr.sun_path);
1652 autobind_start = port + 1;
1660 si->family = family;
1661 set_port(si->family, port, si->myname);
1667 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1670 struct sockaddr_un un_addr;
1671 struct socket_info *si = find_socket_info(s);
1674 return real_connect(s, serv_addr, addrlen);
1677 if (si->bound == 0) {
1678 ret = swrap_auto_bind(si, serv_addr->sa_family);
1679 if (ret == -1) return -1;
1682 if (si->family != serv_addr->sa_family) {
1687 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1688 if (ret == -1) return -1;
1690 if (si->type == SOCK_DGRAM) {
1691 si->defer_connect = 1;
1694 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1696 ret = real_connect(s, (struct sockaddr *)&un_addr,
1697 sizeof(struct sockaddr_un));
1700 /* to give better errors */
1701 if (ret == -1 && errno == ENOENT) {
1702 errno = EHOSTUNREACH;
1706 si->peername_len = addrlen;
1707 si->peername = sockaddr_dup(serv_addr, addrlen);
1710 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1711 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1713 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1719 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1722 struct sockaddr_un un_addr;
1723 struct socket_info *si = find_socket_info(s);
1726 return real_bind(s, myaddr, addrlen);
1729 si->myname_len = addrlen;
1730 si->myname = sockaddr_dup(myaddr, addrlen);
1732 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1733 if (ret == -1) return -1;
1735 unlink(un_addr.sun_path);
1737 ret = real_bind(s, (struct sockaddr *)&un_addr,
1738 sizeof(struct sockaddr_un));
1747 _PUBLIC_ int swrap_listen(int s, int backlog)
1750 struct socket_info *si = find_socket_info(s);
1753 return real_listen(s, backlog);
1756 ret = real_listen(s, backlog);
1761 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1763 struct socket_info *si = find_socket_info(s);
1766 return real_getpeername(s, name, addrlen);
1775 memcpy(name, si->peername, si->peername_len);
1776 *addrlen = si->peername_len;
1781 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1783 struct socket_info *si = find_socket_info(s);
1786 return real_getsockname(s, name, addrlen);
1789 memcpy(name, si->myname, si->myname_len);
1790 *addrlen = si->myname_len;
1795 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1797 struct socket_info *si = find_socket_info(s);
1800 return real_getsockopt(s, level, optname, optval, optlen);
1803 if (level == SOL_SOCKET) {
1804 return real_getsockopt(s, level, optname, optval, optlen);
1807 errno = ENOPROTOOPT;
1811 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1813 struct socket_info *si = find_socket_info(s);
1816 return real_setsockopt(s, level, optname, optval, optlen);
1819 if (level == SOL_SOCKET) {
1820 return real_setsockopt(s, level, optname, optval, optlen);
1823 switch (si->family) {
1827 errno = ENOPROTOOPT;
1832 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1834 struct sockaddr_un un_addr;
1835 socklen_t un_addrlen = sizeof(un_addr);
1837 struct socket_info *si = find_socket_info(s);
1838 struct sockaddr_storage ss;
1839 socklen_t ss_len = sizeof(ss);
1842 return real_recvfrom(s, buf, len, flags, from, fromlen);
1846 from = (struct sockaddr *)&ss;
1850 len = MIN(len, 1500);
1852 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1853 memset(&un_addr, 0, sizeof(un_addr));
1854 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1858 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1859 si->family, from, fromlen) == -1) {
1863 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1869 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1871 struct sockaddr_un un_addr;
1873 struct socket_info *si = find_socket_info(s);
1877 return real_sendto(s, buf, len, flags, to, tolen);
1880 if (si->connected) {
1887 tolen = si->peername_len;
1890 len = MIN(len, 1500);
1894 ret = real_send(s, buf, len, flags);
1897 if (si->bound == 0) {
1898 ret = swrap_auto_bind(si, si->family);
1899 if (ret == -1) return -1;
1902 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1903 if (ret == -1) return -1;
1908 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1911 type = SOCKET_TYPE_CHAR_UDP;
1913 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1914 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1915 socket_wrapper_dir(), type, iface, prt);
1916 if (stat(un_addr.sun_path, &st) != 0) continue;
1918 /* ignore the any errors in broadcast sends */
1919 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1922 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1927 if (si->defer_connect) {
1928 ret = real_connect(s, (struct sockaddr *)&un_addr,
1931 /* to give better errors */
1932 if (ret == -1 && errno == ENOENT) {
1933 errno = EHOSTUNREACH;
1939 si->defer_connect = 0;
1942 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1946 errno = EHOSTUNREACH;
1950 /* to give better errors */
1951 if (ret == -1 && errno == ENOENT) {
1952 errno = EHOSTUNREACH;
1956 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1957 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1959 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1965 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1968 struct socket_info *si = find_socket_info(s);
1972 return real_ioctl(s, r, p);
1975 ret = real_ioctl(s, r, p);
1979 value = *((int *)p);
1980 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1981 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1982 } else if (value == 0) { /* END OF FILE */
1983 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1991 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1994 struct socket_info *si = find_socket_info(s);
1997 return real_recv(s, buf, len, flags);
2000 len = MIN(len, 1500);
2002 ret = real_recv(s, buf, len, flags);
2003 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2004 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2005 } else if (ret == 0) { /* END OF FILE */
2006 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2007 } else if (ret > 0) {
2008 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2015 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2018 struct socket_info *si = find_socket_info(s);
2021 return real_send(s, buf, len, flags);
2024 len = MIN(len, 1500);
2026 if (si->defer_connect) {
2027 struct sockaddr_un un_addr;
2030 if (si->bound == 0) {
2031 ret = swrap_auto_bind(si, si->family);
2032 if (ret == -1) return -1;
2035 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2036 &un_addr, 0, &bcast);
2037 if (ret == -1) return -1;
2039 ret = real_connect(s, (struct sockaddr *)&un_addr,
2042 /* to give better errors */
2043 if (ret == -1 && errno == ENOENT) {
2044 errno = EHOSTUNREACH;
2050 si->defer_connect = 0;
2053 ret = real_send(s, buf, len, flags);
2056 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2057 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2059 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2065 int swrap_readv(int s, const struct iovec *vector, size_t count)
2068 struct socket_info *si = find_socket_info(s);
2072 return real_readv(s, vector, count);
2075 /* we read 1500 bytes as maximum */
2079 for (i=0; i < count; i++) {
2081 nlen = len + vector[i].iov_len;
2089 v.iov_len = MIN(v.iov_len, 1500);
2095 ret = real_readv(s, vector, count);
2096 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2097 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2098 } else if (ret == 0) { /* END OF FILE */
2099 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2100 } else if (ret > 0) {
2105 /* we capture it as one single packet */
2106 buf = (uint8_t *)malloc(ret);
2108 /* we just not capture the packet */
2113 for (i=0; i < count; i++) {
2117 ofs += vector[i].iov_len;
2120 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2127 int swrap_writev(int s, const struct iovec *vector, size_t count)
2130 struct socket_info *si = find_socket_info(s);
2134 return real_writev(s, vector, count);
2137 /* we write 1500 bytes as maximum */
2141 for (i=0; i < count; i++) {
2143 nlen = len + vector[i].iov_len;
2151 v.iov_len = MIN(v.iov_len, 1500);
2157 ret = real_writev(s, vector, count);
2159 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2165 /* we capture it as one single packet */
2166 buf = (uint8_t *)malloc(ret);
2168 /* we just not capture the packet */
2173 for (i=0; i < count; i++) {
2177 ofs += vector[i].iov_len;
2180 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2187 _PUBLIC_ int swrap_close(int fd)
2189 struct socket_info *si = find_socket_info(fd);
2193 return real_close(fd);
2196 SWRAP_DLIST_REMOVE(sockets, si);
2198 if (si->myname && si->peername) {
2199 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2202 ret = real_close(fd);
2204 if (si->myname && si->peername) {
2205 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2206 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2209 if (si->path) free(si->path);
2210 if (si->myname) free(si->myname);
2211 if (si->peername) free(si->peername);
2213 unlink(si->tmp_path);