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
);
225 struct sockaddr
*myname
;
226 socklen_t myname_len
;
228 struct sockaddr
*peername
;
229 socklen_t peername_len
;
232 unsigned long pck_snd
;
233 unsigned long pck_rcv
;
236 struct socket_info
*prev
, *next
;
239 static struct socket_info
*sockets
;
241 const char *socket_wrapper_dir(void)
243 const char *s
= getenv("SOCKET_WRAPPER_DIR");
247 if (strncmp(s
, "./", 2) == 0) {
253 unsigned int socket_wrapper_default_iface(void)
255 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
258 if (sscanf(s
, "%u", &iface
) == 1) {
259 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
265 return 1;/* 127.0.0.1 */
268 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
275 p
= strrchr(un
->sun_path
, '/');
276 if (p
) p
++; else p
= un
->sun_path
;
278 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
283 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
294 case SOCKET_TYPE_CHAR_TCP
:
295 case SOCKET_TYPE_CHAR_UDP
: {
296 struct sockaddr_in
*in2
= (struct sockaddr_in
*)in
;
298 if ((*len
) < sizeof(*in2
)) {
303 memset(in2
, 0, sizeof(*in2
));
304 in2
->sin_family
= AF_INET
;
305 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
306 in2
->sin_port
= htons(prt
);
312 case SOCKET_TYPE_CHAR_TCP_V6
:
313 case SOCKET_TYPE_CHAR_UDP_V6
: {
314 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)in
;
316 if ((*len
) < sizeof(*in2
)) {
321 memset(in2
, 0, sizeof(*in2
));
322 in2
->sin6_family
= AF_INET6
;
323 in2
->sin6_addr
= *swrap_ipv6();
324 in2
->sin6_addr
.s6_addr
[15] = iface
;
325 in2
->sin6_port
= htons(prt
);
339 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
347 if (bcast
) *bcast
= 0;
349 switch (si
->family
) {
351 const struct sockaddr_in
*in
=
352 (const struct sockaddr_in
*)inaddr
;
353 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
360 u_type
= SOCKET_TYPE_CHAR_TCP
;
363 u_type
= SOCKET_TYPE_CHAR_UDP
;
364 a_type
= SOCKET_TYPE_CHAR_UDP
;
365 b_type
= SOCKET_TYPE_CHAR_UDP
;
369 prt
= ntohs(in
->sin_port
);
370 if (a_type
&& addr
== 0xFFFFFFFF) {
371 /* 255.255.255.255 only udp */
374 iface
= socket_wrapper_default_iface();
375 } else if (b_type
&& addr
== 0x7FFFFFFF) {
376 /* 127.255.255.255 only udp */
379 iface
= socket_wrapper_default_iface();
380 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
384 iface
= (addr
& 0x000000FF);
389 if (bcast
) *bcast
= is_bcast
;
394 const struct sockaddr_in6
*in
=
395 (const struct sockaddr_in6
*)inaddr
;
400 type
= SOCKET_TYPE_CHAR_TCP_V6
;
403 type
= SOCKET_TYPE_CHAR_UDP_V6
;
407 /* XXX no multicast/broadcast */
409 prt
= ntohs(in
->sin6_port
);
413 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp
)) {
414 iface
= in
->sin6_addr
.s6_addr
[15];
434 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
435 socket_wrapper_dir());
436 /* the caller need to do more processing */
440 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
441 socket_wrapper_dir(), type
, iface
, prt
);
446 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
455 if (bcast
) *bcast
= 0;
457 switch (si
->family
) {
459 const struct sockaddr_in
*in
=
460 (const struct sockaddr_in
*)inaddr
;
461 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
467 prt
= ntohs(in
->sin_port
);
471 u_type
= SOCKET_TYPE_CHAR_TCP
;
472 d_type
= SOCKET_TYPE_CHAR_TCP
;
475 u_type
= SOCKET_TYPE_CHAR_UDP
;
476 d_type
= SOCKET_TYPE_CHAR_UDP
;
477 a_type
= SOCKET_TYPE_CHAR_UDP
;
478 b_type
= SOCKET_TYPE_CHAR_UDP
;
486 iface
= socket_wrapper_default_iface();
487 } else if (a_type
&& addr
== 0xFFFFFFFF) {
488 /* 255.255.255.255 only udp */
491 iface
= socket_wrapper_default_iface();
492 } else if (b_type
&& addr
== 0x7FFFFFFF) {
493 /* 127.255.255.255 only udp */
496 iface
= socket_wrapper_default_iface();
497 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
501 iface
= (addr
& 0x000000FF);
503 errno
= EADDRNOTAVAIL
;
510 const struct sockaddr_in6
*in
=
511 (const struct sockaddr_in6
*)inaddr
;
516 type
= SOCKET_TYPE_CHAR_TCP_V6
;
519 type
= SOCKET_TYPE_CHAR_UDP_V6
;
523 /* XXX no multicast/broadcast */
525 prt
= ntohs(in
->sin6_port
);
529 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
530 iface
= socket_wrapper_default_iface();
531 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp
)) {
532 iface
= in
->sin6_addr
.s6_addr
[15];
534 errno
= EADDRNOTAVAIL
;
542 errno
= EADDRNOTAVAIL
;
547 if (bcast
) *bcast
= is_bcast
;
550 /* handle auto-allocation of ephemeral ports */
551 for (prt
= 5001; prt
< 10000; prt
++) {
552 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
553 socket_wrapper_dir(), type
, iface
, prt
);
554 if (stat(un
->sun_path
, &st
) == 0) continue;
556 set_port(si
->family
, prt
, si
->myname
);
565 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
566 socket_wrapper_dir(), type
, iface
, prt
);
570 static struct socket_info
*find_socket_info(int fd
)
572 struct socket_info
*i
;
573 for (i
= sockets
; i
; i
= i
->next
) {
581 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
582 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
587 out_addr
->sun_family
= AF_UNIX
;
589 switch (in_addr
->sa_family
) {
599 errno
= ESOCKTNOSUPPORT
;
603 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
605 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
611 errno
= EAFNOSUPPORT
;
615 static int sockaddr_convert_from_un(const struct socket_info
*si
,
616 const struct sockaddr_un
*in_addr
,
617 socklen_t un_addrlen
,
619 struct sockaddr
*out_addr
,
620 socklen_t
*out_addrlen
)
622 if (out_addr
== NULL
|| out_addrlen
== NULL
)
625 if (un_addrlen
== 0) {
640 errno
= ESOCKTNOSUPPORT
;
643 return convert_un_in(in_addr
, out_addr
, out_addrlen
);
648 errno
= EAFNOSUPPORT
;
652 enum swrap_packet_type
{
654 SWRAP_CONNECT_UNREACH
,
662 SWRAP_SENDTO_UNREACH
,
673 struct swrap_file_hdr
{
675 uint16_t version_major
;
676 uint16_t version_minor
;
679 uint32_t frame_max_len
;
680 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
683 #define SWRAP_FILE_HDR_SIZE 24
685 struct swrap_packet_frame
{
687 uint32_t micro_seconds
;
688 uint32_t recorded_length
;
689 uint32_t full_length
;
691 #define SWRAP_PACKET_FRAME_SIZE 16
693 union swrap_packet_ip
{
697 uint16_t packet_length
;
698 uint16_t identification
;
703 uint16_t hdr_checksum
;
707 #define SWRAP_PACKET_IP_V4_SIZE 20
710 uint8_t flow_label_high
;
711 uint16_t flow_label_low
;
712 uint16_t payload_length
;
715 uint8_t src_addr
[16];
716 uint8_t dest_addr
[16];
718 #define SWRAP_PACKET_IP_V6_SIZE 40
720 #define SWRAP_PACKET_IP_SIZE 40
722 union swrap_packet_payload
{
724 uint16_t source_port
;
734 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
736 uint16_t source_port
;
741 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
748 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
755 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
757 #define SWRAP_PACKET_PAYLOAD_SIZE 20
759 #define SWRAP_PACKET_MIN_ALLOC \
760 (SWRAP_PACKET_FRAME_SIZE + \
761 SWRAP_PACKET_IP_SIZE + \
762 SWRAP_PACKET_PAYLOAD_SIZE)
764 static const char *socket_wrapper_pcap_file(void)
766 static int initialized
= 0;
767 static const char *s
= NULL
;
768 static const struct swrap_file_hdr h
;
769 static const struct swrap_packet_frame f
;
770 static const union swrap_packet_ip i
;
771 static const union swrap_packet_payload p
;
773 if (initialized
== 1) {
779 * TODO: don't use the structs use plain buffer offsets
780 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
782 * for now make sure we disable PCAP support
783 * if the struct has alignment!
785 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
788 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
791 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
794 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
797 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
800 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
803 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
806 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
809 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
812 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
816 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
820 if (strncmp(s
, "./", 2) == 0) {
826 static uint8_t *swrap_packet_init(struct timeval
*tval
,
827 const struct sockaddr
*src
,
828 const struct sockaddr
*dest
,
830 const uint8_t *payload
,
832 unsigned long tcp_seqno
,
833 unsigned long tcp_ack
,
834 unsigned char tcp_ctl
,
840 struct swrap_packet_frame
*frame
;
841 union swrap_packet_ip
*ip
;
842 union swrap_packet_payload
*pay
;
845 size_t nonwire_len
= sizeof(*frame
);
846 size_t wire_hdr_len
= 0;
848 size_t ip_hdr_len
= 0;
849 size_t icmp_hdr_len
= 0;
850 size_t icmp_truncate_len
= 0;
851 uint8_t protocol
= 0, icmp_protocol
= 0;
852 const struct sockaddr_in
*src_in
= NULL
;
853 const struct sockaddr_in
*dest_in
= NULL
;
855 const struct sockaddr_in6
*src_in6
= NULL
;
856 const struct sockaddr_in6
*dest_in6
= NULL
;
861 switch (src
->sa_family
) {
863 src_in
= (const struct sockaddr_in
*)src
;
864 dest_in
= (const struct sockaddr_in
*)dest
;
865 src_port
= src_in
->sin_port
;
866 dest_port
= dest_in
->sin_port
;
867 ip_hdr_len
= sizeof(ip
->v4
);
871 src_in6
= (const struct sockaddr_in6
*)src
;
872 dest_in6
= (const struct sockaddr_in6
*)dest
;
873 src_port
= src_in6
->sin6_port
;
874 dest_port
= dest_in6
->sin6_port
;
875 ip_hdr_len
= sizeof(ip
->v6
);
882 switch (socket_type
) {
884 protocol
= 0x06; /* TCP */
885 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
886 wire_len
= wire_hdr_len
+ payload_len
;
890 protocol
= 0x11; /* UDP */
891 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
892 wire_len
= wire_hdr_len
+ payload_len
;
900 icmp_protocol
= protocol
;
901 switch (src
->sa_family
) {
903 protocol
= 0x01; /* ICMPv4 */
904 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
908 protocol
= 0x3A; /* ICMPv6 */
909 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
913 if (wire_len
> 64 ) {
914 icmp_truncate_len
= wire_len
- 64;
916 wire_hdr_len
+= icmp_hdr_len
;
917 wire_len
+= icmp_hdr_len
;
920 packet_len
= nonwire_len
+ wire_len
;
921 alloc_len
= packet_len
;
922 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
923 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
926 base
= (uint8_t *)malloc(alloc_len
);
927 if (!base
) return NULL
;
931 frame
= (struct swrap_packet_frame
*)buf
;
932 frame
->seconds
= tval
->tv_sec
;
933 frame
->micro_seconds
= tval
->tv_usec
;
934 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
935 frame
->full_length
= wire_len
- icmp_truncate_len
;
936 buf
+= SWRAP_PACKET_FRAME_SIZE
;
938 ip
= (union swrap_packet_ip
*)buf
;
939 switch (src
->sa_family
) {
941 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
943 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
944 ip
->v4
.identification
= htons(0xFFFF);
945 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
946 ip
->v4
.fragment
= htons(0x0000);
948 ip
->v4
.protocol
= protocol
;
949 ip
->v4
.hdr_checksum
= htons(0x0000);
950 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
951 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
952 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
956 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
957 ip
->v6
.flow_label_high
= 0x00;
958 ip
->v6
.flow_label_low
= 0x0000;
959 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
);//TODO
960 ip
->v6
.next_header
= protocol
;
961 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
962 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
963 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
969 pay
= (union swrap_packet_payload
*)buf
;
970 switch (src
->sa_family
) {
972 pay
->icmp4
.type
= 0x03; /* destination unreachable */
973 pay
->icmp4
.code
= 0x01; /* host unreachable */
974 pay
->icmp4
.checksum
= htons(0x0000);
975 pay
->icmp4
.unused
= htonl(0x00000000);
976 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
978 /* set the ip header in the ICMP payload */
979 ip
= (union swrap_packet_ip
*)buf
;
980 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
982 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
983 ip
->v4
.identification
= htons(0xFFFF);
984 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
985 ip
->v4
.fragment
= htons(0x0000);
987 ip
->v4
.protocol
= icmp_protocol
;
988 ip
->v4
.hdr_checksum
= htons(0x0000);
989 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
990 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
991 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
993 src_port
= dest_in
->sin_port
;
994 dest_port
= src_in
->sin_port
;
998 pay
->icmp6
.type
= 0x01; /* destination unreachable */
999 pay
->icmp6
.code
= 0x03; /* address unreachable */
1000 pay
->icmp6
.checksum
= htons(0x0000);
1001 pay
->icmp6
.unused
= htonl(0x00000000);
1002 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1004 /* set the ip header in the ICMP payload */
1005 ip
= (union swrap_packet_ip
*)buf
;
1006 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1007 ip
->v6
.flow_label_high
= 0x00;
1008 ip
->v6
.flow_label_low
= 0x0000;
1009 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
);//TODO
1010 ip
->v6
.next_header
= protocol
;
1011 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1012 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1013 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1015 src_port
= dest_in6
->sin6_port
;
1016 dest_port
= src_in6
->sin6_port
;
1022 pay
= (union swrap_packet_payload
*)buf
;
1024 switch (socket_type
) {
1026 pay
->tcp
.source_port
= src_port
;
1027 pay
->tcp
.dest_port
= dest_port
;
1028 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1029 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1030 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1031 pay
->tcp
.control
= tcp_ctl
;
1032 pay
->tcp
.window
= htons(0x7FFF);
1033 pay
->tcp
.checksum
= htons(0x0000);
1034 pay
->tcp
.urg
= htons(0x0000);
1035 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1040 pay
->udp
.source_port
= src_port
;
1041 pay
->udp
.dest_port
= dest_port
;
1042 pay
->udp
.length
= htons(8 + payload_len
);
1043 pay
->udp
.checksum
= htons(0x0000);
1044 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1049 if (payload
&& payload_len
> 0) {
1050 memcpy(buf
, payload
, payload_len
);
1053 *_packet_len
= packet_len
- icmp_truncate_len
;
1057 static int swrap_get_pcap_fd(const char *fname
)
1061 if (fd
!= -1) return fd
;
1063 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1065 struct swrap_file_hdr file_hdr
;
1066 file_hdr
.magic
= 0xA1B2C3D4;
1067 file_hdr
.version_major
= 0x0002;
1068 file_hdr
.version_minor
= 0x0004;
1069 file_hdr
.timezone
= 0x00000000;
1070 file_hdr
.sigfigs
= 0x00000000;
1071 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1072 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1074 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1081 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1086 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1087 const struct sockaddr
*addr
,
1088 enum swrap_packet_type type
,
1089 const void *buf
, size_t len
,
1092 const struct sockaddr
*src_addr
;
1093 const struct sockaddr
*dest_addr
;
1094 unsigned long tcp_seqno
= 0;
1095 unsigned long tcp_ack
= 0;
1096 unsigned char tcp_ctl
= 0;
1097 int unreachable
= 0;
1101 switch (si
->family
) {
1111 case SWRAP_CONNECT_SEND
:
1112 if (si
->type
!= SOCK_STREAM
) return NULL
;
1114 src_addr
= si
->myname
;
1117 tcp_seqno
= si
->io
.pck_snd
;
1118 tcp_ack
= si
->io
.pck_rcv
;
1119 tcp_ctl
= 0x02; /* SYN */
1121 si
->io
.pck_snd
+= 1;
1125 case SWRAP_CONNECT_RECV
:
1126 if (si
->type
!= SOCK_STREAM
) return NULL
;
1128 dest_addr
= si
->myname
;
1131 tcp_seqno
= si
->io
.pck_rcv
;
1132 tcp_ack
= si
->io
.pck_snd
;
1133 tcp_ctl
= 0x12; /** SYN,ACK */
1135 si
->io
.pck_rcv
+= 1;
1139 case SWRAP_CONNECT_UNREACH
:
1140 if (si
->type
!= SOCK_STREAM
) return NULL
;
1142 dest_addr
= si
->myname
;
1145 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1146 tcp_seqno
= si
->io
.pck_snd
- 1;
1147 tcp_ack
= si
->io
.pck_rcv
;
1148 tcp_ctl
= 0x02; /* SYN */
1153 case SWRAP_CONNECT_ACK
:
1154 if (si
->type
!= SOCK_STREAM
) return NULL
;
1156 src_addr
= si
->myname
;
1159 tcp_seqno
= si
->io
.pck_snd
;
1160 tcp_ack
= si
->io
.pck_rcv
;
1161 tcp_ctl
= 0x10; /* ACK */
1165 case SWRAP_ACCEPT_SEND
:
1166 if (si
->type
!= SOCK_STREAM
) return NULL
;
1168 dest_addr
= si
->myname
;
1171 tcp_seqno
= si
->io
.pck_rcv
;
1172 tcp_ack
= si
->io
.pck_snd
;
1173 tcp_ctl
= 0x02; /* SYN */
1175 si
->io
.pck_rcv
+= 1;
1179 case SWRAP_ACCEPT_RECV
:
1180 if (si
->type
!= SOCK_STREAM
) return NULL
;
1182 src_addr
= si
->myname
;
1185 tcp_seqno
= si
->io
.pck_snd
;
1186 tcp_ack
= si
->io
.pck_rcv
;
1187 tcp_ctl
= 0x12; /* SYN,ACK */
1189 si
->io
.pck_snd
+= 1;
1193 case SWRAP_ACCEPT_ACK
:
1194 if (si
->type
!= SOCK_STREAM
) return NULL
;
1196 dest_addr
= si
->myname
;
1199 tcp_seqno
= si
->io
.pck_rcv
;
1200 tcp_ack
= si
->io
.pck_snd
;
1201 tcp_ctl
= 0x10; /* ACK */
1206 src_addr
= si
->myname
;
1207 dest_addr
= si
->peername
;
1209 tcp_seqno
= si
->io
.pck_snd
;
1210 tcp_ack
= si
->io
.pck_rcv
;
1211 tcp_ctl
= 0x18; /* PSH,ACK */
1213 si
->io
.pck_snd
+= len
;
1217 case SWRAP_SEND_RST
:
1218 dest_addr
= si
->myname
;
1219 src_addr
= si
->peername
;
1221 if (si
->type
== SOCK_DGRAM
) {
1222 return swrap_marshall_packet(si
, si
->peername
,
1223 SWRAP_SENDTO_UNREACH
,
1224 buf
, len
, packet_len
);
1227 tcp_seqno
= si
->io
.pck_rcv
;
1228 tcp_ack
= si
->io
.pck_snd
;
1229 tcp_ctl
= 0x14; /** RST,ACK */
1233 case SWRAP_PENDING_RST
:
1234 dest_addr
= si
->myname
;
1235 src_addr
= si
->peername
;
1237 if (si
->type
== SOCK_DGRAM
) {
1241 tcp_seqno
= si
->io
.pck_rcv
;
1242 tcp_ack
= si
->io
.pck_snd
;
1243 tcp_ctl
= 0x14; /* RST,ACK */
1248 dest_addr
= si
->myname
;
1249 src_addr
= si
->peername
;
1251 tcp_seqno
= si
->io
.pck_rcv
;
1252 tcp_ack
= si
->io
.pck_snd
;
1253 tcp_ctl
= 0x18; /* PSH,ACK */
1255 si
->io
.pck_rcv
+= len
;
1259 case SWRAP_RECV_RST
:
1260 dest_addr
= si
->myname
;
1261 src_addr
= si
->peername
;
1263 if (si
->type
== SOCK_DGRAM
) {
1267 tcp_seqno
= si
->io
.pck_rcv
;
1268 tcp_ack
= si
->io
.pck_snd
;
1269 tcp_ctl
= 0x14; /* RST,ACK */
1274 src_addr
= si
->myname
;
1277 si
->io
.pck_snd
+= len
;
1281 case SWRAP_SENDTO_UNREACH
:
1282 dest_addr
= si
->myname
;
1289 case SWRAP_RECVFROM
:
1290 dest_addr
= si
->myname
;
1293 si
->io
.pck_rcv
+= len
;
1297 case SWRAP_CLOSE_SEND
:
1298 if (si
->type
!= SOCK_STREAM
) return NULL
;
1300 src_addr
= si
->myname
;
1301 dest_addr
= si
->peername
;
1303 tcp_seqno
= si
->io
.pck_snd
;
1304 tcp_ack
= si
->io
.pck_rcv
;
1305 tcp_ctl
= 0x11; /* FIN, ACK */
1307 si
->io
.pck_snd
+= 1;
1311 case SWRAP_CLOSE_RECV
:
1312 if (si
->type
!= SOCK_STREAM
) return NULL
;
1314 dest_addr
= si
->myname
;
1315 src_addr
= si
->peername
;
1317 tcp_seqno
= si
->io
.pck_rcv
;
1318 tcp_ack
= si
->io
.pck_snd
;
1319 tcp_ctl
= 0x11; /* FIN,ACK */
1321 si
->io
.pck_rcv
+= 1;
1325 case SWRAP_CLOSE_ACK
:
1326 if (si
->type
!= SOCK_STREAM
) return NULL
;
1328 src_addr
= si
->myname
;
1329 dest_addr
= si
->peername
;
1331 tcp_seqno
= si
->io
.pck_snd
;
1332 tcp_ack
= si
->io
.pck_rcv
;
1333 tcp_ctl
= 0x10; /* ACK */
1340 swrapGetTimeOfDay(&tv
);
1342 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1343 (const uint8_t *)buf
, len
,
1344 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1348 static void swrap_dump_packet(struct socket_info
*si
,
1349 const struct sockaddr
*addr
,
1350 enum swrap_packet_type type
,
1351 const void *buf
, size_t len
)
1353 const char *file_name
;
1355 size_t packet_len
= 0;
1358 file_name
= socket_wrapper_pcap_file();
1363 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1368 fd
= swrap_get_pcap_fd(file_name
);
1370 if (write(fd
, packet
, packet_len
) != packet_len
) {
1379 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1381 struct socket_info
*si
;
1384 if (!socket_wrapper_dir()) {
1385 return real_socket(family
, type
, protocol
);
1395 return real_socket(family
, type
, protocol
);
1397 errno
= EAFNOSUPPORT
;
1407 errno
= EPROTONOSUPPORT
;
1415 if (type
== SOCK_STREAM
) {
1420 if (type
== SOCK_DGRAM
) {
1425 errno
= EPROTONOSUPPORT
;
1429 fd
= real_socket(AF_UNIX
, type
, 0);
1431 if (fd
== -1) return -1;
1433 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1435 si
->family
= family
;
1437 si
->protocol
= protocol
;
1440 SWRAP_DLIST_ADD(sockets
, si
);
1445 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1447 struct socket_info
*parent_si
, *child_si
;
1449 struct sockaddr_un un_addr
;
1450 socklen_t un_addrlen
= sizeof(un_addr
);
1451 struct sockaddr_un un_my_addr
;
1452 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1453 struct sockaddr
*my_addr
;
1454 socklen_t my_addrlen
, len
;
1457 parent_si
= find_socket_info(s
);
1459 return real_accept(s
, addr
, addrlen
);
1463 * assume out sockaddr have the same size as the in parent
1466 my_addrlen
= socket_length(parent_si
->family
);
1467 if (my_addrlen
<= 0) {
1472 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1473 if (my_addr
== NULL
) {
1477 memset(&un_addr
, 0, sizeof(un_addr
));
1478 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1480 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1489 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1490 parent_si
->family
, my_addr
, &len
);
1497 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1498 memset(child_si
, 0, sizeof(*child_si
));
1501 child_si
->family
= parent_si
->family
;
1502 child_si
->type
= parent_si
->type
;
1503 child_si
->protocol
= parent_si
->protocol
;
1504 child_si
->bound
= 1;
1505 child_si
->is_server
= 1;
1506 child_si
->connected
= 1;
1508 child_si
->peername_len
= len
;
1509 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1511 if (addr
!= NULL
&& addrlen
!= NULL
) {
1513 if (*addrlen
>= len
)
1514 memcpy(addr
, my_addr
, len
);
1518 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1526 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1527 child_si
->family
, my_addr
, &len
);
1535 child_si
->myname_len
= len
;
1536 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1539 SWRAP_DLIST_ADD(sockets
, child_si
);
1541 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1542 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1543 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1548 static int autobind_start_init
;
1549 static int autobind_start
;
1551 /* using sendto() or connect() on an unbound socket would give the
1552 recipient no way to reply, as unlike UDP and TCP, a unix domain
1553 socket can't auto-assign emphemeral port numbers, so we need to
1555 Note: this might change the family from ipv6 to ipv4
1557 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1559 struct sockaddr_un un_addr
;
1566 if (autobind_start_init
!= 1) {
1567 autobind_start_init
= 1;
1568 autobind_start
= getpid();
1569 autobind_start
%= 50000;
1570 autobind_start
+= 10000;
1573 un_addr
.sun_family
= AF_UNIX
;
1577 struct sockaddr_in in
;
1581 type
= SOCKET_TYPE_CHAR_TCP
;
1584 type
= SOCKET_TYPE_CHAR_UDP
;
1587 errno
= ESOCKTNOSUPPORT
;
1591 memset(&in
, 0, sizeof(in
));
1592 in
.sin_family
= AF_INET
;
1593 in
.sin_addr
.s_addr
= htonl(127<<24 |
1594 socket_wrapper_default_iface());
1596 si
->myname_len
= sizeof(in
);
1597 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1602 struct sockaddr_in6 in6
;
1604 if (si
->family
!= family
) {
1605 errno
= ENETUNREACH
;
1611 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1614 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1617 errno
= ESOCKTNOSUPPORT
;
1621 memset(&in6
, 0, sizeof(in6
));
1622 in6
.sin6_family
= AF_INET6
;
1623 in6
.sin6_addr
= *swrap_ipv6();
1624 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1625 si
->myname_len
= sizeof(in6
);
1626 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1631 errno
= ESOCKTNOSUPPORT
;
1635 if (autobind_start
> 60000) {
1636 autobind_start
= 10000;
1639 for (i
=0;i
<1000;i
++) {
1640 port
= autobind_start
+ i
;
1641 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1642 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1643 type
, socket_wrapper_default_iface(), port
);
1644 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1646 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1647 if (ret
== -1) return ret
;
1649 si
->tmp_path
= strdup(un_addr
.sun_path
);
1651 autobind_start
= port
+ 1;
1659 si
->family
= family
;
1660 set_port(si
->family
, port
, si
->myname
);
1666 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1669 struct sockaddr_un un_addr
;
1670 struct socket_info
*si
= find_socket_info(s
);
1673 return real_connect(s
, serv_addr
, addrlen
);
1676 if (si
->bound
== 0) {
1677 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1678 if (ret
== -1) return -1;
1681 if (si
->family
!= serv_addr
->sa_family
) {
1686 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1687 if (ret
== -1) return -1;
1689 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1691 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1692 sizeof(struct sockaddr_un
));
1694 /* to give better errors */
1695 if (ret
== -1 && errno
== ENOENT
) {
1696 errno
= EHOSTUNREACH
;
1700 si
->peername_len
= addrlen
;
1701 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1704 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1705 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1707 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1713 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1716 struct sockaddr_un un_addr
;
1717 struct socket_info
*si
= find_socket_info(s
);
1720 return real_bind(s
, myaddr
, addrlen
);
1723 si
->myname_len
= addrlen
;
1724 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1726 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1727 if (ret
== -1) return -1;
1729 unlink(un_addr
.sun_path
);
1731 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1732 sizeof(struct sockaddr_un
));
1741 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1744 struct socket_info
*si
= find_socket_info(s
);
1747 return real_listen(s
, backlog
);
1750 ret
= real_listen(s
, backlog
);
1755 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1757 struct socket_info
*si
= find_socket_info(s
);
1760 return real_getpeername(s
, name
, addrlen
);
1769 memcpy(name
, si
->peername
, si
->peername_len
);
1770 *addrlen
= si
->peername_len
;
1775 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1777 struct socket_info
*si
= find_socket_info(s
);
1780 return real_getsockname(s
, name
, addrlen
);
1783 memcpy(name
, si
->myname
, si
->myname_len
);
1784 *addrlen
= si
->myname_len
;
1789 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1791 struct socket_info
*si
= find_socket_info(s
);
1794 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1797 if (level
== SOL_SOCKET
) {
1798 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1801 errno
= ENOPROTOOPT
;
1805 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1807 struct socket_info
*si
= find_socket_info(s
);
1810 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1813 if (level
== SOL_SOCKET
) {
1814 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1817 switch (si
->family
) {
1821 errno
= ENOPROTOOPT
;
1826 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1828 struct sockaddr_un un_addr
;
1829 socklen_t un_addrlen
= sizeof(un_addr
);
1831 struct socket_info
*si
= find_socket_info(s
);
1832 struct sockaddr_storage ss
;
1833 socklen_t ss_len
= sizeof(ss
);
1836 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1840 from
= (struct sockaddr
*)&ss
;
1844 len
= MIN(len
, 1500);
1846 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1847 memset(&un_addr
, 0, sizeof(un_addr
));
1848 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1852 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1853 si
->family
, from
, fromlen
) == -1) {
1857 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1863 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1865 struct sockaddr_un un_addr
;
1867 struct socket_info
*si
= find_socket_info(s
);
1871 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1874 if (si
->connected
) {
1881 tolen
= si
->peername_len
;
1884 len
= MIN(len
, 1500);
1888 ret
= real_send(s
, buf
, len
, flags
);
1891 if (si
->bound
== 0) {
1892 ret
= swrap_auto_bind(si
, si
->family
);
1893 if (ret
== -1) return -1;
1896 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1897 if (ret
== -1) return -1;
1902 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1905 type
= SOCKET_TYPE_CHAR_UDP
;
1907 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1908 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1909 socket_wrapper_dir(), type
, iface
, prt
);
1910 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1912 /* ignore the any errors in broadcast sends */
1913 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1916 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1921 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1925 errno
= EHOSTUNREACH
;
1929 /* to give better errors */
1930 if (ret
== -1 && errno
== ENOENT
) {
1931 errno
= EHOSTUNREACH
;
1935 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1936 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1938 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1944 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1947 struct socket_info
*si
= find_socket_info(s
);
1951 return real_ioctl(s
, r
, p
);
1954 ret
= real_ioctl(s
, r
, p
);
1958 value
= *((int *)p
);
1959 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1960 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1961 } else if (value
== 0) { /* END OF FILE */
1962 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1970 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1973 struct socket_info
*si
= find_socket_info(s
);
1976 return real_recv(s
, buf
, len
, flags
);
1979 len
= MIN(len
, 1500);
1981 ret
= real_recv(s
, buf
, len
, flags
);
1982 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1983 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1984 } else if (ret
== 0) { /* END OF FILE */
1985 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1986 } else if (ret
> 0) {
1987 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1994 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1997 struct socket_info
*si
= find_socket_info(s
);
2000 return real_send(s
, buf
, len
, flags
);
2003 len
= MIN(len
, 1500);
2005 ret
= real_send(s
, buf
, len
, flags
);
2008 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2009 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2011 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2017 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2020 struct socket_info
*si
= find_socket_info(s
);
2024 return real_readv(s
, vector
, count
);
2027 /* we read 1500 bytes as maximum */
2031 for (i
=0; i
< count
; i
++) {
2033 nlen
= len
+ vector
[i
].iov_len
;
2041 v
.iov_len
= MIN(v
.iov_len
, 1500);
2047 ret
= real_readv(s
, vector
, count
);
2048 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2049 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2050 } else if (ret
== 0) { /* END OF FILE */
2051 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2052 } else if (ret
> 0) {
2056 size_t remain
= ret
;
2058 /* we capture it as one single packet */
2059 buf
= (uint8_t *)malloc(ret
);
2061 /* we just not capture the packet */
2066 for (i
=0; i
< count
; i
++) {
2067 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2072 remain
-= this_time
;
2075 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2082 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2085 struct socket_info
*si
= find_socket_info(s
);
2089 return real_writev(s
, vector
, count
);
2092 /* we write 1500 bytes as maximum */
2096 for (i
=0; i
< count
; i
++) {
2098 nlen
= len
+ vector
[i
].iov_len
;
2106 v
.iov_len
= MIN(v
.iov_len
, 1500);
2112 ret
= real_writev(s
, vector
, count
);
2114 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2119 size_t remain
= ret
;
2121 /* we capture it as one single packet */
2122 buf
= (uint8_t *)malloc(ret
);
2124 /* we just not capture the packet */
2129 for (i
=0; i
< count
; i
++) {
2130 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2135 remain
-= this_time
;
2138 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2145 _PUBLIC_
int swrap_close(int fd
)
2147 struct socket_info
*si
= find_socket_info(fd
);
2151 return real_close(fd
);
2154 SWRAP_DLIST_REMOVE(sockets
, si
);
2156 if (si
->myname
&& si
->peername
) {
2157 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2160 ret
= real_close(fd
);
2162 if (si
->myname
&& si
->peername
) {
2163 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2164 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2167 if (si
->path
) free(si
->path
);
2168 if (si
->myname
) free(si
->myname
);
2169 if (si
->peername
) free(si
->peername
);
2171 unlink(si
->tmp_path
);