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
) {
1113 case SWRAP_CONNECT_SEND
:
1114 if (si
->type
!= SOCK_STREAM
) return NULL
;
1116 src_addr
= si
->myname
;
1119 tcp_seqno
= si
->io
.pck_snd
;
1120 tcp_ack
= si
->io
.pck_rcv
;
1121 tcp_ctl
= 0x02; /* SYN */
1123 si
->io
.pck_snd
+= 1;
1127 case SWRAP_CONNECT_RECV
:
1128 if (si
->type
!= SOCK_STREAM
) return NULL
;
1130 dest_addr
= si
->myname
;
1133 tcp_seqno
= si
->io
.pck_rcv
;
1134 tcp_ack
= si
->io
.pck_snd
;
1135 tcp_ctl
= 0x12; /** SYN,ACK */
1137 si
->io
.pck_rcv
+= 1;
1141 case SWRAP_CONNECT_UNREACH
:
1142 if (si
->type
!= SOCK_STREAM
) return NULL
;
1144 dest_addr
= si
->myname
;
1147 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1148 tcp_seqno
= si
->io
.pck_snd
- 1;
1149 tcp_ack
= si
->io
.pck_rcv
;
1150 tcp_ctl
= 0x02; /* SYN */
1155 case SWRAP_CONNECT_ACK
:
1156 if (si
->type
!= SOCK_STREAM
) return NULL
;
1158 src_addr
= si
->myname
;
1161 tcp_seqno
= si
->io
.pck_snd
;
1162 tcp_ack
= si
->io
.pck_rcv
;
1163 tcp_ctl
= 0x10; /* ACK */
1167 case SWRAP_ACCEPT_SEND
:
1168 if (si
->type
!= SOCK_STREAM
) return NULL
;
1170 dest_addr
= si
->myname
;
1173 tcp_seqno
= si
->io
.pck_rcv
;
1174 tcp_ack
= si
->io
.pck_snd
;
1175 tcp_ctl
= 0x02; /* SYN */
1177 si
->io
.pck_rcv
+= 1;
1181 case SWRAP_ACCEPT_RECV
:
1182 if (si
->type
!= SOCK_STREAM
) return NULL
;
1184 src_addr
= si
->myname
;
1187 tcp_seqno
= si
->io
.pck_snd
;
1188 tcp_ack
= si
->io
.pck_rcv
;
1189 tcp_ctl
= 0x12; /* SYN,ACK */
1191 si
->io
.pck_snd
+= 1;
1195 case SWRAP_ACCEPT_ACK
:
1196 if (si
->type
!= SOCK_STREAM
) return NULL
;
1198 dest_addr
= si
->myname
;
1201 tcp_seqno
= si
->io
.pck_rcv
;
1202 tcp_ack
= si
->io
.pck_snd
;
1203 tcp_ctl
= 0x10; /* ACK */
1208 src_addr
= si
->myname
;
1209 dest_addr
= si
->peername
;
1211 tcp_seqno
= si
->io
.pck_snd
;
1212 tcp_ack
= si
->io
.pck_rcv
;
1213 tcp_ctl
= 0x18; /* PSH,ACK */
1215 si
->io
.pck_snd
+= len
;
1219 case SWRAP_SEND_RST
:
1220 dest_addr
= si
->myname
;
1221 src_addr
= si
->peername
;
1223 if (si
->type
== SOCK_DGRAM
) {
1224 return swrap_marshall_packet(si
, si
->peername
,
1225 SWRAP_SENDTO_UNREACH
,
1226 buf
, len
, packet_len
);
1229 tcp_seqno
= si
->io
.pck_rcv
;
1230 tcp_ack
= si
->io
.pck_snd
;
1231 tcp_ctl
= 0x14; /** RST,ACK */
1235 case SWRAP_PENDING_RST
:
1236 dest_addr
= si
->myname
;
1237 src_addr
= si
->peername
;
1239 if (si
->type
== SOCK_DGRAM
) {
1243 tcp_seqno
= si
->io
.pck_rcv
;
1244 tcp_ack
= si
->io
.pck_snd
;
1245 tcp_ctl
= 0x14; /* RST,ACK */
1250 dest_addr
= si
->myname
;
1251 src_addr
= si
->peername
;
1253 tcp_seqno
= si
->io
.pck_rcv
;
1254 tcp_ack
= si
->io
.pck_snd
;
1255 tcp_ctl
= 0x18; /* PSH,ACK */
1257 si
->io
.pck_rcv
+= len
;
1261 case SWRAP_RECV_RST
:
1262 dest_addr
= si
->myname
;
1263 src_addr
= si
->peername
;
1265 if (si
->type
== SOCK_DGRAM
) {
1269 tcp_seqno
= si
->io
.pck_rcv
;
1270 tcp_ack
= si
->io
.pck_snd
;
1271 tcp_ctl
= 0x14; /* RST,ACK */
1276 src_addr
= si
->myname
;
1279 si
->io
.pck_snd
+= len
;
1283 case SWRAP_SENDTO_UNREACH
:
1284 dest_addr
= si
->myname
;
1291 case SWRAP_RECVFROM
:
1292 dest_addr
= si
->myname
;
1295 si
->io
.pck_rcv
+= len
;
1299 case SWRAP_CLOSE_SEND
:
1300 if (si
->type
!= SOCK_STREAM
) return NULL
;
1302 src_addr
= si
->myname
;
1303 dest_addr
= si
->peername
;
1305 tcp_seqno
= si
->io
.pck_snd
;
1306 tcp_ack
= si
->io
.pck_rcv
;
1307 tcp_ctl
= 0x11; /* FIN, ACK */
1309 si
->io
.pck_snd
+= 1;
1313 case SWRAP_CLOSE_RECV
:
1314 if (si
->type
!= SOCK_STREAM
) return NULL
;
1316 dest_addr
= si
->myname
;
1317 src_addr
= si
->peername
;
1319 tcp_seqno
= si
->io
.pck_rcv
;
1320 tcp_ack
= si
->io
.pck_snd
;
1321 tcp_ctl
= 0x11; /* FIN,ACK */
1323 si
->io
.pck_rcv
+= 1;
1327 case SWRAP_CLOSE_ACK
:
1328 if (si
->type
!= SOCK_STREAM
) return NULL
;
1330 src_addr
= si
->myname
;
1331 dest_addr
= si
->peername
;
1333 tcp_seqno
= si
->io
.pck_snd
;
1334 tcp_ack
= si
->io
.pck_rcv
;
1335 tcp_ctl
= 0x10; /* ACK */
1342 swrapGetTimeOfDay(&tv
);
1344 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1345 (const uint8_t *)buf
, len
,
1346 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1350 static void swrap_dump_packet(struct socket_info
*si
,
1351 const struct sockaddr
*addr
,
1352 enum swrap_packet_type type
,
1353 const void *buf
, size_t len
)
1355 const char *file_name
;
1357 size_t packet_len
= 0;
1360 file_name
= socket_wrapper_pcap_file();
1365 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1370 fd
= swrap_get_pcap_fd(file_name
);
1372 if (write(fd
, packet
, packet_len
) != packet_len
) {
1381 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1383 struct socket_info
*si
;
1386 if (!socket_wrapper_dir()) {
1387 return real_socket(family
, type
, protocol
);
1397 return real_socket(family
, type
, protocol
);
1399 errno
= EAFNOSUPPORT
;
1409 errno
= EPROTONOSUPPORT
;
1417 if (type
== SOCK_STREAM
) {
1422 if (type
== SOCK_DGRAM
) {
1427 errno
= EPROTONOSUPPORT
;
1431 fd
= real_socket(AF_UNIX
, type
, 0);
1433 if (fd
== -1) return -1;
1435 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1437 si
->family
= family
;
1439 si
->protocol
= protocol
;
1442 SWRAP_DLIST_ADD(sockets
, si
);
1447 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1449 struct socket_info
*parent_si
, *child_si
;
1451 struct sockaddr_un un_addr
;
1452 socklen_t un_addrlen
= sizeof(un_addr
);
1453 struct sockaddr_un un_my_addr
;
1454 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1455 struct sockaddr
*my_addr
;
1456 socklen_t my_addrlen
, len
;
1459 parent_si
= find_socket_info(s
);
1461 return real_accept(s
, addr
, addrlen
);
1465 * assume out sockaddr have the same size as the in parent
1468 my_addrlen
= socket_length(parent_si
->family
);
1469 if (my_addrlen
<= 0) {
1474 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1475 if (my_addr
== NULL
) {
1479 memset(&un_addr
, 0, sizeof(un_addr
));
1480 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1482 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1491 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1492 parent_si
->family
, my_addr
, &len
);
1499 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1500 memset(child_si
, 0, sizeof(*child_si
));
1503 child_si
->family
= parent_si
->family
;
1504 child_si
->type
= parent_si
->type
;
1505 child_si
->protocol
= parent_si
->protocol
;
1506 child_si
->bound
= 1;
1507 child_si
->is_server
= 1;
1508 child_si
->connected
= 1;
1510 child_si
->peername_len
= len
;
1511 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1513 if (addr
!= NULL
&& addrlen
!= NULL
) {
1515 if (*addrlen
>= len
)
1516 memcpy(addr
, my_addr
, len
);
1520 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1528 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1529 child_si
->family
, my_addr
, &len
);
1537 child_si
->myname_len
= len
;
1538 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1541 SWRAP_DLIST_ADD(sockets
, child_si
);
1543 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1544 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1545 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1550 static int autobind_start_init
;
1551 static int autobind_start
;
1553 /* using sendto() or connect() on an unbound socket would give the
1554 recipient no way to reply, as unlike UDP and TCP, a unix domain
1555 socket can't auto-assign emphemeral port numbers, so we need to
1557 Note: this might change the family from ipv6 to ipv4
1559 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1561 struct sockaddr_un un_addr
;
1568 if (autobind_start_init
!= 1) {
1569 autobind_start_init
= 1;
1570 autobind_start
= getpid();
1571 autobind_start
%= 50000;
1572 autobind_start
+= 10000;
1575 un_addr
.sun_family
= AF_UNIX
;
1579 struct sockaddr_in in
;
1583 type
= SOCKET_TYPE_CHAR_TCP
;
1586 type
= SOCKET_TYPE_CHAR_UDP
;
1589 errno
= ESOCKTNOSUPPORT
;
1593 memset(&in
, 0, sizeof(in
));
1594 in
.sin_family
= AF_INET
;
1595 in
.sin_addr
.s_addr
= htonl(127<<24 |
1596 socket_wrapper_default_iface());
1598 si
->myname_len
= sizeof(in
);
1599 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1604 struct sockaddr_in6 in6
;
1606 if (si
->family
!= family
) {
1607 errno
= ENETUNREACH
;
1613 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1616 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1619 errno
= ESOCKTNOSUPPORT
;
1623 memset(&in6
, 0, sizeof(in6
));
1624 in6
.sin6_family
= AF_INET6
;
1625 in6
.sin6_addr
= *swrap_ipv6();
1626 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1627 si
->myname_len
= sizeof(in6
);
1628 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1633 errno
= ESOCKTNOSUPPORT
;
1637 if (autobind_start
> 60000) {
1638 autobind_start
= 10000;
1641 for (i
=0;i
<1000;i
++) {
1642 port
= autobind_start
+ i
;
1643 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1644 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1645 type
, socket_wrapper_default_iface(), port
);
1646 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1648 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1649 if (ret
== -1) return ret
;
1651 si
->tmp_path
= strdup(un_addr
.sun_path
);
1653 autobind_start
= port
+ 1;
1661 si
->family
= family
;
1662 set_port(si
->family
, port
, si
->myname
);
1668 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1671 struct sockaddr_un un_addr
;
1672 struct socket_info
*si
= find_socket_info(s
);
1675 return real_connect(s
, serv_addr
, addrlen
);
1678 if (si
->bound
== 0) {
1679 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1680 if (ret
== -1) return -1;
1683 if (si
->family
!= serv_addr
->sa_family
) {
1688 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1689 if (ret
== -1) return -1;
1691 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1693 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1694 sizeof(struct sockaddr_un
));
1696 /* to give better errors */
1697 if (ret
== -1 && errno
== ENOENT
) {
1698 errno
= EHOSTUNREACH
;
1702 si
->peername_len
= addrlen
;
1703 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1706 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1707 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1709 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1715 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1718 struct sockaddr_un un_addr
;
1719 struct socket_info
*si
= find_socket_info(s
);
1722 return real_bind(s
, myaddr
, addrlen
);
1725 si
->myname_len
= addrlen
;
1726 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1728 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1729 if (ret
== -1) return -1;
1731 unlink(un_addr
.sun_path
);
1733 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1734 sizeof(struct sockaddr_un
));
1743 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1746 struct socket_info
*si
= find_socket_info(s
);
1749 return real_listen(s
, backlog
);
1752 ret
= real_listen(s
, backlog
);
1757 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1759 struct socket_info
*si
= find_socket_info(s
);
1762 return real_getpeername(s
, name
, addrlen
);
1771 memcpy(name
, si
->peername
, si
->peername_len
);
1772 *addrlen
= si
->peername_len
;
1777 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1779 struct socket_info
*si
= find_socket_info(s
);
1782 return real_getsockname(s
, name
, addrlen
);
1785 memcpy(name
, si
->myname
, si
->myname_len
);
1786 *addrlen
= si
->myname_len
;
1791 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1793 struct socket_info
*si
= find_socket_info(s
);
1796 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1799 if (level
== SOL_SOCKET
) {
1800 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1803 errno
= ENOPROTOOPT
;
1807 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1809 struct socket_info
*si
= find_socket_info(s
);
1812 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1815 if (level
== SOL_SOCKET
) {
1816 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1819 switch (si
->family
) {
1823 errno
= ENOPROTOOPT
;
1828 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1830 struct sockaddr_un un_addr
;
1831 socklen_t un_addrlen
= sizeof(un_addr
);
1833 struct socket_info
*si
= find_socket_info(s
);
1834 struct sockaddr_storage ss
;
1835 socklen_t ss_len
= sizeof(ss
);
1838 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1842 from
= (struct sockaddr
*)&ss
;
1846 len
= MIN(len
, 1500);
1848 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1849 memset(&un_addr
, 0, sizeof(un_addr
));
1850 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1854 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1855 si
->family
, from
, fromlen
) == -1) {
1859 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1865 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1867 struct sockaddr_un un_addr
;
1869 struct socket_info
*si
= find_socket_info(s
);
1873 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1876 if (si
->connected
) {
1883 tolen
= si
->peername_len
;
1886 len
= MIN(len
, 1500);
1890 ret
= real_send(s
, buf
, len
, flags
);
1893 if (si
->bound
== 0) {
1894 ret
= swrap_auto_bind(si
, si
->family
);
1895 if (ret
== -1) return -1;
1898 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1899 if (ret
== -1) return -1;
1904 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1907 type
= SOCKET_TYPE_CHAR_UDP
;
1909 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1910 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1911 socket_wrapper_dir(), type
, iface
, prt
);
1912 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1914 /* ignore the any errors in broadcast sends */
1915 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1918 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1923 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1927 errno
= EHOSTUNREACH
;
1931 /* to give better errors */
1932 if (ret
== -1 && errno
== ENOENT
) {
1933 errno
= EHOSTUNREACH
;
1937 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1938 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1940 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1946 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1949 struct socket_info
*si
= find_socket_info(s
);
1953 return real_ioctl(s
, r
, p
);
1956 ret
= real_ioctl(s
, r
, p
);
1960 value
= *((int *)p
);
1961 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1962 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1963 } else if (value
== 0) { /* END OF FILE */
1964 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1972 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1975 struct socket_info
*si
= find_socket_info(s
);
1978 return real_recv(s
, buf
, len
, flags
);
1981 len
= MIN(len
, 1500);
1983 ret
= real_recv(s
, buf
, len
, flags
);
1984 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1985 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1986 } else if (ret
== 0) { /* END OF FILE */
1987 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1988 } else if (ret
> 0) {
1989 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1996 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1999 struct socket_info
*si
= find_socket_info(s
);
2002 return real_send(s
, buf
, len
, flags
);
2005 len
= MIN(len
, 1500);
2007 ret
= real_send(s
, buf
, len
, flags
);
2010 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2011 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2013 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2019 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2022 struct socket_info
*si
= find_socket_info(s
);
2026 return real_readv(s
, vector
, count
);
2029 /* we read 1500 bytes as maximum */
2033 for (i
=0; i
< count
; i
++) {
2035 nlen
= len
+ vector
[i
].iov_len
;
2043 v
.iov_len
= MIN(v
.iov_len
, 1500);
2049 ret
= real_readv(s
, vector
, count
);
2050 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2051 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2052 } else if (ret
== 0) { /* END OF FILE */
2053 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2054 } else if (ret
> 0) {
2058 size_t remain
= ret
;
2060 /* we capture it as one single packet */
2061 buf
= (uint8_t *)malloc(ret
);
2063 /* we just not capture the packet */
2068 for (i
=0; i
< count
; i
++) {
2069 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2074 remain
-= this_time
;
2077 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2084 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2087 struct socket_info
*si
= find_socket_info(s
);
2091 return real_writev(s
, vector
, count
);
2094 /* we write 1500 bytes as maximum */
2098 for (i
=0; i
< count
; i
++) {
2100 nlen
= len
+ vector
[i
].iov_len
;
2108 v
.iov_len
= MIN(v
.iov_len
, 1500);
2114 ret
= real_writev(s
, vector
, count
);
2116 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2121 size_t remain
= ret
;
2123 /* we capture it as one single packet */
2124 buf
= (uint8_t *)malloc(ret
);
2126 /* we just not capture the packet */
2131 for (i
=0; i
< count
; i
++) {
2132 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2137 remain
-= this_time
;
2140 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2147 _PUBLIC_
int swrap_close(int fd
)
2149 struct socket_info
*si
= find_socket_info(fd
);
2153 return real_close(fd
);
2156 SWRAP_DLIST_REMOVE(sockets
, si
);
2158 if (si
->myname
&& si
->peername
) {
2159 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2162 ret
= real_close(fd
);
2164 if (si
->myname
&& si
->peername
) {
2165 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2166 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2169 if (si
->path
) free(si
->path
);
2170 if (si
->myname
) free(si
->myname
);
2171 if (si
->peername
) free(si
->peername
);
2173 unlink(si
->tmp_path
);