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_sendmsg sendmsg
122 #define real_ioctl ioctl
123 #define real_recv recv
124 #define real_read read
125 #define real_send send
126 #define real_readv readv
127 #define real_writev writev
128 #define real_socket socket
129 #define real_close close
132 #ifdef HAVE_GETTIMEOFDAY_TZ
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 /* we need to use a very terse format here as IRIX 6.4 silently
139 truncates names to 16 chars, so if we use a longer name then we
140 can't tell which port a packet came from with recvfrom()
142 with this format we have 8 chars left for the directory name
144 #define SOCKET_FORMAT "%c%02X%04X"
145 #define SOCKET_TYPE_CHAR_TCP 'T'
146 #define SOCKET_TYPE_CHAR_UDP 'U'
147 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
148 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
150 /* This limit is to avoid broadcast sendto() needing to stat too many
151 * files. It may be raised (with a performance cost) to up to 254
152 * without changing the format above */
153 #define MAX_WRAPPED_INTERFACES 32
159 static const struct in6_addr
*swrap_ipv6(void)
161 static struct in6_addr v
;
162 static int initialized
;
170 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
179 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
181 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
182 memcpy(ret
, data
, len
);
186 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
190 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
194 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
200 static size_t socket_length(int family
)
204 return sizeof(struct sockaddr_in
);
207 return sizeof(struct sockaddr_in6
);
231 struct sockaddr
*myname
;
232 socklen_t myname_len
;
234 struct sockaddr
*peername
;
235 socklen_t peername_len
;
238 unsigned long pck_snd
;
239 unsigned long pck_rcv
;
242 struct socket_info
*prev
, *next
;
245 static struct socket_info
*sockets
;
247 const char *socket_wrapper_dir(void)
249 const char *s
= getenv("SOCKET_WRAPPER_DIR");
253 if (strncmp(s
, "./", 2) == 0) {
259 unsigned int socket_wrapper_default_iface(void)
261 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
264 if (sscanf(s
, "%u", &iface
) == 1) {
265 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
271 return 1;/* 127.0.0.1 */
274 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
281 p
= strrchr(un
->sun_path
, '/');
282 if (p
) p
++; else p
= un
->sun_path
;
284 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
289 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
300 case SOCKET_TYPE_CHAR_TCP
:
301 case SOCKET_TYPE_CHAR_UDP
: {
302 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
304 if ((*len
) < sizeof(*in2
)) {
309 memset(in2
, 0, sizeof(*in2
));
310 in2
->sin_family
= AF_INET
;
311 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
312 in2
->sin_port
= htons(prt
);
318 case SOCKET_TYPE_CHAR_TCP_V6
:
319 case SOCKET_TYPE_CHAR_UDP_V6
: {
320 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
322 if ((*len
) < sizeof(*in2
)) {
327 memset(in2
, 0, sizeof(*in2
));
328 in2
->sin6_family
= AF_INET6
;
329 in2
->sin6_addr
= *swrap_ipv6();
330 in2
->sin6_addr
.s6_addr
[15] = iface
;
331 in2
->sin6_port
= htons(prt
);
345 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
353 if (bcast
) *bcast
= 0;
355 switch (inaddr
->sa_family
) {
357 const struct sockaddr_in
*in
=
358 (const struct sockaddr_in
*)(const void *)inaddr
;
359 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
366 u_type
= SOCKET_TYPE_CHAR_TCP
;
369 u_type
= SOCKET_TYPE_CHAR_UDP
;
370 a_type
= SOCKET_TYPE_CHAR_UDP
;
371 b_type
= SOCKET_TYPE_CHAR_UDP
;
375 prt
= ntohs(in
->sin_port
);
376 if (a_type
&& addr
== 0xFFFFFFFF) {
377 /* 255.255.255.255 only udp */
380 iface
= socket_wrapper_default_iface();
381 } else if (b_type
&& addr
== 0x7FFFFFFF) {
382 /* 127.255.255.255 only udp */
385 iface
= socket_wrapper_default_iface();
386 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
390 iface
= (addr
& 0x000000FF);
395 if (bcast
) *bcast
= is_bcast
;
400 const struct sockaddr_in6
*in
=
401 (const struct sockaddr_in6
*)(const void *)inaddr
;
402 struct in6_addr cmp1
, cmp2
;
406 type
= SOCKET_TYPE_CHAR_TCP_V6
;
409 type
= SOCKET_TYPE_CHAR_UDP_V6
;
413 /* XXX no multicast/broadcast */
415 prt
= ntohs(in
->sin6_port
);
417 cmp1
= *swrap_ipv6();
418 cmp2
= in
->sin6_addr
;
419 cmp2
.s6_addr
[15] = 0;
420 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
421 iface
= in
->sin6_addr
.s6_addr
[15];
441 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
442 socket_wrapper_dir());
443 /* the caller need to do more processing */
447 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
448 socket_wrapper_dir(), type
, iface
, prt
);
453 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
462 if (bcast
) *bcast
= 0;
464 switch (si
->family
) {
466 const struct sockaddr_in
*in
=
467 (const struct sockaddr_in
*)(const void *)inaddr
;
468 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
474 prt
= ntohs(in
->sin_port
);
478 u_type
= SOCKET_TYPE_CHAR_TCP
;
479 d_type
= SOCKET_TYPE_CHAR_TCP
;
482 u_type
= SOCKET_TYPE_CHAR_UDP
;
483 d_type
= SOCKET_TYPE_CHAR_UDP
;
484 a_type
= SOCKET_TYPE_CHAR_UDP
;
485 b_type
= SOCKET_TYPE_CHAR_UDP
;
493 iface
= socket_wrapper_default_iface();
494 } else if (a_type
&& addr
== 0xFFFFFFFF) {
495 /* 255.255.255.255 only udp */
498 iface
= socket_wrapper_default_iface();
499 } else if (b_type
&& addr
== 0x7FFFFFFF) {
500 /* 127.255.255.255 only udp */
503 iface
= socket_wrapper_default_iface();
504 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
508 iface
= (addr
& 0x000000FF);
510 errno
= EADDRNOTAVAIL
;
517 const struct sockaddr_in6
*in
=
518 (const struct sockaddr_in6
*)(const void *)inaddr
;
519 struct in6_addr cmp1
, cmp2
;
523 type
= SOCKET_TYPE_CHAR_TCP_V6
;
526 type
= SOCKET_TYPE_CHAR_UDP_V6
;
530 /* XXX no multicast/broadcast */
532 prt
= ntohs(in
->sin6_port
);
534 cmp1
= *swrap_ipv6();
535 cmp2
= in
->sin6_addr
;
536 cmp2
.s6_addr
[15] = 0;
537 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
538 iface
= socket_wrapper_default_iface();
539 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
540 iface
= in
->sin6_addr
.s6_addr
[15];
542 errno
= EADDRNOTAVAIL
;
550 errno
= EADDRNOTAVAIL
;
555 if (bcast
) *bcast
= is_bcast
;
557 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
563 /* handle auto-allocation of ephemeral ports */
564 for (prt
= 5001; prt
< 10000; prt
++) {
565 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
566 socket_wrapper_dir(), type
, iface
, prt
);
567 if (stat(un
->sun_path
, &st
) == 0) continue;
569 set_port(si
->family
, prt
, si
->myname
);
578 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
579 socket_wrapper_dir(), type
, iface
, prt
);
583 static struct socket_info
*find_socket_info(int fd
)
585 struct socket_info
*i
;
586 for (i
= sockets
; i
; i
= i
->next
) {
594 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
595 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
597 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
601 out
->sa_family
= AF_UNIX
;
602 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
603 out
->sa_len
= sizeof(*out_addr
);
606 switch (in_addr
->sa_family
) {
616 errno
= ESOCKTNOSUPPORT
;
620 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
622 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
628 errno
= EAFNOSUPPORT
;
632 static int sockaddr_convert_from_un(const struct socket_info
*si
,
633 const struct sockaddr_un
*in_addr
,
634 socklen_t un_addrlen
,
636 struct sockaddr
*out_addr
,
637 socklen_t
*out_addrlen
)
641 if (out_addr
== NULL
|| out_addrlen
== NULL
)
644 if (un_addrlen
== 0) {
659 errno
= ESOCKTNOSUPPORT
;
662 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
663 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
664 out_addr
->sa_len
= *out_addrlen
;
671 errno
= EAFNOSUPPORT
;
675 enum swrap_packet_type
{
677 SWRAP_CONNECT_UNREACH
,
685 SWRAP_SENDTO_UNREACH
,
696 struct swrap_file_hdr
{
698 uint16_t version_major
;
699 uint16_t version_minor
;
702 uint32_t frame_max_len
;
703 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
706 #define SWRAP_FILE_HDR_SIZE 24
708 struct swrap_packet_frame
{
710 uint32_t micro_seconds
;
711 uint32_t recorded_length
;
712 uint32_t full_length
;
714 #define SWRAP_PACKET_FRAME_SIZE 16
716 union swrap_packet_ip
{
720 uint16_t packet_length
;
721 uint16_t identification
;
726 uint16_t hdr_checksum
;
730 #define SWRAP_PACKET_IP_V4_SIZE 20
733 uint8_t flow_label_high
;
734 uint16_t flow_label_low
;
735 uint16_t payload_length
;
738 uint8_t src_addr
[16];
739 uint8_t dest_addr
[16];
741 #define SWRAP_PACKET_IP_V6_SIZE 40
743 #define SWRAP_PACKET_IP_SIZE 40
745 union swrap_packet_payload
{
747 uint16_t source_port
;
757 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
759 uint16_t source_port
;
764 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
771 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
778 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
780 #define SWRAP_PACKET_PAYLOAD_SIZE 20
782 #define SWRAP_PACKET_MIN_ALLOC \
783 (SWRAP_PACKET_FRAME_SIZE + \
784 SWRAP_PACKET_IP_SIZE + \
785 SWRAP_PACKET_PAYLOAD_SIZE)
787 static const char *socket_wrapper_pcap_file(void)
789 static int initialized
= 0;
790 static const char *s
= NULL
;
791 static const struct swrap_file_hdr h
;
792 static const struct swrap_packet_frame f
;
793 static const union swrap_packet_ip i
;
794 static const union swrap_packet_payload p
;
796 if (initialized
== 1) {
802 * TODO: don't use the structs use plain buffer offsets
803 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
805 * for now make sure we disable PCAP support
806 * if the struct has alignment!
808 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
811 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
814 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
817 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
820 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
823 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
826 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
829 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
832 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
835 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
839 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
843 if (strncmp(s
, "./", 2) == 0) {
849 static uint8_t *swrap_packet_init(struct timeval
*tval
,
850 const struct sockaddr
*src
,
851 const struct sockaddr
*dest
,
853 const uint8_t *payload
,
855 unsigned long tcp_seqno
,
856 unsigned long tcp_ack
,
857 unsigned char tcp_ctl
,
863 struct swrap_packet_frame
*frame
;
864 union swrap_packet_ip
*ip
;
865 union swrap_packet_payload
*pay
;
868 size_t nonwire_len
= sizeof(*frame
);
869 size_t wire_hdr_len
= 0;
871 size_t ip_hdr_len
= 0;
872 size_t icmp_hdr_len
= 0;
873 size_t icmp_truncate_len
= 0;
874 uint8_t protocol
= 0, icmp_protocol
= 0;
875 const struct sockaddr_in
*src_in
= NULL
;
876 const struct sockaddr_in
*dest_in
= NULL
;
878 const struct sockaddr_in6
*src_in6
= NULL
;
879 const struct sockaddr_in6
*dest_in6
= NULL
;
884 switch (src
->sa_family
) {
886 src_in
= (const struct sockaddr_in
*)src
;
887 dest_in
= (const struct sockaddr_in
*)dest
;
888 src_port
= src_in
->sin_port
;
889 dest_port
= dest_in
->sin_port
;
890 ip_hdr_len
= sizeof(ip
->v4
);
894 src_in6
= (const struct sockaddr_in6
*)src
;
895 dest_in6
= (const struct sockaddr_in6
*)dest
;
896 src_port
= src_in6
->sin6_port
;
897 dest_port
= dest_in6
->sin6_port
;
898 ip_hdr_len
= sizeof(ip
->v6
);
905 switch (socket_type
) {
907 protocol
= 0x06; /* TCP */
908 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
909 wire_len
= wire_hdr_len
+ payload_len
;
913 protocol
= 0x11; /* UDP */
914 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
915 wire_len
= wire_hdr_len
+ payload_len
;
923 icmp_protocol
= protocol
;
924 switch (src
->sa_family
) {
926 protocol
= 0x01; /* ICMPv4 */
927 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
931 protocol
= 0x3A; /* ICMPv6 */
932 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
936 if (wire_len
> 64 ) {
937 icmp_truncate_len
= wire_len
- 64;
939 wire_hdr_len
+= icmp_hdr_len
;
940 wire_len
+= icmp_hdr_len
;
943 packet_len
= nonwire_len
+ wire_len
;
944 alloc_len
= packet_len
;
945 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
946 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
949 base
= (uint8_t *)malloc(alloc_len
);
950 if (!base
) return NULL
;
954 frame
= (struct swrap_packet_frame
*)buf
;
955 frame
->seconds
= tval
->tv_sec
;
956 frame
->micro_seconds
= tval
->tv_usec
;
957 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
958 frame
->full_length
= wire_len
- icmp_truncate_len
;
959 buf
+= SWRAP_PACKET_FRAME_SIZE
;
961 ip
= (union swrap_packet_ip
*)buf
;
962 switch (src
->sa_family
) {
964 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
966 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
967 ip
->v4
.identification
= htons(0xFFFF);
968 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
969 ip
->v4
.fragment
= htons(0x0000);
971 ip
->v4
.protocol
= protocol
;
972 ip
->v4
.hdr_checksum
= htons(0x0000);
973 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
974 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
975 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
979 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
980 ip
->v6
.flow_label_high
= 0x00;
981 ip
->v6
.flow_label_low
= 0x0000;
982 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
983 ip
->v6
.next_header
= protocol
;
984 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
985 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
986 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
992 pay
= (union swrap_packet_payload
*)buf
;
993 switch (src
->sa_family
) {
995 pay
->icmp4
.type
= 0x03; /* destination unreachable */
996 pay
->icmp4
.code
= 0x01; /* host unreachable */
997 pay
->icmp4
.checksum
= htons(0x0000);
998 pay
->icmp4
.unused
= htonl(0x00000000);
999 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1001 /* set the ip header in the ICMP payload */
1002 ip
= (union swrap_packet_ip
*)buf
;
1003 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1005 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1006 ip
->v4
.identification
= htons(0xFFFF);
1007 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
1008 ip
->v4
.fragment
= htons(0x0000);
1010 ip
->v4
.protocol
= icmp_protocol
;
1011 ip
->v4
.hdr_checksum
= htons(0x0000);
1012 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1013 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1014 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1016 src_port
= dest_in
->sin_port
;
1017 dest_port
= src_in
->sin_port
;
1021 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1022 pay
->icmp6
.code
= 0x03; /* address unreachable */
1023 pay
->icmp6
.checksum
= htons(0x0000);
1024 pay
->icmp6
.unused
= htonl(0x00000000);
1025 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1027 /* set the ip header in the ICMP payload */
1028 ip
= (union swrap_packet_ip
*)buf
;
1029 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1030 ip
->v6
.flow_label_high
= 0x00;
1031 ip
->v6
.flow_label_low
= 0x0000;
1032 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1033 ip
->v6
.next_header
= protocol
;
1034 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1035 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1036 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1038 src_port
= dest_in6
->sin6_port
;
1039 dest_port
= src_in6
->sin6_port
;
1045 pay
= (union swrap_packet_payload
*)buf
;
1047 switch (socket_type
) {
1049 pay
->tcp
.source_port
= src_port
;
1050 pay
->tcp
.dest_port
= dest_port
;
1051 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1052 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1053 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1054 pay
->tcp
.control
= tcp_ctl
;
1055 pay
->tcp
.window
= htons(0x7FFF);
1056 pay
->tcp
.checksum
= htons(0x0000);
1057 pay
->tcp
.urg
= htons(0x0000);
1058 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1063 pay
->udp
.source_port
= src_port
;
1064 pay
->udp
.dest_port
= dest_port
;
1065 pay
->udp
.length
= htons(8 + payload_len
);
1066 pay
->udp
.checksum
= htons(0x0000);
1067 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1072 if (payload
&& payload_len
> 0) {
1073 memcpy(buf
, payload
, payload_len
);
1076 *_packet_len
= packet_len
- icmp_truncate_len
;
1080 static int swrap_get_pcap_fd(const char *fname
)
1084 if (fd
!= -1) return fd
;
1086 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1088 struct swrap_file_hdr file_hdr
;
1089 file_hdr
.magic
= 0xA1B2C3D4;
1090 file_hdr
.version_major
= 0x0002;
1091 file_hdr
.version_minor
= 0x0004;
1092 file_hdr
.timezone
= 0x00000000;
1093 file_hdr
.sigfigs
= 0x00000000;
1094 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1095 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1097 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1104 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1109 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1110 const struct sockaddr
*addr
,
1111 enum swrap_packet_type type
,
1112 const void *buf
, size_t len
,
1115 const struct sockaddr
*src_addr
;
1116 const struct sockaddr
*dest_addr
;
1117 unsigned long tcp_seqno
= 0;
1118 unsigned long tcp_ack
= 0;
1119 unsigned char tcp_ctl
= 0;
1120 int unreachable
= 0;
1124 switch (si
->family
) {
1136 case SWRAP_CONNECT_SEND
:
1137 if (si
->type
!= SOCK_STREAM
) return NULL
;
1139 src_addr
= si
->myname
;
1142 tcp_seqno
= si
->io
.pck_snd
;
1143 tcp_ack
= si
->io
.pck_rcv
;
1144 tcp_ctl
= 0x02; /* SYN */
1146 si
->io
.pck_snd
+= 1;
1150 case SWRAP_CONNECT_RECV
:
1151 if (si
->type
!= SOCK_STREAM
) return NULL
;
1153 dest_addr
= si
->myname
;
1156 tcp_seqno
= si
->io
.pck_rcv
;
1157 tcp_ack
= si
->io
.pck_snd
;
1158 tcp_ctl
= 0x12; /** SYN,ACK */
1160 si
->io
.pck_rcv
+= 1;
1164 case SWRAP_CONNECT_UNREACH
:
1165 if (si
->type
!= SOCK_STREAM
) return NULL
;
1167 dest_addr
= si
->myname
;
1170 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1171 tcp_seqno
= si
->io
.pck_snd
- 1;
1172 tcp_ack
= si
->io
.pck_rcv
;
1173 tcp_ctl
= 0x02; /* SYN */
1178 case SWRAP_CONNECT_ACK
:
1179 if (si
->type
!= SOCK_STREAM
) return NULL
;
1181 src_addr
= si
->myname
;
1184 tcp_seqno
= si
->io
.pck_snd
;
1185 tcp_ack
= si
->io
.pck_rcv
;
1186 tcp_ctl
= 0x10; /* ACK */
1190 case SWRAP_ACCEPT_SEND
:
1191 if (si
->type
!= SOCK_STREAM
) return NULL
;
1193 dest_addr
= si
->myname
;
1196 tcp_seqno
= si
->io
.pck_rcv
;
1197 tcp_ack
= si
->io
.pck_snd
;
1198 tcp_ctl
= 0x02; /* SYN */
1200 si
->io
.pck_rcv
+= 1;
1204 case SWRAP_ACCEPT_RECV
:
1205 if (si
->type
!= SOCK_STREAM
) return NULL
;
1207 src_addr
= si
->myname
;
1210 tcp_seqno
= si
->io
.pck_snd
;
1211 tcp_ack
= si
->io
.pck_rcv
;
1212 tcp_ctl
= 0x12; /* SYN,ACK */
1214 si
->io
.pck_snd
+= 1;
1218 case SWRAP_ACCEPT_ACK
:
1219 if (si
->type
!= SOCK_STREAM
) return NULL
;
1221 dest_addr
= si
->myname
;
1224 tcp_seqno
= si
->io
.pck_rcv
;
1225 tcp_ack
= si
->io
.pck_snd
;
1226 tcp_ctl
= 0x10; /* ACK */
1231 src_addr
= si
->myname
;
1232 dest_addr
= si
->peername
;
1234 tcp_seqno
= si
->io
.pck_snd
;
1235 tcp_ack
= si
->io
.pck_rcv
;
1236 tcp_ctl
= 0x18; /* PSH,ACK */
1238 si
->io
.pck_snd
+= len
;
1242 case SWRAP_SEND_RST
:
1243 dest_addr
= si
->myname
;
1244 src_addr
= si
->peername
;
1246 if (si
->type
== SOCK_DGRAM
) {
1247 return swrap_marshall_packet(si
, si
->peername
,
1248 SWRAP_SENDTO_UNREACH
,
1249 buf
, len
, packet_len
);
1252 tcp_seqno
= si
->io
.pck_rcv
;
1253 tcp_ack
= si
->io
.pck_snd
;
1254 tcp_ctl
= 0x14; /** RST,ACK */
1258 case SWRAP_PENDING_RST
:
1259 dest_addr
= si
->myname
;
1260 src_addr
= si
->peername
;
1262 if (si
->type
== SOCK_DGRAM
) {
1266 tcp_seqno
= si
->io
.pck_rcv
;
1267 tcp_ack
= si
->io
.pck_snd
;
1268 tcp_ctl
= 0x14; /* RST,ACK */
1273 dest_addr
= si
->myname
;
1274 src_addr
= si
->peername
;
1276 tcp_seqno
= si
->io
.pck_rcv
;
1277 tcp_ack
= si
->io
.pck_snd
;
1278 tcp_ctl
= 0x18; /* PSH,ACK */
1280 si
->io
.pck_rcv
+= len
;
1284 case SWRAP_RECV_RST
:
1285 dest_addr
= si
->myname
;
1286 src_addr
= si
->peername
;
1288 if (si
->type
== SOCK_DGRAM
) {
1292 tcp_seqno
= si
->io
.pck_rcv
;
1293 tcp_ack
= si
->io
.pck_snd
;
1294 tcp_ctl
= 0x14; /* RST,ACK */
1299 src_addr
= si
->myname
;
1302 si
->io
.pck_snd
+= len
;
1306 case SWRAP_SENDTO_UNREACH
:
1307 dest_addr
= si
->myname
;
1314 case SWRAP_RECVFROM
:
1315 dest_addr
= si
->myname
;
1318 si
->io
.pck_rcv
+= len
;
1322 case SWRAP_CLOSE_SEND
:
1323 if (si
->type
!= SOCK_STREAM
) return NULL
;
1325 src_addr
= si
->myname
;
1326 dest_addr
= si
->peername
;
1328 tcp_seqno
= si
->io
.pck_snd
;
1329 tcp_ack
= si
->io
.pck_rcv
;
1330 tcp_ctl
= 0x11; /* FIN, ACK */
1332 si
->io
.pck_snd
+= 1;
1336 case SWRAP_CLOSE_RECV
:
1337 if (si
->type
!= SOCK_STREAM
) return NULL
;
1339 dest_addr
= si
->myname
;
1340 src_addr
= si
->peername
;
1342 tcp_seqno
= si
->io
.pck_rcv
;
1343 tcp_ack
= si
->io
.pck_snd
;
1344 tcp_ctl
= 0x11; /* FIN,ACK */
1346 si
->io
.pck_rcv
+= 1;
1350 case SWRAP_CLOSE_ACK
:
1351 if (si
->type
!= SOCK_STREAM
) return NULL
;
1353 src_addr
= si
->myname
;
1354 dest_addr
= si
->peername
;
1356 tcp_seqno
= si
->io
.pck_snd
;
1357 tcp_ack
= si
->io
.pck_rcv
;
1358 tcp_ctl
= 0x10; /* ACK */
1365 swrapGetTimeOfDay(&tv
);
1367 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1368 (const uint8_t *)buf
, len
,
1369 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1373 static void swrap_dump_packet(struct socket_info
*si
,
1374 const struct sockaddr
*addr
,
1375 enum swrap_packet_type type
,
1376 const void *buf
, size_t len
)
1378 const char *file_name
;
1380 size_t packet_len
= 0;
1383 file_name
= socket_wrapper_pcap_file();
1388 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1393 fd
= swrap_get_pcap_fd(file_name
);
1395 if (write(fd
, packet
, packet_len
) != packet_len
) {
1404 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1406 struct socket_info
*si
;
1408 int real_type
= type
;
1410 real_type
&= ~SOCK_CLOEXEC
;
1412 #ifdef SOCK_NONBLOCK
1413 real_type
&= ~SOCK_NONBLOCK
;
1416 if (!socket_wrapper_dir()) {
1417 return real_socket(family
, type
, protocol
);
1427 return real_socket(family
, type
, protocol
);
1429 errno
= EAFNOSUPPORT
;
1433 switch (real_type
) {
1439 errno
= EPROTONOSUPPORT
;
1447 if (real_type
== SOCK_STREAM
) {
1452 if (real_type
== SOCK_DGRAM
) {
1457 errno
= EPROTONOSUPPORT
;
1461 /* We must call real_socket with type, from the caller, not the version we removed
1462 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1463 fd
= real_socket(AF_UNIX
, type
, 0);
1465 if (fd
== -1) return -1;
1467 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1469 si
->family
= family
;
1471 /* however, the rest of the socket_wrapper code expects just
1472 * the type, not the flags */
1473 si
->type
= real_type
;
1474 si
->protocol
= protocol
;
1477 SWRAP_DLIST_ADD(sockets
, si
);
1482 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1484 struct socket_info
*parent_si
, *child_si
;
1486 struct sockaddr_un un_addr
;
1487 socklen_t un_addrlen
= sizeof(un_addr
);
1488 struct sockaddr_un un_my_addr
;
1489 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1490 struct sockaddr
*my_addr
;
1491 socklen_t my_addrlen
, len
;
1494 parent_si
= find_socket_info(s
);
1496 return real_accept(s
, addr
, addrlen
);
1500 * assume out sockaddr have the same size as the in parent
1503 my_addrlen
= socket_length(parent_si
->family
);
1504 if (my_addrlen
<= 0) {
1509 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1510 if (my_addr
== NULL
) {
1514 memset(&un_addr
, 0, sizeof(un_addr
));
1515 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1517 ret
= real_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
1526 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1527 parent_si
->family
, my_addr
, &len
);
1534 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1535 memset(child_si
, 0, sizeof(*child_si
));
1538 child_si
->family
= parent_si
->family
;
1539 child_si
->type
= parent_si
->type
;
1540 child_si
->protocol
= parent_si
->protocol
;
1541 child_si
->bound
= 1;
1542 child_si
->is_server
= 1;
1543 child_si
->connected
= 1;
1545 child_si
->peername_len
= len
;
1546 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1548 if (addr
!= NULL
&& addrlen
!= NULL
) {
1549 size_t copy_len
= MIN(*addrlen
, len
);
1551 memcpy(addr
, my_addr
, copy_len
);
1556 ret
= real_getsockname(fd
, (struct sockaddr
*)(void *)&un_my_addr
,
1565 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1566 child_si
->family
, my_addr
, &len
);
1574 child_si
->myname_len
= len
;
1575 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1578 SWRAP_DLIST_ADD(sockets
, child_si
);
1580 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1581 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1582 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1587 static int autobind_start_init
;
1588 static int autobind_start
;
1590 /* using sendto() or connect() on an unbound socket would give the
1591 recipient no way to reply, as unlike UDP and TCP, a unix domain
1592 socket can't auto-assign emphemeral port numbers, so we need to
1594 Note: this might change the family from ipv6 to ipv4
1596 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1598 struct sockaddr_un un_addr
;
1605 if (autobind_start_init
!= 1) {
1606 autobind_start_init
= 1;
1607 autobind_start
= getpid();
1608 autobind_start
%= 50000;
1609 autobind_start
+= 10000;
1612 un_addr
.sun_family
= AF_UNIX
;
1616 struct sockaddr_in in
;
1620 type
= SOCKET_TYPE_CHAR_TCP
;
1623 type
= SOCKET_TYPE_CHAR_UDP
;
1626 errno
= ESOCKTNOSUPPORT
;
1630 memset(&in
, 0, sizeof(in
));
1631 in
.sin_family
= AF_INET
;
1632 in
.sin_addr
.s_addr
= htonl(127<<24 |
1633 socket_wrapper_default_iface());
1635 si
->myname_len
= sizeof(in
);
1636 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1641 struct sockaddr_in6 in6
;
1643 if (si
->family
!= family
) {
1644 errno
= ENETUNREACH
;
1650 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1653 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1656 errno
= ESOCKTNOSUPPORT
;
1660 memset(&in6
, 0, sizeof(in6
));
1661 in6
.sin6_family
= AF_INET6
;
1662 in6
.sin6_addr
= *swrap_ipv6();
1663 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1664 si
->myname_len
= sizeof(in6
);
1665 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1670 errno
= ESOCKTNOSUPPORT
;
1674 if (autobind_start
> 60000) {
1675 autobind_start
= 10000;
1678 for (i
=0;i
<1000;i
++) {
1679 port
= autobind_start
+ i
;
1680 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1681 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1682 type
, socket_wrapper_default_iface(), port
);
1683 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1685 ret
= real_bind(si
->fd
, (struct sockaddr
*)(void *)&un_addr
,
1687 if (ret
== -1) return ret
;
1689 si
->tmp_path
= strdup(un_addr
.sun_path
);
1691 autobind_start
= port
+ 1;
1699 si
->family
= family
;
1700 set_port(si
->family
, port
, si
->myname
);
1706 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1709 struct sockaddr_un un_addr
;
1710 struct socket_info
*si
= find_socket_info(s
);
1714 return real_connect(s
, serv_addr
, addrlen
);
1717 if (si
->bound
== 0) {
1718 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1719 if (ret
== -1) return -1;
1722 if (si
->family
!= serv_addr
->sa_family
) {
1727 ret
= sockaddr_convert_to_un(si
, serv_addr
,
1728 addrlen
, &un_addr
, 0, &bcast
);
1729 if (ret
== -1) return -1;
1732 errno
= ENETUNREACH
;
1736 if (si
->type
== SOCK_DGRAM
) {
1737 si
->defer_connect
= 1;
1740 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1742 ret
= real_connect(s
, (struct sockaddr
*)(void *)&un_addr
,
1743 sizeof(struct sockaddr_un
));
1746 /* to give better errors */
1747 if (ret
== -1 && errno
== ENOENT
) {
1748 errno
= EHOSTUNREACH
;
1752 si
->peername_len
= addrlen
;
1753 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1756 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1757 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1759 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1765 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1768 struct sockaddr_un un_addr
;
1769 struct socket_info
*si
= find_socket_info(s
);
1772 return real_bind(s
, myaddr
, addrlen
);
1775 si
->myname_len
= addrlen
;
1776 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1778 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1779 if (ret
== -1) return -1;
1781 unlink(un_addr
.sun_path
);
1783 ret
= real_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
1784 sizeof(struct sockaddr_un
));
1793 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1796 struct socket_info
*si
= find_socket_info(s
);
1799 return real_listen(s
, backlog
);
1802 ret
= real_listen(s
, backlog
);
1807 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1809 struct socket_info
*si
= find_socket_info(s
);
1812 return real_getpeername(s
, name
, addrlen
);
1821 memcpy(name
, si
->peername
, si
->peername_len
);
1822 *addrlen
= si
->peername_len
;
1827 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1829 struct socket_info
*si
= find_socket_info(s
);
1832 return real_getsockname(s
, name
, addrlen
);
1835 memcpy(name
, si
->myname
, si
->myname_len
);
1836 *addrlen
= si
->myname_len
;
1841 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1843 struct socket_info
*si
= find_socket_info(s
);
1846 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1849 if (level
== SOL_SOCKET
) {
1850 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1853 errno
= ENOPROTOOPT
;
1857 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1859 struct socket_info
*si
= find_socket_info(s
);
1862 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1865 if (level
== SOL_SOCKET
) {
1866 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1869 switch (si
->family
) {
1877 errno
= ENOPROTOOPT
;
1882 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1885 struct socket_info
*si
= find_socket_info(s
);
1889 return real_ioctl(s
, r
, p
);
1892 ret
= real_ioctl(s
, r
, p
);
1896 value
= *((int *)p
);
1897 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1898 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1899 } else if (value
== 0) { /* END OF FILE */
1900 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1908 static ssize_t
swrap_sendmsg_before(struct socket_info
*si
,
1910 struct iovec
*tmp_iov
,
1911 struct sockaddr_un
*tmp_un
,
1912 const struct sockaddr_un
**to_un
,
1913 const struct sockaddr
**to
,
1931 if (!si
->connected
) {
1936 if (msg
->msg_iovlen
== 0) {
1941 * cut down to 1500 byte packets for stream sockets,
1942 * which makes it easier to format PCAP capture files
1943 * (as the caller will simply continue from here)
1946 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
1948 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
1953 msg
->msg_iovlen
= i
;
1954 if (msg
->msg_iovlen
== 0) {
1955 *tmp_iov
= msg
->msg_iov
[0];
1956 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, 1500);
1957 msg
->msg_iov
= tmp_iov
;
1958 msg
->msg_iovlen
= 1;
1963 if (si
->connected
) {
1964 if (msg
->msg_name
) {
1969 const struct sockaddr
*msg_name
;
1970 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
1972 if (msg_name
== NULL
) {
1978 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
1980 if (ret
== -1) return -1;
1988 msg
->msg_name
= tmp_un
;
1989 msg
->msg_namelen
= sizeof(*tmp_un
);
1992 if (si
->bound
== 0) {
1993 ret
= swrap_auto_bind(si
, si
->family
);
1994 if (ret
== -1) return -1;
1997 if (!si
->defer_connect
) {
2001 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2003 if (ret
== -1) return -1;
2005 ret
= real_connect(si
->fd
, (struct sockaddr
*)(void *)tmp_un
,
2008 /* to give better errors */
2009 if (ret
== -1 && errno
== ENOENT
) {
2010 errno
= EHOSTUNREACH
;
2017 si
->defer_connect
= 0;
2020 errno
= EHOSTUNREACH
;
2027 static void swrap_sendmsg_after(struct socket_info
*si
,
2029 const struct sockaddr
*to
,
2032 int saved_errno
= errno
;
2039 /* to give better errors */
2040 if (ret
== -1 && saved_errno
== ENOENT
) {
2041 saved_errno
= EHOSTUNREACH
;
2044 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2045 avail
+= msg
->msg_iov
[i
].iov_len
;
2049 remain
= MIN(80, avail
);
2054 /* we capture it as one single packet */
2055 buf
= (uint8_t *)malloc(remain
);
2057 /* we just not capture the packet */
2058 errno
= saved_errno
;
2062 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2063 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2065 msg
->msg_iov
[i
].iov_base
,
2068 remain
-= this_time
;
2075 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2076 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2078 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2083 if (si
->connected
) {
2087 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2088 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
2090 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2096 errno
= saved_errno
;
2099 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
2101 struct sockaddr_un un_addr
;
2102 socklen_t un_addrlen
= sizeof(un_addr
);
2104 struct socket_info
*si
= find_socket_info(s
);
2105 struct sockaddr_storage ss
;
2106 socklen_t ss_len
= sizeof(ss
);
2109 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
2113 from
= (struct sockaddr
*)(void *)&ss
;
2117 if (si
->type
== SOCK_STREAM
) {
2118 /* cut down to 1500 byte packets for stream sockets,
2119 * which makes it easier to format PCAP capture files
2120 * (as the caller will simply continue from here) */
2121 len
= MIN(len
, 1500);
2124 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2125 memset(&un_addr
, 0, sizeof(un_addr
));
2126 ret
= real_recvfrom(s
, buf
, len
, flags
,
2127 (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2131 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
2132 si
->family
, from
, fromlen
) == -1) {
2136 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
2142 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
2146 struct sockaddr_un un_addr
;
2147 const struct sockaddr_un
*to_un
= NULL
;
2149 struct socket_info
*si
= find_socket_info(s
);
2153 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
2156 tmp
.iov_base
= discard_const_p(char, buf
);
2160 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
2161 msg
.msg_namelen
= tolen
; /* size of address */
2162 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2163 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2164 #if 0 /* not available on solaris */
2165 msg
.msg_control
= NULL
; /* ancillary data, see below */
2166 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2167 msg
.msg_flags
= 0; /* flags on received message */
2170 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2171 if (ret
== -1) return -1;
2173 buf
= msg
.msg_iov
[0].iov_base
;
2174 len
= msg
.msg_iov
[0].iov_len
;
2179 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2182 type
= SOCKET_TYPE_CHAR_UDP
;
2184 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2185 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2186 socket_wrapper_dir(), type
, iface
, prt
);
2187 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2189 /* ignore the any errors in broadcast sends */
2190 real_sendto(s
, buf
, len
, flags
,
2191 (struct sockaddr
*)(void *)&un_addr
,
2195 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2200 ret
= real_sendto(s
, buf
, len
, flags
, msg
.msg_name
, msg
.msg_namelen
);
2202 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2207 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2210 struct socket_info
*si
= find_socket_info(s
);
2213 return real_recv(s
, buf
, len
, flags
);
2216 if (si
->type
== SOCK_STREAM
) {
2217 /* cut down to 1500 byte packets for stream sockets,
2218 * which makes it easier to format PCAP capture files
2219 * (as the caller will simply continue from here) */
2220 len
= MIN(len
, 1500);
2223 ret
= real_recv(s
, buf
, len
, flags
);
2224 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2225 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2226 } else if (ret
== 0) { /* END OF FILE */
2227 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2228 } else if (ret
> 0) {
2229 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2235 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2238 struct socket_info
*si
= find_socket_info(s
);
2241 return real_read(s
, buf
, len
);
2244 if (si
->type
== SOCK_STREAM
) {
2245 /* cut down to 1500 byte packets for stream sockets,
2246 * which makes it easier to format PCAP capture files
2247 * (as the caller will simply continue from here) */
2248 len
= MIN(len
, 1500);
2251 ret
= real_read(s
, buf
, len
);
2252 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2253 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2254 } else if (ret
== 0) { /* END OF FILE */
2255 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2256 } else if (ret
> 0) {
2257 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2264 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2268 struct sockaddr_un un_addr
;
2270 struct socket_info
*si
= find_socket_info(s
);
2273 return real_send(s
, buf
, len
, flags
);
2276 tmp
.iov_base
= discard_const_p(char, buf
);
2280 msg
.msg_name
= NULL
; /* optional address */
2281 msg
.msg_namelen
= 0; /* size of address */
2282 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2283 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2284 #if 0 /* not available on solaris */
2285 msg
.msg_control
= NULL
; /* ancillary data, see below */
2286 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2287 msg
.msg_flags
= 0; /* flags on received message */
2290 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2291 if (ret
== -1) return -1;
2293 buf
= msg
.msg_iov
[0].iov_base
;
2294 len
= msg
.msg_iov
[0].iov_len
;
2296 ret
= real_send(s
, buf
, len
, flags
);
2298 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2303 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
2307 struct sockaddr_un un_addr
;
2308 const struct sockaddr_un
*to_un
= NULL
;
2309 const struct sockaddr
*to
= NULL
;
2311 struct socket_info
*si
= find_socket_info(s
);
2315 return real_sendmsg(s
, omsg
, flags
);
2318 tmp
.iov_base
= NULL
;
2323 msg
.msg_name
= omsg
->msg_name
; /* optional address */
2324 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
2325 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
2326 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
2327 /* the following is not available on solaris */
2328 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
2329 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
2330 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
2333 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2334 if (ret
== -1) return -1;
2339 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2347 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2348 avail
+= msg
.msg_iov
[i
].iov_len
;
2354 /* we capture it as one single packet */
2355 buf
= (uint8_t *)malloc(remain
);
2360 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2361 size_t this_time
= MIN(remain
, msg
.msg_iov
[i
].iov_len
);
2363 msg
.msg_iov
[i
].iov_base
,
2366 remain
-= this_time
;
2369 type
= SOCKET_TYPE_CHAR_UDP
;
2371 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2372 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2373 socket_wrapper_dir(), type
, iface
, prt
);
2374 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2376 msg
.msg_name
= &un_addr
; /* optional address */
2377 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
2379 /* ignore the any errors in broadcast sends */
2380 real_sendmsg(s
, &msg
, flags
);
2383 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2389 ret
= real_sendmsg(s
, &msg
, flags
);
2391 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2396 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2399 struct socket_info
*si
= find_socket_info(s
);
2403 return real_readv(s
, vector
, count
);
2406 if (!si
->connected
) {
2411 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2412 /* cut down to 1500 byte packets for stream sockets,
2413 * which makes it easier to format PCAP capture files
2414 * (as the caller will simply continue from here) */
2417 for (i
=0; i
< count
; i
++) {
2419 nlen
= len
+ vector
[i
].iov_len
;
2427 v
.iov_len
= MIN(v
.iov_len
, 1500);
2433 ret
= real_readv(s
, vector
, count
);
2434 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2435 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2436 } else if (ret
== 0) { /* END OF FILE */
2437 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2438 } else if (ret
> 0) {
2442 size_t remain
= ret
;
2444 /* we capture it as one single packet */
2445 buf
= (uint8_t *)malloc(ret
);
2447 /* we just not capture the packet */
2452 for (i
=0; i
< count
; i
++) {
2453 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2458 remain
-= this_time
;
2461 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2468 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2472 struct sockaddr_un un_addr
;
2474 struct socket_info
*si
= find_socket_info(s
);
2477 return real_writev(s
, vector
, count
);
2480 tmp
.iov_base
= NULL
;
2484 msg
.msg_name
= NULL
; /* optional address */
2485 msg
.msg_namelen
= 0; /* size of address */
2486 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
2487 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
2488 #if 0 /* not available on solaris */
2489 msg
.msg_control
= NULL
; /* ancillary data, see below */
2490 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2491 msg
.msg_flags
= 0; /* flags on received message */
2494 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2495 if (ret
== -1) return -1;
2497 ret
= real_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
2499 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2504 _PUBLIC_
int swrap_close(int fd
)
2506 struct socket_info
*si
= find_socket_info(fd
);
2510 return real_close(fd
);
2513 SWRAP_DLIST_REMOVE(sockets
, si
);
2515 if (si
->myname
&& si
->peername
) {
2516 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2519 ret
= real_close(fd
);
2521 if (si
->myname
&& si
->peername
) {
2522 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2523 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2526 if (si
->path
) free(si
->path
);
2527 if (si
->myname
) free(si
->myname
);
2528 if (si
->peername
) free(si
->peername
);
2530 unlink(si
->tmp_path
);