2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <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_socket socket
125 #define real_close close
128 #ifdef HAVE_GETTIMEOFDAY_TZ
129 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
131 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
134 /* we need to use a very terse format here as IRIX 6.4 silently
135 truncates names to 16 chars, so if we use a longer name then we
136 can't tell which port a packet came from with recvfrom()
138 with this format we have 8 chars left for the directory name
140 #define SOCKET_FORMAT "%c%02X%04X"
141 #define SOCKET_TYPE_CHAR_TCP 'T'
142 #define SOCKET_TYPE_CHAR_UDP 'U'
143 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
144 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
146 #define MAX_WRAPPED_INTERFACES 16
148 #define SW_IPV6_ADDRESS 1
150 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
152 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
153 memcpy(ret
, data
, len
);
157 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
161 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
165 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
171 static size_t socket_length(int family
)
175 return sizeof(struct sockaddr_in
);
178 return sizeof(struct sockaddr_in6
);
200 struct sockaddr
*myname
;
201 socklen_t myname_len
;
203 struct sockaddr
*peername
;
204 socklen_t peername_len
;
207 unsigned long pck_snd
;
208 unsigned long pck_rcv
;
211 struct socket_info
*prev
, *next
;
214 static struct socket_info
*sockets
;
216 const char *socket_wrapper_dir(void)
218 const char *s
= getenv("SOCKET_WRAPPER_DIR");
222 if (strncmp(s
, "./", 2) == 0) {
228 unsigned int socket_wrapper_default_iface(void)
230 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
233 if (sscanf(s
, "%u", &iface
) == 1) {
234 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
240 return 1;/* 127.0.0.1 */
243 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
250 p
= strrchr(un
->sun_path
, '/');
251 if (p
) p
++; else p
= un
->sun_path
;
253 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
258 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
269 case SOCKET_TYPE_CHAR_TCP
:
270 case SOCKET_TYPE_CHAR_UDP
: {
271 struct sockaddr_in
*in2
= (struct sockaddr_in
*)in
;
273 if ((*len
) < sizeof(*in2
)) {
278 memset(in2
, 0, sizeof(*in2
));
279 in2
->sin_family
= AF_INET
;
280 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
281 in2
->sin_port
= htons(prt
);
287 case SOCKET_TYPE_CHAR_TCP_V6
:
288 case SOCKET_TYPE_CHAR_UDP_V6
: {
289 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)in
;
291 if ((*len
) < sizeof(*in2
)) {
296 memset(in2
, 0, sizeof(*in2
));
297 in2
->sin6_family
= AF_INET6
;
298 in2
->sin6_addr
.s6_addr
[0] = SW_IPV6_ADDRESS
;
299 in2
->sin6_port
= htons(prt
);
313 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
321 if (bcast
) *bcast
= 0;
323 switch (si
->family
) {
325 const struct sockaddr_in
*in
=
326 (const struct sockaddr_in
*)inaddr
;
327 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
334 u_type
= SOCKET_TYPE_CHAR_TCP
;
337 u_type
= SOCKET_TYPE_CHAR_UDP
;
338 a_type
= SOCKET_TYPE_CHAR_UDP
;
339 b_type
= SOCKET_TYPE_CHAR_UDP
;
343 prt
= ntohs(in
->sin_port
);
344 if (a_type
&& addr
== 0xFFFFFFFF) {
345 /* 255.255.255.255 only udp */
348 iface
= socket_wrapper_default_iface();
349 } else if (b_type
&& addr
== 0x7FFFFFFF) {
350 /* 127.255.255.255 only udp */
353 iface
= socket_wrapper_default_iface();
354 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
358 iface
= (addr
& 0x000000FF);
363 if (bcast
) *bcast
= is_bcast
;
368 const struct sockaddr_in6
*in
=
369 (const struct sockaddr_in6
*)inaddr
;
373 type
= SOCKET_TYPE_CHAR_TCP_V6
;
376 type
= SOCKET_TYPE_CHAR_UDP_V6
;
380 /* XXX no multicast/broadcast */
382 prt
= ntohs(in
->sin6_port
);
383 iface
= SW_IPV6_ADDRESS
;
399 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
400 socket_wrapper_dir());
401 /* the caller need to do more processing */
405 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
406 socket_wrapper_dir(), type
, iface
, prt
);
411 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
420 if (bcast
) *bcast
= 0;
422 switch (si
->family
) {
424 const struct sockaddr_in
*in
=
425 (const struct sockaddr_in
*)inaddr
;
426 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
432 prt
= ntohs(in
->sin_port
);
436 u_type
= SOCKET_TYPE_CHAR_TCP
;
437 d_type
= SOCKET_TYPE_CHAR_TCP
;
440 u_type
= SOCKET_TYPE_CHAR_UDP
;
441 d_type
= SOCKET_TYPE_CHAR_UDP
;
442 a_type
= SOCKET_TYPE_CHAR_UDP
;
443 b_type
= SOCKET_TYPE_CHAR_UDP
;
451 iface
= socket_wrapper_default_iface();
452 } else if (a_type
&& addr
== 0xFFFFFFFF) {
453 /* 255.255.255.255 only udp */
456 iface
= socket_wrapper_default_iface();
457 } else if (b_type
&& addr
== 0x7FFFFFFF) {
458 /* 127.255.255.255 only udp */
461 iface
= socket_wrapper_default_iface();
462 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
466 iface
= (addr
& 0x000000FF);
468 errno
= EADDRNOTAVAIL
;
475 const struct sockaddr_in6
*in
=
476 (const struct sockaddr_in6
*)inaddr
;
480 type
= SOCKET_TYPE_CHAR_TCP_V6
;
483 type
= SOCKET_TYPE_CHAR_UDP_V6
;
487 /* XXX no multicast/broadcast */
489 prt
= ntohs(in
->sin6_port
);
490 iface
= SW_IPV6_ADDRESS
;
501 if (bcast
) *bcast
= is_bcast
;
504 /* handle auto-allocation of ephemeral ports */
505 for (prt
= 5001; prt
< 10000; prt
++) {
506 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
507 socket_wrapper_dir(), type
, iface
, prt
);
508 if (stat(un
->sun_path
, &st
) == 0) continue;
510 set_port(si
->family
, prt
, si
->myname
);
519 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
520 socket_wrapper_dir(), type
, iface
, prt
);
524 static struct socket_info
*find_socket_info(int fd
)
526 struct socket_info
*i
;
527 for (i
= sockets
; i
; i
= i
->next
) {
535 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
536 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
541 out_addr
->sun_family
= AF_UNIX
;
543 switch (in_addr
->sa_family
) {
553 errno
= ESOCKTNOSUPPORT
;
557 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
559 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
565 errno
= EAFNOSUPPORT
;
569 static int sockaddr_convert_from_un(const struct socket_info
*si
,
570 const struct sockaddr_un
*in_addr
,
571 socklen_t un_addrlen
,
573 struct sockaddr
*out_addr
,
574 socklen_t
*out_addrlen
)
576 if (out_addr
== NULL
|| out_addrlen
== NULL
)
579 if (un_addrlen
== 0) {
594 errno
= ESOCKTNOSUPPORT
;
597 return convert_un_in(in_addr
, out_addr
, out_addrlen
);
602 errno
= EAFNOSUPPORT
;
606 enum swrap_packet_type
{
608 SWRAP_CONNECT_UNREACH
,
616 SWRAP_SENDTO_UNREACH
,
627 struct swrap_file_hdr
{
629 uint16_t version_major
;
630 uint16_t version_minor
;
633 uint32_t frame_max_len
;
634 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
637 #define SWRAP_FILE_HDR_SIZE 24
639 struct swrap_packet_frame
{
641 uint32_t micro_seconds
;
642 uint32_t recorded_length
;
643 uint32_t full_length
;
645 #define SWRAP_PACKET_FRAME_SIZE 16
647 union swrap_packet_ip
{
651 uint16_t packet_length
;
652 uint16_t identification
;
657 uint16_t hdr_checksum
;
661 #define SWRAP_PACKET_IP_V4_SIZE 20
664 uint8_t flow_label_high
;
665 uint16_t flow_label_low
;
666 uint16_t payload_length
;
669 uint8_t src_addr
[16];
670 uint8_t dest_addr
[16];
672 #define SWRAP_PACKET_IP_V6_SIZE 40
674 #define SWRAP_PACKET_IP_SIZE 40
676 union swrap_packet_payload
{
678 uint16_t source_port
;
688 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
690 uint16_t source_port
;
695 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
702 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
709 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
711 #define SWRAP_PACKET_PAYLOAD_SIZE 20
713 #define SWRAP_PACKET_MIN_ALLOC \
714 (SWRAP_PACKET_FRAME_SIZE + \
715 SWRAP_PACKET_IP_SIZE + \
716 SWRAP_PACKET_PAYLOAD_SIZE)
718 static const char *socket_wrapper_pcap_file(void)
720 static int initialized
= 0;
721 static const char *s
= NULL
;
722 static const struct swrap_file_hdr h
;
723 static const struct swrap_packet_frame f
;
724 static const union swrap_packet_ip i
;
725 static const union swrap_packet_payload p
;
727 if (initialized
== 1) {
733 * TODO: don't use the structs use plain buffer offsets
734 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
736 * for now make sure we disable PCAP support
737 * if the struct has alignment!
739 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
742 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
745 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
748 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
751 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
754 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
757 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
760 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
763 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
766 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
770 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
774 if (strncmp(s
, "./", 2) == 0) {
780 static uint8_t *swrap_packet_init(struct timeval
*tval
,
781 const struct sockaddr
*src
,
782 const struct sockaddr
*dest
,
784 const uint8_t *payload
,
786 unsigned long tcp_seqno
,
787 unsigned long tcp_ack
,
788 unsigned char tcp_ctl
,
794 struct swrap_packet_frame
*frame
;
795 union swrap_packet_ip
*ip
;
796 union swrap_packet_payload
*pay
;
799 size_t nonwire_len
= sizeof(*frame
);
800 size_t wire_hdr_len
= 0;
802 size_t ip_hdr_len
= 0;
803 size_t icmp_hdr_len
= 0;
804 size_t icmp_truncate_len
= 0;
805 uint8_t protocol
= 0, icmp_protocol
= 0;
806 const struct sockaddr_in
*src_in
;
807 const struct sockaddr_in
*dest_in
;
809 const struct sockaddr_in6
*src_in6
;
810 const struct sockaddr_in6
*dest_in6
;
815 switch (src
->sa_family
) {
817 src_in
= (const struct sockaddr_in
*)src
;
818 dest_in
= (const struct sockaddr_in
*)dest
;
819 src_port
= src_in
->sin_port
;
820 dest_port
= dest_in
->sin_port
;
821 ip_hdr_len
= sizeof(ip
->v4
);
825 src_in6
= (const struct sockaddr_in6
*)src
;
826 dest_in6
= (const struct sockaddr_in6
*)dest
;
827 src_port
= src_in6
->sin6_port
;
828 dest_port
= dest_in6
->sin6_port
;
829 ip_hdr_len
= sizeof(ip
->v6
);
836 switch (socket_type
) {
838 protocol
= 0x06; /* TCP */
839 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
840 wire_len
= wire_hdr_len
+ payload_len
;
844 protocol
= 0x11; /* UDP */
845 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
846 wire_len
= wire_hdr_len
+ payload_len
;
854 icmp_protocol
= protocol
;
855 switch (src
->sa_family
) {
857 protocol
= 0x01; /* ICMPv4 */
858 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
862 protocol
= 0x3A; /* ICMPv6 */
863 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
867 if (wire_len
> 64 ) {
868 icmp_truncate_len
= wire_len
- 64;
870 wire_hdr_len
+= icmp_hdr_len
;
871 wire_len
+= icmp_hdr_len
;
874 packet_len
= nonwire_len
+ wire_len
;
875 alloc_len
= packet_len
;
876 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
877 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
880 base
= (uint8_t *)malloc(alloc_len
);
881 if (!base
) return NULL
;
885 frame
= (struct swrap_packet_frame
*)buf
;
886 frame
->seconds
= tval
->tv_sec
;
887 frame
->micro_seconds
= tval
->tv_usec
;
888 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
889 frame
->full_length
= wire_len
- icmp_truncate_len
;
890 buf
+= SWRAP_PACKET_FRAME_SIZE
;
892 ip
= (union swrap_packet_ip
*)buf
;
893 switch (src
->sa_family
) {
895 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
897 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
898 ip
->v4
.identification
= htons(0xFFFF);
899 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
900 ip
->v4
.fragment
= htons(0x0000);
902 ip
->v4
.protocol
= protocol
;
903 ip
->v4
.hdr_checksum
= htons(0x0000);
904 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
905 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
906 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
910 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
911 ip
->v6
.flow_label_high
= 0x00;
912 ip
->v6
.flow_label_low
= 0x0000;
913 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
);//TODO
914 ip
->v6
.next_header
= protocol
;
915 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
916 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
917 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
923 pay
= (union swrap_packet_payload
*)buf
;
924 switch (src
->sa_family
) {
926 pay
->icmp4
.type
= 0x03; /* destination unreachable */
927 pay
->icmp4
.code
= 0x01; /* host unreachable */
928 pay
->icmp4
.checksum
= htons(0x0000);
929 pay
->icmp4
.unused
= htonl(0x00000000);
930 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
932 /* set the ip header in the ICMP payload */
933 ip
= (union swrap_packet_ip
*)buf
;
934 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
936 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
937 ip
->v4
.identification
= htons(0xFFFF);
938 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
939 ip
->v4
.fragment
= htons(0x0000);
941 ip
->v4
.protocol
= icmp_protocol
;
942 ip
->v4
.hdr_checksum
= htons(0x0000);
943 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
944 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
945 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
947 src_port
= dest_in
->sin_port
;
948 dest_port
= src_in
->sin_port
;
952 pay
->icmp6
.type
= 0x01; /* destination unreachable */
953 pay
->icmp6
.code
= 0x03; /* address unreachable */
954 pay
->icmp6
.checksum
= htons(0x0000);
955 pay
->icmp6
.unused
= htonl(0x00000000);
956 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
958 /* set the ip header in the ICMP payload */
959 ip
= (union swrap_packet_ip
*)buf
;
960 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
961 ip
->v6
.flow_label_high
= 0x00;
962 ip
->v6
.flow_label_low
= 0x0000;
963 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
);//TODO
964 ip
->v6
.next_header
= protocol
;
965 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
966 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
967 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
969 src_port
= dest_in6
->sin6_port
;
970 dest_port
= src_in6
->sin6_port
;
976 pay
= (union swrap_packet_payload
*)buf
;
978 switch (socket_type
) {
980 pay
->tcp
.source_port
= src_port
;
981 pay
->tcp
.dest_port
= dest_port
;
982 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
983 pay
->tcp
.ack_num
= htonl(tcp_ack
);
984 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
985 pay
->tcp
.control
= tcp_ctl
;
986 pay
->tcp
.window
= htons(0x7FFF);
987 pay
->tcp
.checksum
= htons(0x0000);
988 pay
->tcp
.urg
= htons(0x0000);
989 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
994 pay
->udp
.source_port
= src_port
;
995 pay
->udp
.dest_port
= dest_port
;
996 pay
->udp
.length
= htons(8 + payload_len
);
997 pay
->udp
.checksum
= htons(0x0000);
998 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1003 if (payload
&& payload_len
> 0) {
1004 memcpy(buf
, payload
, payload_len
);
1007 *_packet_len
= packet_len
- icmp_truncate_len
;
1011 static int swrap_get_pcap_fd(const char *fname
)
1015 if (fd
!= -1) return fd
;
1017 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1019 struct swrap_file_hdr file_hdr
;
1020 file_hdr
.magic
= 0xA1B2C3D4;
1021 file_hdr
.version_major
= 0x0002;
1022 file_hdr
.version_minor
= 0x0004;
1023 file_hdr
.timezone
= 0x00000000;
1024 file_hdr
.sigfigs
= 0x00000000;
1025 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1026 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1028 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1035 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1040 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1041 const struct sockaddr
*addr
,
1042 enum swrap_packet_type type
,
1043 const void *buf
, size_t len
,
1046 const struct sockaddr
*src_addr
;
1047 const struct sockaddr
*dest_addr
;
1048 unsigned long tcp_seqno
= 0;
1049 unsigned long tcp_ack
= 0;
1050 unsigned char tcp_ctl
= 0;
1051 int unreachable
= 0;
1055 switch (si
->family
) {
1065 case SWRAP_CONNECT_SEND
:
1066 if (si
->type
!= SOCK_STREAM
) return NULL
;
1068 src_addr
= si
->myname
;
1071 tcp_seqno
= si
->io
.pck_snd
;
1072 tcp_ack
= si
->io
.pck_rcv
;
1073 tcp_ctl
= 0x02; /* SYN */
1075 si
->io
.pck_snd
+= 1;
1079 case SWRAP_CONNECT_RECV
:
1080 if (si
->type
!= SOCK_STREAM
) return NULL
;
1082 dest_addr
= si
->myname
;
1085 tcp_seqno
= si
->io
.pck_rcv
;
1086 tcp_ack
= si
->io
.pck_snd
;
1087 tcp_ctl
= 0x12; /** SYN,ACK */
1089 si
->io
.pck_rcv
+= 1;
1093 case SWRAP_CONNECT_UNREACH
:
1094 if (si
->type
!= SOCK_STREAM
) return NULL
;
1096 dest_addr
= si
->myname
;
1099 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1100 tcp_seqno
= si
->io
.pck_snd
- 1;
1101 tcp_ack
= si
->io
.pck_rcv
;
1102 tcp_ctl
= 0x02; /* SYN */
1107 case SWRAP_CONNECT_ACK
:
1108 if (si
->type
!= SOCK_STREAM
) return NULL
;
1110 src_addr
= si
->myname
;
1113 tcp_seqno
= si
->io
.pck_snd
;
1114 tcp_ack
= si
->io
.pck_rcv
;
1115 tcp_ctl
= 0x10; /* ACK */
1119 case SWRAP_ACCEPT_SEND
:
1120 if (si
->type
!= SOCK_STREAM
) return NULL
;
1122 dest_addr
= si
->myname
;
1125 tcp_seqno
= si
->io
.pck_rcv
;
1126 tcp_ack
= si
->io
.pck_snd
;
1127 tcp_ctl
= 0x02; /* SYN */
1129 si
->io
.pck_rcv
+= 1;
1133 case SWRAP_ACCEPT_RECV
:
1134 if (si
->type
!= SOCK_STREAM
) return NULL
;
1136 src_addr
= si
->myname
;
1139 tcp_seqno
= si
->io
.pck_snd
;
1140 tcp_ack
= si
->io
.pck_rcv
;
1141 tcp_ctl
= 0x12; /* SYN,ACK */
1143 si
->io
.pck_snd
+= 1;
1147 case SWRAP_ACCEPT_ACK
:
1148 if (si
->type
!= SOCK_STREAM
) return NULL
;
1150 dest_addr
= si
->myname
;
1153 tcp_seqno
= si
->io
.pck_rcv
;
1154 tcp_ack
= si
->io
.pck_snd
;
1155 tcp_ctl
= 0x10; /* ACK */
1160 src_addr
= si
->myname
;
1161 dest_addr
= si
->peername
;
1163 tcp_seqno
= si
->io
.pck_snd
;
1164 tcp_ack
= si
->io
.pck_rcv
;
1165 tcp_ctl
= 0x18; /* PSH,ACK */
1167 si
->io
.pck_snd
+= len
;
1171 case SWRAP_SEND_RST
:
1172 dest_addr
= si
->myname
;
1173 src_addr
= si
->peername
;
1175 if (si
->type
== SOCK_DGRAM
) {
1176 return swrap_marshall_packet(si
, si
->peername
,
1177 SWRAP_SENDTO_UNREACH
,
1178 buf
, len
, packet_len
);
1181 tcp_seqno
= si
->io
.pck_rcv
;
1182 tcp_ack
= si
->io
.pck_snd
;
1183 tcp_ctl
= 0x14; /** RST,ACK */
1187 case SWRAP_PENDING_RST
:
1188 dest_addr
= si
->myname
;
1189 src_addr
= si
->peername
;
1191 if (si
->type
== SOCK_DGRAM
) {
1195 tcp_seqno
= si
->io
.pck_rcv
;
1196 tcp_ack
= si
->io
.pck_snd
;
1197 tcp_ctl
= 0x14; /* RST,ACK */
1202 dest_addr
= si
->myname
;
1203 src_addr
= si
->peername
;
1205 tcp_seqno
= si
->io
.pck_rcv
;
1206 tcp_ack
= si
->io
.pck_snd
;
1207 tcp_ctl
= 0x18; /* PSH,ACK */
1209 si
->io
.pck_rcv
+= len
;
1213 case SWRAP_RECV_RST
:
1214 dest_addr
= si
->myname
;
1215 src_addr
= si
->peername
;
1217 if (si
->type
== SOCK_DGRAM
) {
1221 tcp_seqno
= si
->io
.pck_rcv
;
1222 tcp_ack
= si
->io
.pck_snd
;
1223 tcp_ctl
= 0x14; /* RST,ACK */
1228 src_addr
= si
->myname
;
1231 si
->io
.pck_snd
+= len
;
1235 case SWRAP_SENDTO_UNREACH
:
1236 dest_addr
= si
->myname
;
1243 case SWRAP_RECVFROM
:
1244 dest_addr
= si
->myname
;
1247 si
->io
.pck_rcv
+= len
;
1251 case SWRAP_CLOSE_SEND
:
1252 if (si
->type
!= SOCK_STREAM
) return NULL
;
1254 src_addr
= si
->myname
;
1255 dest_addr
= si
->peername
;
1257 tcp_seqno
= si
->io
.pck_snd
;
1258 tcp_ack
= si
->io
.pck_rcv
;
1259 tcp_ctl
= 0x11; /* FIN, ACK */
1261 si
->io
.pck_snd
+= 1;
1265 case SWRAP_CLOSE_RECV
:
1266 if (si
->type
!= SOCK_STREAM
) return NULL
;
1268 dest_addr
= si
->myname
;
1269 src_addr
= si
->peername
;
1271 tcp_seqno
= si
->io
.pck_rcv
;
1272 tcp_ack
= si
->io
.pck_snd
;
1273 tcp_ctl
= 0x11; /* FIN,ACK */
1275 si
->io
.pck_rcv
+= 1;
1279 case SWRAP_CLOSE_ACK
:
1280 if (si
->type
!= SOCK_STREAM
) return NULL
;
1282 src_addr
= si
->myname
;
1283 dest_addr
= si
->peername
;
1285 tcp_seqno
= si
->io
.pck_snd
;
1286 tcp_ack
= si
->io
.pck_rcv
;
1287 tcp_ctl
= 0x10; /* ACK */
1294 swrapGetTimeOfDay(&tv
);
1296 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1297 (const uint8_t *)buf
, len
,
1298 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1302 static void swrap_dump_packet(struct socket_info
*si
,
1303 const struct sockaddr
*addr
,
1304 enum swrap_packet_type type
,
1305 const void *buf
, size_t len
)
1307 const char *file_name
;
1309 size_t packet_len
= 0;
1312 file_name
= socket_wrapper_pcap_file();
1317 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1322 fd
= swrap_get_pcap_fd(file_name
);
1324 if (write(fd
, packet
, packet_len
) != packet_len
) {
1333 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1335 struct socket_info
*si
;
1338 if (!socket_wrapper_dir()) {
1339 return real_socket(family
, type
, protocol
);
1349 return real_socket(family
, type
, protocol
);
1351 errno
= EAFNOSUPPORT
;
1361 errno
= EPROTONOSUPPORT
;
1369 if (type
== SOCK_STREAM
) {
1374 if (type
== SOCK_DGRAM
) {
1379 errno
= EPROTONOSUPPORT
;
1383 fd
= real_socket(AF_UNIX
, type
, 0);
1385 if (fd
== -1) return -1;
1387 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1389 si
->family
= family
;
1391 si
->protocol
= protocol
;
1394 SWRAP_DLIST_ADD(sockets
, si
);
1399 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1401 struct socket_info
*parent_si
, *child_si
;
1403 struct sockaddr_un un_addr
;
1404 socklen_t un_addrlen
= sizeof(un_addr
);
1405 struct sockaddr_un un_my_addr
;
1406 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1407 struct sockaddr
*my_addr
;
1408 socklen_t my_addrlen
, len
;
1411 parent_si
= find_socket_info(s
);
1413 return real_accept(s
, addr
, addrlen
);
1417 * assume out sockaddr have the same size as the in parent
1420 my_addrlen
= socket_length(parent_si
->family
);
1421 if (my_addrlen
<= 0) {
1426 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1427 if (my_addr
== NULL
) {
1431 memset(&un_addr
, 0, sizeof(un_addr
));
1432 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1434 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1443 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1444 parent_si
->family
, my_addr
, &len
);
1451 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1452 memset(child_si
, 0, sizeof(*child_si
));
1455 child_si
->family
= parent_si
->family
;
1456 child_si
->type
= parent_si
->type
;
1457 child_si
->protocol
= parent_si
->protocol
;
1458 child_si
->bound
= 1;
1459 child_si
->is_server
= 1;
1461 child_si
->peername_len
= len
;
1462 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1464 if (addr
!= NULL
&& addrlen
!= NULL
) {
1466 if (*addrlen
>= len
)
1467 memcpy(addr
, my_addr
, len
);
1471 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1479 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1480 child_si
->family
, my_addr
, &len
);
1488 child_si
->myname_len
= len
;
1489 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1492 SWRAP_DLIST_ADD(sockets
, child_si
);
1494 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1495 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1496 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1501 static int autobind_start_init
;
1502 static int autobind_start
;
1504 /* using sendto() or connect() on an unbound socket would give the
1505 recipient no way to reply, as unlike UDP and TCP, a unix domain
1506 socket can't auto-assign emphemeral port numbers, so we need to
1508 static int swrap_auto_bind(struct socket_info
*si
)
1510 struct sockaddr_un un_addr
;
1517 if (autobind_start_init
!= 1) {
1518 autobind_start_init
= 1;
1519 autobind_start
= getpid();
1520 autobind_start
%= 50000;
1521 autobind_start
+= 10000;
1524 un_addr
.sun_family
= AF_UNIX
;
1526 switch (si
->family
) {
1528 struct sockaddr_in in
;
1532 type
= SOCKET_TYPE_CHAR_TCP
;
1535 type
= SOCKET_TYPE_CHAR_UDP
;
1538 errno
= ESOCKTNOSUPPORT
;
1542 memset(&in
, 0, sizeof(in
));
1543 in
.sin_family
= AF_INET
;
1544 in
.sin_addr
.s_addr
= htonl(127<<24 |
1545 socket_wrapper_default_iface());
1547 si
->myname_len
= sizeof(in
);
1548 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1553 struct sockaddr_in6 in6
;
1557 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1560 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1563 errno
= ESOCKTNOSUPPORT
;
1567 memset(&in6
, 0, sizeof(in6
));
1568 in6
.sin6_family
= AF_INET6
;
1569 in6
.sin6_addr
.s6_addr
[0] = SW_IPV6_ADDRESS
;
1570 si
->myname_len
= sizeof(in6
);
1571 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1576 errno
= ESOCKTNOSUPPORT
;
1580 if (autobind_start
> 60000) {
1581 autobind_start
= 10000;
1584 for (i
=0;i
<1000;i
++) {
1585 port
= autobind_start
+ i
;
1586 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1587 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1588 type
, socket_wrapper_default_iface(), port
);
1589 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1591 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1592 if (ret
== -1) return ret
;
1594 si
->tmp_path
= strdup(un_addr
.sun_path
);
1596 autobind_start
= port
+ 1;
1604 set_port(si
->family
, port
, si
->myname
);
1610 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1613 struct sockaddr_un un_addr
;
1614 struct socket_info
*si
= find_socket_info(s
);
1617 return real_connect(s
, serv_addr
, addrlen
);
1620 if (si
->bound
== 0) {
1621 ret
= swrap_auto_bind(si
);
1622 if (ret
== -1) return -1;
1625 if (si
->family
!= serv_addr
->sa_family
) {
1630 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1631 if (ret
== -1) return -1;
1633 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1635 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1636 sizeof(struct sockaddr_un
));
1638 /* to give better errors */
1639 if (ret
== -1 && errno
== ENOENT
) {
1640 errno
= EHOSTUNREACH
;
1644 si
->peername_len
= addrlen
;
1645 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1647 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1648 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1650 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1656 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1659 struct sockaddr_un un_addr
;
1660 struct socket_info
*si
= find_socket_info(s
);
1663 return real_bind(s
, myaddr
, addrlen
);
1666 si
->myname_len
= addrlen
;
1667 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1669 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1670 if (ret
== -1) return -1;
1672 unlink(un_addr
.sun_path
);
1674 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1675 sizeof(struct sockaddr_un
));
1684 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1687 struct socket_info
*si
= find_socket_info(s
);
1690 return real_listen(s
, backlog
);
1693 ret
= real_listen(s
, backlog
);
1698 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1700 struct socket_info
*si
= find_socket_info(s
);
1703 return real_getpeername(s
, name
, addrlen
);
1712 memcpy(name
, si
->peername
, si
->peername_len
);
1713 *addrlen
= si
->peername_len
;
1718 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1720 struct socket_info
*si
= find_socket_info(s
);
1723 return real_getsockname(s
, name
, addrlen
);
1726 memcpy(name
, si
->myname
, si
->myname_len
);
1727 *addrlen
= si
->myname_len
;
1732 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1734 struct socket_info
*si
= find_socket_info(s
);
1737 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1740 if (level
== SOL_SOCKET
) {
1741 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1744 errno
= ENOPROTOOPT
;
1748 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1750 struct socket_info
*si
= find_socket_info(s
);
1753 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1756 if (level
== SOL_SOCKET
) {
1757 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1760 switch (si
->family
) {
1764 errno
= ENOPROTOOPT
;
1769 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1771 struct sockaddr_un un_addr
;
1772 socklen_t un_addrlen
= sizeof(un_addr
);
1774 struct socket_info
*si
= find_socket_info(s
);
1777 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1780 len
= MIN(len
, 1500);
1782 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1783 memset(&un_addr
, 0, sizeof(un_addr
));
1784 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1788 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1789 si
->family
, from
, fromlen
) == -1) {
1793 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1799 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1801 struct sockaddr_un un_addr
;
1803 struct socket_info
*si
= find_socket_info(s
);
1807 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1810 len
= MIN(len
, 1500);
1814 ret
= real_send(s
, buf
, len
, flags
);
1817 if (si
->bound
== 0) {
1818 ret
= swrap_auto_bind(si
);
1819 if (ret
== -1) return -1;
1822 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1823 if (ret
== -1) return -1;
1828 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1831 type
= SOCKET_TYPE_CHAR_UDP
;
1833 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1834 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1835 socket_wrapper_dir(), type
, iface
, prt
);
1836 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1838 /* ignore the any errors in broadcast sends */
1839 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1842 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1847 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1851 errno
= EHOSTUNREACH
;
1855 /* to give better errors */
1856 if (ret
== -1 && errno
== ENOENT
) {
1857 errno
= EHOSTUNREACH
;
1861 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1862 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1864 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1870 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1873 struct socket_info
*si
= find_socket_info(s
);
1877 return real_ioctl(s
, r
, p
);
1880 ret
= real_ioctl(s
, r
, p
);
1884 value
= *((int *)p
);
1885 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1886 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1887 } else if (value
== 0) { /* END OF FILE */
1888 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1896 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1899 struct socket_info
*si
= find_socket_info(s
);
1902 return real_recv(s
, buf
, len
, flags
);
1905 len
= MIN(len
, 1500);
1907 ret
= real_recv(s
, buf
, len
, flags
);
1908 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1909 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1910 } else if (ret
== 0) { /* END OF FILE */
1911 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1912 } else if (ret
> 0) {
1913 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1920 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1923 struct socket_info
*si
= find_socket_info(s
);
1926 return real_send(s
, buf
, len
, flags
);
1929 len
= MIN(len
, 1500);
1931 ret
= real_send(s
, buf
, len
, flags
);
1934 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
1935 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
1937 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
1943 _PUBLIC_
int swrap_close(int fd
)
1945 struct socket_info
*si
= find_socket_info(fd
);
1949 return real_close(fd
);
1952 SWRAP_DLIST_REMOVE(sockets
, si
);
1954 if (si
->myname
&& si
->peername
) {
1955 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
1958 ret
= real_close(fd
);
1960 if (si
->myname
&& si
->peername
) {
1961 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
1962 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
1965 if (si
->path
) free(si
->path
);
1966 if (si
->myname
) free(si
->myname
);
1967 if (si
->peername
) free(si
->peername
);
1969 unlink(si
->tmp_path
);