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
) {
1114 case SWRAP_CONNECT_SEND
:
1115 if (si
->type
!= SOCK_STREAM
) return NULL
;
1117 src_addr
= si
->myname
;
1120 tcp_seqno
= si
->io
.pck_snd
;
1121 tcp_ack
= si
->io
.pck_rcv
;
1122 tcp_ctl
= 0x02; /* SYN */
1124 si
->io
.pck_snd
+= 1;
1128 case SWRAP_CONNECT_RECV
:
1129 if (si
->type
!= SOCK_STREAM
) return NULL
;
1131 dest_addr
= si
->myname
;
1134 tcp_seqno
= si
->io
.pck_rcv
;
1135 tcp_ack
= si
->io
.pck_snd
;
1136 tcp_ctl
= 0x12; /** SYN,ACK */
1138 si
->io
.pck_rcv
+= 1;
1142 case SWRAP_CONNECT_UNREACH
:
1143 if (si
->type
!= SOCK_STREAM
) return NULL
;
1145 dest_addr
= si
->myname
;
1148 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1149 tcp_seqno
= si
->io
.pck_snd
- 1;
1150 tcp_ack
= si
->io
.pck_rcv
;
1151 tcp_ctl
= 0x02; /* SYN */
1156 case SWRAP_CONNECT_ACK
:
1157 if (si
->type
!= SOCK_STREAM
) return NULL
;
1159 src_addr
= si
->myname
;
1162 tcp_seqno
= si
->io
.pck_snd
;
1163 tcp_ack
= si
->io
.pck_rcv
;
1164 tcp_ctl
= 0x10; /* ACK */
1168 case SWRAP_ACCEPT_SEND
:
1169 if (si
->type
!= SOCK_STREAM
) return NULL
;
1171 dest_addr
= si
->myname
;
1174 tcp_seqno
= si
->io
.pck_rcv
;
1175 tcp_ack
= si
->io
.pck_snd
;
1176 tcp_ctl
= 0x02; /* SYN */
1178 si
->io
.pck_rcv
+= 1;
1182 case SWRAP_ACCEPT_RECV
:
1183 if (si
->type
!= SOCK_STREAM
) return NULL
;
1185 src_addr
= si
->myname
;
1188 tcp_seqno
= si
->io
.pck_snd
;
1189 tcp_ack
= si
->io
.pck_rcv
;
1190 tcp_ctl
= 0x12; /* SYN,ACK */
1192 si
->io
.pck_snd
+= 1;
1196 case SWRAP_ACCEPT_ACK
:
1197 if (si
->type
!= SOCK_STREAM
) return NULL
;
1199 dest_addr
= si
->myname
;
1202 tcp_seqno
= si
->io
.pck_rcv
;
1203 tcp_ack
= si
->io
.pck_snd
;
1204 tcp_ctl
= 0x10; /* ACK */
1209 src_addr
= si
->myname
;
1210 dest_addr
= si
->peername
;
1212 tcp_seqno
= si
->io
.pck_snd
;
1213 tcp_ack
= si
->io
.pck_rcv
;
1214 tcp_ctl
= 0x18; /* PSH,ACK */
1216 si
->io
.pck_snd
+= len
;
1220 case SWRAP_SEND_RST
:
1221 dest_addr
= si
->myname
;
1222 src_addr
= si
->peername
;
1224 if (si
->type
== SOCK_DGRAM
) {
1225 return swrap_marshall_packet(si
, si
->peername
,
1226 SWRAP_SENDTO_UNREACH
,
1227 buf
, len
, packet_len
);
1230 tcp_seqno
= si
->io
.pck_rcv
;
1231 tcp_ack
= si
->io
.pck_snd
;
1232 tcp_ctl
= 0x14; /** RST,ACK */
1236 case SWRAP_PENDING_RST
:
1237 dest_addr
= si
->myname
;
1238 src_addr
= si
->peername
;
1240 if (si
->type
== SOCK_DGRAM
) {
1244 tcp_seqno
= si
->io
.pck_rcv
;
1245 tcp_ack
= si
->io
.pck_snd
;
1246 tcp_ctl
= 0x14; /* RST,ACK */
1251 dest_addr
= si
->myname
;
1252 src_addr
= si
->peername
;
1254 tcp_seqno
= si
->io
.pck_rcv
;
1255 tcp_ack
= si
->io
.pck_snd
;
1256 tcp_ctl
= 0x18; /* PSH,ACK */
1258 si
->io
.pck_rcv
+= len
;
1262 case SWRAP_RECV_RST
:
1263 dest_addr
= si
->myname
;
1264 src_addr
= si
->peername
;
1266 if (si
->type
== SOCK_DGRAM
) {
1270 tcp_seqno
= si
->io
.pck_rcv
;
1271 tcp_ack
= si
->io
.pck_snd
;
1272 tcp_ctl
= 0x14; /* RST,ACK */
1277 src_addr
= si
->myname
;
1280 si
->io
.pck_snd
+= len
;
1284 case SWRAP_SENDTO_UNREACH
:
1285 dest_addr
= si
->myname
;
1292 case SWRAP_RECVFROM
:
1293 dest_addr
= si
->myname
;
1296 si
->io
.pck_rcv
+= len
;
1300 case SWRAP_CLOSE_SEND
:
1301 if (si
->type
!= SOCK_STREAM
) return NULL
;
1303 src_addr
= si
->myname
;
1304 dest_addr
= si
->peername
;
1306 tcp_seqno
= si
->io
.pck_snd
;
1307 tcp_ack
= si
->io
.pck_rcv
;
1308 tcp_ctl
= 0x11; /* FIN, ACK */
1310 si
->io
.pck_snd
+= 1;
1314 case SWRAP_CLOSE_RECV
:
1315 if (si
->type
!= SOCK_STREAM
) return NULL
;
1317 dest_addr
= si
->myname
;
1318 src_addr
= si
->peername
;
1320 tcp_seqno
= si
->io
.pck_rcv
;
1321 tcp_ack
= si
->io
.pck_snd
;
1322 tcp_ctl
= 0x11; /* FIN,ACK */
1324 si
->io
.pck_rcv
+= 1;
1328 case SWRAP_CLOSE_ACK
:
1329 if (si
->type
!= SOCK_STREAM
) return NULL
;
1331 src_addr
= si
->myname
;
1332 dest_addr
= si
->peername
;
1334 tcp_seqno
= si
->io
.pck_snd
;
1335 tcp_ack
= si
->io
.pck_rcv
;
1336 tcp_ctl
= 0x10; /* ACK */
1343 swrapGetTimeOfDay(&tv
);
1345 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1346 (const uint8_t *)buf
, len
,
1347 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1351 static void swrap_dump_packet(struct socket_info
*si
,
1352 const struct sockaddr
*addr
,
1353 enum swrap_packet_type type
,
1354 const void *buf
, size_t len
)
1356 const char *file_name
;
1358 size_t packet_len
= 0;
1361 file_name
= socket_wrapper_pcap_file();
1366 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1371 fd
= swrap_get_pcap_fd(file_name
);
1373 if (write(fd
, packet
, packet_len
) != packet_len
) {
1382 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1384 struct socket_info
*si
;
1387 if (!socket_wrapper_dir()) {
1388 return real_socket(family
, type
, protocol
);
1398 return real_socket(family
, type
, protocol
);
1400 errno
= EAFNOSUPPORT
;
1410 errno
= EPROTONOSUPPORT
;
1418 if (type
== SOCK_STREAM
) {
1423 if (type
== SOCK_DGRAM
) {
1428 errno
= EPROTONOSUPPORT
;
1432 fd
= real_socket(AF_UNIX
, type
, 0);
1434 if (fd
== -1) return -1;
1436 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1438 si
->family
= family
;
1440 si
->protocol
= protocol
;
1443 SWRAP_DLIST_ADD(sockets
, si
);
1448 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1450 struct socket_info
*parent_si
, *child_si
;
1452 struct sockaddr_un un_addr
;
1453 socklen_t un_addrlen
= sizeof(un_addr
);
1454 struct sockaddr_un un_my_addr
;
1455 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1456 struct sockaddr
*my_addr
;
1457 socklen_t my_addrlen
, len
;
1460 parent_si
= find_socket_info(s
);
1462 return real_accept(s
, addr
, addrlen
);
1466 * assume out sockaddr have the same size as the in parent
1469 my_addrlen
= socket_length(parent_si
->family
);
1470 if (my_addrlen
<= 0) {
1475 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1476 if (my_addr
== NULL
) {
1480 memset(&un_addr
, 0, sizeof(un_addr
));
1481 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1483 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1492 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1493 parent_si
->family
, my_addr
, &len
);
1500 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1501 memset(child_si
, 0, sizeof(*child_si
));
1504 child_si
->family
= parent_si
->family
;
1505 child_si
->type
= parent_si
->type
;
1506 child_si
->protocol
= parent_si
->protocol
;
1507 child_si
->bound
= 1;
1508 child_si
->is_server
= 1;
1509 child_si
->connected
= 1;
1511 child_si
->peername_len
= len
;
1512 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1514 if (addr
!= NULL
&& addrlen
!= NULL
) {
1516 if (*addrlen
>= len
)
1517 memcpy(addr
, my_addr
, len
);
1521 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1529 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1530 child_si
->family
, my_addr
, &len
);
1538 child_si
->myname_len
= len
;
1539 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1542 SWRAP_DLIST_ADD(sockets
, child_si
);
1544 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1545 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1546 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1551 static int autobind_start_init
;
1552 static int autobind_start
;
1554 /* using sendto() or connect() on an unbound socket would give the
1555 recipient no way to reply, as unlike UDP and TCP, a unix domain
1556 socket can't auto-assign emphemeral port numbers, so we need to
1558 Note: this might change the family from ipv6 to ipv4
1560 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1562 struct sockaddr_un un_addr
;
1569 if (autobind_start_init
!= 1) {
1570 autobind_start_init
= 1;
1571 autobind_start
= getpid();
1572 autobind_start
%= 50000;
1573 autobind_start
+= 10000;
1576 un_addr
.sun_family
= AF_UNIX
;
1580 struct sockaddr_in in
;
1584 type
= SOCKET_TYPE_CHAR_TCP
;
1587 type
= SOCKET_TYPE_CHAR_UDP
;
1590 errno
= ESOCKTNOSUPPORT
;
1594 memset(&in
, 0, sizeof(in
));
1595 in
.sin_family
= AF_INET
;
1596 in
.sin_addr
.s_addr
= htonl(127<<24 |
1597 socket_wrapper_default_iface());
1599 si
->myname_len
= sizeof(in
);
1600 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1605 struct sockaddr_in6 in6
;
1607 if (si
->family
!= family
) {
1608 errno
= ENETUNREACH
;
1614 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1617 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1620 errno
= ESOCKTNOSUPPORT
;
1624 memset(&in6
, 0, sizeof(in6
));
1625 in6
.sin6_family
= AF_INET6
;
1626 in6
.sin6_addr
= *swrap_ipv6();
1627 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1628 si
->myname_len
= sizeof(in6
);
1629 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1634 errno
= ESOCKTNOSUPPORT
;
1638 if (autobind_start
> 60000) {
1639 autobind_start
= 10000;
1642 for (i
=0;i
<1000;i
++) {
1643 port
= autobind_start
+ i
;
1644 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1645 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1646 type
, socket_wrapper_default_iface(), port
);
1647 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1649 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1650 if (ret
== -1) return ret
;
1652 si
->tmp_path
= strdup(un_addr
.sun_path
);
1654 autobind_start
= port
+ 1;
1662 si
->family
= family
;
1663 set_port(si
->family
, port
, si
->myname
);
1669 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1672 struct sockaddr_un un_addr
;
1673 struct socket_info
*si
= find_socket_info(s
);
1676 return real_connect(s
, serv_addr
, addrlen
);
1679 if (si
->bound
== 0) {
1680 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1681 if (ret
== -1) return -1;
1684 if (si
->family
!= serv_addr
->sa_family
) {
1689 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1690 if (ret
== -1) return -1;
1692 if (si
->type
== SOCK_DGRAM
) {
1693 si
->defer_connect
= 1;
1696 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1698 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1699 sizeof(struct sockaddr_un
));
1702 /* to give better errors */
1703 if (ret
== -1 && errno
== ENOENT
) {
1704 errno
= EHOSTUNREACH
;
1708 si
->peername_len
= addrlen
;
1709 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1712 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1713 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1715 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1721 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1724 struct sockaddr_un un_addr
;
1725 struct socket_info
*si
= find_socket_info(s
);
1728 return real_bind(s
, myaddr
, addrlen
);
1731 si
->myname_len
= addrlen
;
1732 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1734 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1735 if (ret
== -1) return -1;
1737 unlink(un_addr
.sun_path
);
1739 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1740 sizeof(struct sockaddr_un
));
1749 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1752 struct socket_info
*si
= find_socket_info(s
);
1755 return real_listen(s
, backlog
);
1758 ret
= real_listen(s
, backlog
);
1763 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1765 struct socket_info
*si
= find_socket_info(s
);
1768 return real_getpeername(s
, name
, addrlen
);
1777 memcpy(name
, si
->peername
, si
->peername_len
);
1778 *addrlen
= si
->peername_len
;
1783 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1785 struct socket_info
*si
= find_socket_info(s
);
1788 return real_getsockname(s
, name
, addrlen
);
1791 memcpy(name
, si
->myname
, si
->myname_len
);
1792 *addrlen
= si
->myname_len
;
1797 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1799 struct socket_info
*si
= find_socket_info(s
);
1802 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1805 if (level
== SOL_SOCKET
) {
1806 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1809 errno
= ENOPROTOOPT
;
1813 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1815 struct socket_info
*si
= find_socket_info(s
);
1818 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1821 if (level
== SOL_SOCKET
) {
1822 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1825 switch (si
->family
) {
1829 errno
= ENOPROTOOPT
;
1834 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1836 struct sockaddr_un un_addr
;
1837 socklen_t un_addrlen
= sizeof(un_addr
);
1839 struct socket_info
*si
= find_socket_info(s
);
1840 struct sockaddr_storage ss
;
1841 socklen_t ss_len
= sizeof(ss
);
1844 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1848 from
= (struct sockaddr
*)&ss
;
1852 len
= MIN(len
, 1500);
1854 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1855 memset(&un_addr
, 0, sizeof(un_addr
));
1856 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1860 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1861 si
->family
, from
, fromlen
) == -1) {
1865 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1871 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1873 struct sockaddr_un un_addr
;
1875 struct socket_info
*si
= find_socket_info(s
);
1879 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1882 if (si
->connected
) {
1889 tolen
= si
->peername_len
;
1892 len
= MIN(len
, 1500);
1896 ret
= real_send(s
, buf
, len
, flags
);
1899 if (si
->bound
== 0) {
1900 ret
= swrap_auto_bind(si
, si
->family
);
1901 if (ret
== -1) return -1;
1904 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1905 if (ret
== -1) return -1;
1910 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1913 type
= SOCKET_TYPE_CHAR_UDP
;
1915 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1916 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1917 socket_wrapper_dir(), type
, iface
, prt
);
1918 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1920 /* ignore the any errors in broadcast sends */
1921 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1924 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1929 if (si
->defer_connect
) {
1930 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1933 /* to give better errors */
1934 if (ret
== -1 && errno
== ENOENT
) {
1935 errno
= EHOSTUNREACH
;
1941 si
->defer_connect
= 0;
1944 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1948 errno
= EHOSTUNREACH
;
1952 /* to give better errors */
1953 if (ret
== -1 && errno
== ENOENT
) {
1954 errno
= EHOSTUNREACH
;
1958 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1959 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1961 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1967 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1970 struct socket_info
*si
= find_socket_info(s
);
1974 return real_ioctl(s
, r
, p
);
1977 ret
= real_ioctl(s
, r
, p
);
1981 value
= *((int *)p
);
1982 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1983 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1984 } else if (value
== 0) { /* END OF FILE */
1985 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1993 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1996 struct socket_info
*si
= find_socket_info(s
);
1999 return real_recv(s
, buf
, len
, flags
);
2002 len
= MIN(len
, 1500);
2004 ret
= real_recv(s
, buf
, len
, flags
);
2005 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2006 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2007 } else if (ret
== 0) { /* END OF FILE */
2008 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2009 } else if (ret
> 0) {
2010 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2017 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2020 struct socket_info
*si
= find_socket_info(s
);
2023 return real_send(s
, buf
, len
, flags
);
2026 len
= MIN(len
, 1500);
2028 if (si
->defer_connect
) {
2029 struct sockaddr_un un_addr
;
2032 if (si
->bound
== 0) {
2033 ret
= swrap_auto_bind(si
, si
->family
);
2034 if (ret
== -1) return -1;
2037 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2038 &un_addr
, 0, &bcast
);
2039 if (ret
== -1) return -1;
2041 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
2044 /* to give better errors */
2045 if (ret
== -1 && errno
== ENOENT
) {
2046 errno
= EHOSTUNREACH
;
2052 si
->defer_connect
= 0;
2055 ret
= real_send(s
, buf
, len
, flags
);
2058 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2059 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2061 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2067 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2070 struct socket_info
*si
= find_socket_info(s
);
2074 return real_readv(s
, vector
, count
);
2077 /* we read 1500 bytes as maximum */
2081 for (i
=0; i
< count
; i
++) {
2083 nlen
= len
+ vector
[i
].iov_len
;
2091 v
.iov_len
= MIN(v
.iov_len
, 1500);
2097 ret
= real_readv(s
, vector
, count
);
2098 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2099 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2100 } else if (ret
== 0) { /* END OF FILE */
2101 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2102 } else if (ret
> 0) {
2106 size_t remain
= ret
;
2108 /* we capture it as one single packet */
2109 buf
= (uint8_t *)malloc(ret
);
2111 /* we just not capture the packet */
2116 for (i
=0; i
< count
; i
++) {
2117 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2122 remain
-= this_time
;
2125 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2132 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2135 struct socket_info
*si
= find_socket_info(s
);
2139 return real_writev(s
, vector
, count
);
2142 /* we write 1500 bytes as maximum */
2146 for (i
=0; i
< count
; i
++) {
2148 nlen
= len
+ vector
[i
].iov_len
;
2156 v
.iov_len
= MIN(v
.iov_len
, 1500);
2162 ret
= real_writev(s
, vector
, count
);
2164 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2169 size_t remain
= ret
;
2171 /* we capture it as one single packet */
2172 buf
= (uint8_t *)malloc(ret
);
2174 /* we just not capture the packet */
2179 for (i
=0; i
< count
; i
++) {
2180 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2185 remain
-= this_time
;
2188 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2195 _PUBLIC_
int swrap_close(int fd
)
2197 struct socket_info
*si
= find_socket_info(fd
);
2201 return real_close(fd
);
2204 SWRAP_DLIST_REMOVE(sockets
, si
);
2206 if (si
->myname
&& si
->peername
) {
2207 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2210 ret
= real_close(fd
);
2212 if (si
->myname
&& si
->peername
) {
2213 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2214 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2217 if (si
->path
) free(si
->path
);
2218 if (si
->myname
) free(si
->myname
);
2219 if (si
->peername
) free(si
->peername
);
2221 unlink(si
->tmp_path
);