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
;
558 /* handle auto-allocation of ephemeral ports */
559 for (prt
= 5001; prt
< 10000; prt
++) {
560 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
561 socket_wrapper_dir(), type
, iface
, prt
);
562 if (stat(un
->sun_path
, &st
) == 0) continue;
564 set_port(si
->family
, prt
, si
->myname
);
573 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
574 socket_wrapper_dir(), type
, iface
, prt
);
578 static struct socket_info
*find_socket_info(int fd
)
580 struct socket_info
*i
;
581 for (i
= sockets
; i
; i
= i
->next
) {
589 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
590 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
592 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
596 out
->sa_family
= AF_UNIX
;
597 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
598 out
->sa_len
= sizeof(*out_addr
);
601 switch (in_addr
->sa_family
) {
611 errno
= ESOCKTNOSUPPORT
;
615 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
617 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
623 errno
= EAFNOSUPPORT
;
627 static int sockaddr_convert_from_un(const struct socket_info
*si
,
628 const struct sockaddr_un
*in_addr
,
629 socklen_t un_addrlen
,
631 struct sockaddr
*out_addr
,
632 socklen_t
*out_addrlen
)
636 if (out_addr
== NULL
|| out_addrlen
== NULL
)
639 if (un_addrlen
== 0) {
654 errno
= ESOCKTNOSUPPORT
;
657 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
658 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
659 out_addr
->sa_len
= *out_addrlen
;
666 errno
= EAFNOSUPPORT
;
670 enum swrap_packet_type
{
672 SWRAP_CONNECT_UNREACH
,
680 SWRAP_SENDTO_UNREACH
,
691 struct swrap_file_hdr
{
693 uint16_t version_major
;
694 uint16_t version_minor
;
697 uint32_t frame_max_len
;
698 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
701 #define SWRAP_FILE_HDR_SIZE 24
703 struct swrap_packet_frame
{
705 uint32_t micro_seconds
;
706 uint32_t recorded_length
;
707 uint32_t full_length
;
709 #define SWRAP_PACKET_FRAME_SIZE 16
711 union swrap_packet_ip
{
715 uint16_t packet_length
;
716 uint16_t identification
;
721 uint16_t hdr_checksum
;
725 #define SWRAP_PACKET_IP_V4_SIZE 20
728 uint8_t flow_label_high
;
729 uint16_t flow_label_low
;
730 uint16_t payload_length
;
733 uint8_t src_addr
[16];
734 uint8_t dest_addr
[16];
736 #define SWRAP_PACKET_IP_V6_SIZE 40
738 #define SWRAP_PACKET_IP_SIZE 40
740 union swrap_packet_payload
{
742 uint16_t source_port
;
752 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
754 uint16_t source_port
;
759 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
766 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
773 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
775 #define SWRAP_PACKET_PAYLOAD_SIZE 20
777 #define SWRAP_PACKET_MIN_ALLOC \
778 (SWRAP_PACKET_FRAME_SIZE + \
779 SWRAP_PACKET_IP_SIZE + \
780 SWRAP_PACKET_PAYLOAD_SIZE)
782 static const char *socket_wrapper_pcap_file(void)
784 static int initialized
= 0;
785 static const char *s
= NULL
;
786 static const struct swrap_file_hdr h
;
787 static const struct swrap_packet_frame f
;
788 static const union swrap_packet_ip i
;
789 static const union swrap_packet_payload p
;
791 if (initialized
== 1) {
797 * TODO: don't use the structs use plain buffer offsets
798 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
800 * for now make sure we disable PCAP support
801 * if the struct has alignment!
803 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
806 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
809 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
812 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
815 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
818 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
821 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
824 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
827 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
830 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
834 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
838 if (strncmp(s
, "./", 2) == 0) {
844 static uint8_t *swrap_packet_init(struct timeval
*tval
,
845 const struct sockaddr
*src
,
846 const struct sockaddr
*dest
,
848 const uint8_t *payload
,
850 unsigned long tcp_seqno
,
851 unsigned long tcp_ack
,
852 unsigned char tcp_ctl
,
858 struct swrap_packet_frame
*frame
;
859 union swrap_packet_ip
*ip
;
860 union swrap_packet_payload
*pay
;
863 size_t nonwire_len
= sizeof(*frame
);
864 size_t wire_hdr_len
= 0;
866 size_t ip_hdr_len
= 0;
867 size_t icmp_hdr_len
= 0;
868 size_t icmp_truncate_len
= 0;
869 uint8_t protocol
= 0, icmp_protocol
= 0;
870 const struct sockaddr_in
*src_in
= NULL
;
871 const struct sockaddr_in
*dest_in
= NULL
;
873 const struct sockaddr_in6
*src_in6
= NULL
;
874 const struct sockaddr_in6
*dest_in6
= NULL
;
879 switch (src
->sa_family
) {
881 src_in
= (const struct sockaddr_in
*)src
;
882 dest_in
= (const struct sockaddr_in
*)dest
;
883 src_port
= src_in
->sin_port
;
884 dest_port
= dest_in
->sin_port
;
885 ip_hdr_len
= sizeof(ip
->v4
);
889 src_in6
= (const struct sockaddr_in6
*)src
;
890 dest_in6
= (const struct sockaddr_in6
*)dest
;
891 src_port
= src_in6
->sin6_port
;
892 dest_port
= dest_in6
->sin6_port
;
893 ip_hdr_len
= sizeof(ip
->v6
);
900 switch (socket_type
) {
902 protocol
= 0x06; /* TCP */
903 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
904 wire_len
= wire_hdr_len
+ payload_len
;
908 protocol
= 0x11; /* UDP */
909 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
910 wire_len
= wire_hdr_len
+ payload_len
;
918 icmp_protocol
= protocol
;
919 switch (src
->sa_family
) {
921 protocol
= 0x01; /* ICMPv4 */
922 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
926 protocol
= 0x3A; /* ICMPv6 */
927 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
931 if (wire_len
> 64 ) {
932 icmp_truncate_len
= wire_len
- 64;
934 wire_hdr_len
+= icmp_hdr_len
;
935 wire_len
+= icmp_hdr_len
;
938 packet_len
= nonwire_len
+ wire_len
;
939 alloc_len
= packet_len
;
940 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
941 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
944 base
= (uint8_t *)malloc(alloc_len
);
945 if (!base
) return NULL
;
949 frame
= (struct swrap_packet_frame
*)buf
;
950 frame
->seconds
= tval
->tv_sec
;
951 frame
->micro_seconds
= tval
->tv_usec
;
952 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
953 frame
->full_length
= wire_len
- icmp_truncate_len
;
954 buf
+= SWRAP_PACKET_FRAME_SIZE
;
956 ip
= (union swrap_packet_ip
*)buf
;
957 switch (src
->sa_family
) {
959 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
961 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
962 ip
->v4
.identification
= htons(0xFFFF);
963 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
964 ip
->v4
.fragment
= htons(0x0000);
966 ip
->v4
.protocol
= protocol
;
967 ip
->v4
.hdr_checksum
= htons(0x0000);
968 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
969 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
970 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
974 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
975 ip
->v6
.flow_label_high
= 0x00;
976 ip
->v6
.flow_label_low
= 0x0000;
977 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
978 ip
->v6
.next_header
= protocol
;
979 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
980 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
981 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
987 pay
= (union swrap_packet_payload
*)buf
;
988 switch (src
->sa_family
) {
990 pay
->icmp4
.type
= 0x03; /* destination unreachable */
991 pay
->icmp4
.code
= 0x01; /* host unreachable */
992 pay
->icmp4
.checksum
= htons(0x0000);
993 pay
->icmp4
.unused
= htonl(0x00000000);
994 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
996 /* set the ip header in the ICMP payload */
997 ip
= (union swrap_packet_ip
*)buf
;
998 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1000 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1001 ip
->v4
.identification
= htons(0xFFFF);
1002 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
1003 ip
->v4
.fragment
= htons(0x0000);
1005 ip
->v4
.protocol
= icmp_protocol
;
1006 ip
->v4
.hdr_checksum
= htons(0x0000);
1007 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1008 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1009 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1011 src_port
= dest_in
->sin_port
;
1012 dest_port
= src_in
->sin_port
;
1016 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1017 pay
->icmp6
.code
= 0x03; /* address unreachable */
1018 pay
->icmp6
.checksum
= htons(0x0000);
1019 pay
->icmp6
.unused
= htonl(0x00000000);
1020 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1022 /* set the ip header in the ICMP payload */
1023 ip
= (union swrap_packet_ip
*)buf
;
1024 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1025 ip
->v6
.flow_label_high
= 0x00;
1026 ip
->v6
.flow_label_low
= 0x0000;
1027 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1028 ip
->v6
.next_header
= protocol
;
1029 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1030 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1031 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1033 src_port
= dest_in6
->sin6_port
;
1034 dest_port
= src_in6
->sin6_port
;
1040 pay
= (union swrap_packet_payload
*)buf
;
1042 switch (socket_type
) {
1044 pay
->tcp
.source_port
= src_port
;
1045 pay
->tcp
.dest_port
= dest_port
;
1046 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1047 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1048 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1049 pay
->tcp
.control
= tcp_ctl
;
1050 pay
->tcp
.window
= htons(0x7FFF);
1051 pay
->tcp
.checksum
= htons(0x0000);
1052 pay
->tcp
.urg
= htons(0x0000);
1053 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1058 pay
->udp
.source_port
= src_port
;
1059 pay
->udp
.dest_port
= dest_port
;
1060 pay
->udp
.length
= htons(8 + payload_len
);
1061 pay
->udp
.checksum
= htons(0x0000);
1062 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1067 if (payload
&& payload_len
> 0) {
1068 memcpy(buf
, payload
, payload_len
);
1071 *_packet_len
= packet_len
- icmp_truncate_len
;
1075 static int swrap_get_pcap_fd(const char *fname
)
1079 if (fd
!= -1) return fd
;
1081 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1083 struct swrap_file_hdr file_hdr
;
1084 file_hdr
.magic
= 0xA1B2C3D4;
1085 file_hdr
.version_major
= 0x0002;
1086 file_hdr
.version_minor
= 0x0004;
1087 file_hdr
.timezone
= 0x00000000;
1088 file_hdr
.sigfigs
= 0x00000000;
1089 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1090 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1092 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1099 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1104 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1105 const struct sockaddr
*addr
,
1106 enum swrap_packet_type type
,
1107 const void *buf
, size_t len
,
1110 const struct sockaddr
*src_addr
;
1111 const struct sockaddr
*dest_addr
;
1112 unsigned long tcp_seqno
= 0;
1113 unsigned long tcp_ack
= 0;
1114 unsigned char tcp_ctl
= 0;
1115 int unreachable
= 0;
1119 switch (si
->family
) {
1131 case SWRAP_CONNECT_SEND
:
1132 if (si
->type
!= SOCK_STREAM
) return NULL
;
1134 src_addr
= si
->myname
;
1137 tcp_seqno
= si
->io
.pck_snd
;
1138 tcp_ack
= si
->io
.pck_rcv
;
1139 tcp_ctl
= 0x02; /* SYN */
1141 si
->io
.pck_snd
+= 1;
1145 case SWRAP_CONNECT_RECV
:
1146 if (si
->type
!= SOCK_STREAM
) return NULL
;
1148 dest_addr
= si
->myname
;
1151 tcp_seqno
= si
->io
.pck_rcv
;
1152 tcp_ack
= si
->io
.pck_snd
;
1153 tcp_ctl
= 0x12; /** SYN,ACK */
1155 si
->io
.pck_rcv
+= 1;
1159 case SWRAP_CONNECT_UNREACH
:
1160 if (si
->type
!= SOCK_STREAM
) return NULL
;
1162 dest_addr
= si
->myname
;
1165 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1166 tcp_seqno
= si
->io
.pck_snd
- 1;
1167 tcp_ack
= si
->io
.pck_rcv
;
1168 tcp_ctl
= 0x02; /* SYN */
1173 case SWRAP_CONNECT_ACK
:
1174 if (si
->type
!= SOCK_STREAM
) return NULL
;
1176 src_addr
= si
->myname
;
1179 tcp_seqno
= si
->io
.pck_snd
;
1180 tcp_ack
= si
->io
.pck_rcv
;
1181 tcp_ctl
= 0x10; /* ACK */
1185 case SWRAP_ACCEPT_SEND
:
1186 if (si
->type
!= SOCK_STREAM
) return NULL
;
1188 dest_addr
= si
->myname
;
1191 tcp_seqno
= si
->io
.pck_rcv
;
1192 tcp_ack
= si
->io
.pck_snd
;
1193 tcp_ctl
= 0x02; /* SYN */
1195 si
->io
.pck_rcv
+= 1;
1199 case SWRAP_ACCEPT_RECV
:
1200 if (si
->type
!= SOCK_STREAM
) return NULL
;
1202 src_addr
= si
->myname
;
1205 tcp_seqno
= si
->io
.pck_snd
;
1206 tcp_ack
= si
->io
.pck_rcv
;
1207 tcp_ctl
= 0x12; /* SYN,ACK */
1209 si
->io
.pck_snd
+= 1;
1213 case SWRAP_ACCEPT_ACK
:
1214 if (si
->type
!= SOCK_STREAM
) return NULL
;
1216 dest_addr
= si
->myname
;
1219 tcp_seqno
= si
->io
.pck_rcv
;
1220 tcp_ack
= si
->io
.pck_snd
;
1221 tcp_ctl
= 0x10; /* ACK */
1226 src_addr
= si
->myname
;
1227 dest_addr
= si
->peername
;
1229 tcp_seqno
= si
->io
.pck_snd
;
1230 tcp_ack
= si
->io
.pck_rcv
;
1231 tcp_ctl
= 0x18; /* PSH,ACK */
1233 si
->io
.pck_snd
+= len
;
1237 case SWRAP_SEND_RST
:
1238 dest_addr
= si
->myname
;
1239 src_addr
= si
->peername
;
1241 if (si
->type
== SOCK_DGRAM
) {
1242 return swrap_marshall_packet(si
, si
->peername
,
1243 SWRAP_SENDTO_UNREACH
,
1244 buf
, len
, packet_len
);
1247 tcp_seqno
= si
->io
.pck_rcv
;
1248 tcp_ack
= si
->io
.pck_snd
;
1249 tcp_ctl
= 0x14; /** RST,ACK */
1253 case SWRAP_PENDING_RST
:
1254 dest_addr
= si
->myname
;
1255 src_addr
= si
->peername
;
1257 if (si
->type
== SOCK_DGRAM
) {
1261 tcp_seqno
= si
->io
.pck_rcv
;
1262 tcp_ack
= si
->io
.pck_snd
;
1263 tcp_ctl
= 0x14; /* RST,ACK */
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
= 0x18; /* PSH,ACK */
1275 si
->io
.pck_rcv
+= len
;
1279 case SWRAP_RECV_RST
:
1280 dest_addr
= si
->myname
;
1281 src_addr
= si
->peername
;
1283 if (si
->type
== SOCK_DGRAM
) {
1287 tcp_seqno
= si
->io
.pck_rcv
;
1288 tcp_ack
= si
->io
.pck_snd
;
1289 tcp_ctl
= 0x14; /* RST,ACK */
1294 src_addr
= si
->myname
;
1297 si
->io
.pck_snd
+= len
;
1301 case SWRAP_SENDTO_UNREACH
:
1302 dest_addr
= si
->myname
;
1309 case SWRAP_RECVFROM
:
1310 dest_addr
= si
->myname
;
1313 si
->io
.pck_rcv
+= len
;
1317 case SWRAP_CLOSE_SEND
:
1318 if (si
->type
!= SOCK_STREAM
) return NULL
;
1320 src_addr
= si
->myname
;
1321 dest_addr
= si
->peername
;
1323 tcp_seqno
= si
->io
.pck_snd
;
1324 tcp_ack
= si
->io
.pck_rcv
;
1325 tcp_ctl
= 0x11; /* FIN, ACK */
1327 si
->io
.pck_snd
+= 1;
1331 case SWRAP_CLOSE_RECV
:
1332 if (si
->type
!= SOCK_STREAM
) return NULL
;
1334 dest_addr
= si
->myname
;
1335 src_addr
= si
->peername
;
1337 tcp_seqno
= si
->io
.pck_rcv
;
1338 tcp_ack
= si
->io
.pck_snd
;
1339 tcp_ctl
= 0x11; /* FIN,ACK */
1341 si
->io
.pck_rcv
+= 1;
1345 case SWRAP_CLOSE_ACK
:
1346 if (si
->type
!= SOCK_STREAM
) return NULL
;
1348 src_addr
= si
->myname
;
1349 dest_addr
= si
->peername
;
1351 tcp_seqno
= si
->io
.pck_snd
;
1352 tcp_ack
= si
->io
.pck_rcv
;
1353 tcp_ctl
= 0x10; /* ACK */
1360 swrapGetTimeOfDay(&tv
);
1362 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1363 (const uint8_t *)buf
, len
,
1364 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1368 static void swrap_dump_packet(struct socket_info
*si
,
1369 const struct sockaddr
*addr
,
1370 enum swrap_packet_type type
,
1371 const void *buf
, size_t len
)
1373 const char *file_name
;
1375 size_t packet_len
= 0;
1378 file_name
= socket_wrapper_pcap_file();
1383 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1388 fd
= swrap_get_pcap_fd(file_name
);
1390 if (write(fd
, packet
, packet_len
) != packet_len
) {
1399 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1401 struct socket_info
*si
;
1403 int real_type
= type
;
1405 real_type
&= ~SOCK_CLOEXEC
;
1407 #ifdef SOCK_NONBLOCK
1408 real_type
&= ~SOCK_NONBLOCK
;
1411 if (!socket_wrapper_dir()) {
1412 return real_socket(family
, type
, protocol
);
1422 return real_socket(family
, type
, protocol
);
1424 errno
= EAFNOSUPPORT
;
1428 switch (real_type
) {
1434 errno
= EPROTONOSUPPORT
;
1442 if (real_type
== SOCK_STREAM
) {
1447 if (real_type
== SOCK_DGRAM
) {
1452 errno
= EPROTONOSUPPORT
;
1456 /* We must call real_socket with type, from the caller, not the version we removed
1457 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1458 fd
= real_socket(AF_UNIX
, type
, 0);
1460 if (fd
== -1) return -1;
1462 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1464 si
->family
= family
;
1466 /* however, the rest of the socket_wrapper code expects just
1467 * the type, not the flags */
1468 si
->type
= real_type
;
1469 si
->protocol
= protocol
;
1472 SWRAP_DLIST_ADD(sockets
, si
);
1477 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1479 struct socket_info
*parent_si
, *child_si
;
1481 struct sockaddr_un un_addr
;
1482 socklen_t un_addrlen
= sizeof(un_addr
);
1483 struct sockaddr_un un_my_addr
;
1484 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1485 struct sockaddr
*my_addr
;
1486 socklen_t my_addrlen
, len
;
1489 parent_si
= find_socket_info(s
);
1491 return real_accept(s
, addr
, addrlen
);
1495 * assume out sockaddr have the same size as the in parent
1498 my_addrlen
= socket_length(parent_si
->family
);
1499 if (my_addrlen
<= 0) {
1504 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1505 if (my_addr
== NULL
) {
1509 memset(&un_addr
, 0, sizeof(un_addr
));
1510 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1512 ret
= real_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
1521 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1522 parent_si
->family
, my_addr
, &len
);
1529 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1530 memset(child_si
, 0, sizeof(*child_si
));
1533 child_si
->family
= parent_si
->family
;
1534 child_si
->type
= parent_si
->type
;
1535 child_si
->protocol
= parent_si
->protocol
;
1536 child_si
->bound
= 1;
1537 child_si
->is_server
= 1;
1538 child_si
->connected
= 1;
1540 child_si
->peername_len
= len
;
1541 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1543 if (addr
!= NULL
&& addrlen
!= NULL
) {
1544 size_t copy_len
= MIN(*addrlen
, len
);
1546 memcpy(addr
, my_addr
, copy_len
);
1551 ret
= real_getsockname(fd
, (struct sockaddr
*)(void *)&un_my_addr
,
1560 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1561 child_si
->family
, my_addr
, &len
);
1569 child_si
->myname_len
= len
;
1570 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1573 SWRAP_DLIST_ADD(sockets
, child_si
);
1575 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1576 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1577 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1582 static int autobind_start_init
;
1583 static int autobind_start
;
1585 /* using sendto() or connect() on an unbound socket would give the
1586 recipient no way to reply, as unlike UDP and TCP, a unix domain
1587 socket can't auto-assign emphemeral port numbers, so we need to
1589 Note: this might change the family from ipv6 to ipv4
1591 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1593 struct sockaddr_un un_addr
;
1600 if (autobind_start_init
!= 1) {
1601 autobind_start_init
= 1;
1602 autobind_start
= getpid();
1603 autobind_start
%= 50000;
1604 autobind_start
+= 10000;
1607 un_addr
.sun_family
= AF_UNIX
;
1611 struct sockaddr_in in
;
1615 type
= SOCKET_TYPE_CHAR_TCP
;
1618 type
= SOCKET_TYPE_CHAR_UDP
;
1621 errno
= ESOCKTNOSUPPORT
;
1625 memset(&in
, 0, sizeof(in
));
1626 in
.sin_family
= AF_INET
;
1627 in
.sin_addr
.s_addr
= htonl(127<<24 |
1628 socket_wrapper_default_iface());
1630 si
->myname_len
= sizeof(in
);
1631 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1636 struct sockaddr_in6 in6
;
1638 if (si
->family
!= family
) {
1639 errno
= ENETUNREACH
;
1645 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1648 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1651 errno
= ESOCKTNOSUPPORT
;
1655 memset(&in6
, 0, sizeof(in6
));
1656 in6
.sin6_family
= AF_INET6
;
1657 in6
.sin6_addr
= *swrap_ipv6();
1658 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1659 si
->myname_len
= sizeof(in6
);
1660 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1665 errno
= ESOCKTNOSUPPORT
;
1669 if (autobind_start
> 60000) {
1670 autobind_start
= 10000;
1673 for (i
=0;i
<1000;i
++) {
1674 port
= autobind_start
+ i
;
1675 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1676 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1677 type
, socket_wrapper_default_iface(), port
);
1678 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1680 ret
= real_bind(si
->fd
, (struct sockaddr
*)(void *)&un_addr
,
1682 if (ret
== -1) return ret
;
1684 si
->tmp_path
= strdup(un_addr
.sun_path
);
1686 autobind_start
= port
+ 1;
1694 si
->family
= family
;
1695 set_port(si
->family
, port
, si
->myname
);
1701 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1704 struct sockaddr_un un_addr
;
1705 struct socket_info
*si
= find_socket_info(s
);
1709 return real_connect(s
, serv_addr
, addrlen
);
1712 if (si
->bound
== 0) {
1713 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1714 if (ret
== -1) return -1;
1717 if (si
->family
!= serv_addr
->sa_family
) {
1722 ret
= sockaddr_convert_to_un(si
, serv_addr
,
1723 addrlen
, &un_addr
, 0, &bcast
);
1724 if (ret
== -1) return -1;
1727 errno
= ENETUNREACH
;
1731 if (si
->type
== SOCK_DGRAM
) {
1732 si
->defer_connect
= 1;
1735 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1737 ret
= real_connect(s
, (struct sockaddr
*)(void *)&un_addr
,
1738 sizeof(struct sockaddr_un
));
1741 /* to give better errors */
1742 if (ret
== -1 && errno
== ENOENT
) {
1743 errno
= EHOSTUNREACH
;
1747 si
->peername_len
= addrlen
;
1748 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1751 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1752 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1754 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1760 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1763 struct sockaddr_un un_addr
;
1764 struct socket_info
*si
= find_socket_info(s
);
1767 return real_bind(s
, myaddr
, addrlen
);
1770 si
->myname_len
= addrlen
;
1771 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1773 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1774 if (ret
== -1) return -1;
1776 unlink(un_addr
.sun_path
);
1778 ret
= real_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
1779 sizeof(struct sockaddr_un
));
1788 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1791 struct socket_info
*si
= find_socket_info(s
);
1794 return real_listen(s
, backlog
);
1797 ret
= real_listen(s
, backlog
);
1802 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1804 struct socket_info
*si
= find_socket_info(s
);
1807 return real_getpeername(s
, name
, addrlen
);
1816 memcpy(name
, si
->peername
, si
->peername_len
);
1817 *addrlen
= si
->peername_len
;
1822 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1824 struct socket_info
*si
= find_socket_info(s
);
1827 return real_getsockname(s
, name
, addrlen
);
1830 memcpy(name
, si
->myname
, si
->myname_len
);
1831 *addrlen
= si
->myname_len
;
1836 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1838 struct socket_info
*si
= find_socket_info(s
);
1841 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1844 if (level
== SOL_SOCKET
) {
1845 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1848 errno
= ENOPROTOOPT
;
1852 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1854 struct socket_info
*si
= find_socket_info(s
);
1857 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1860 if (level
== SOL_SOCKET
) {
1861 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1864 switch (si
->family
) {
1872 errno
= ENOPROTOOPT
;
1877 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1880 struct socket_info
*si
= find_socket_info(s
);
1884 return real_ioctl(s
, r
, p
);
1887 ret
= real_ioctl(s
, r
, p
);
1891 value
= *((int *)p
);
1892 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1893 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1894 } else if (value
== 0) { /* END OF FILE */
1895 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1903 static ssize_t
swrap_sendmsg_before(struct socket_info
*si
,
1905 struct iovec
*tmp_iov
,
1906 struct sockaddr_un
*tmp_un
,
1907 const struct sockaddr_un
**to_un
,
1908 const struct sockaddr
**to
,
1926 if (!si
->connected
) {
1931 if (msg
->msg_iovlen
== 0) {
1936 * cut down to 1500 byte packets for stream sockets,
1937 * which makes it easier to format PCAP capture files
1938 * (as the caller will simply continue from here)
1941 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
1943 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
1948 msg
->msg_iovlen
= i
;
1949 if (msg
->msg_iovlen
== 0) {
1950 *tmp_iov
= msg
->msg_iov
[0];
1951 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, 1500);
1952 msg
->msg_iov
= tmp_iov
;
1953 msg
->msg_iovlen
= 1;
1958 if (si
->connected
) {
1959 if (msg
->msg_name
) {
1964 const struct sockaddr
*msg_name
;
1965 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
1967 if (msg_name
== NULL
) {
1973 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
1975 if (ret
== -1) return -1;
1983 msg
->msg_name
= tmp_un
;
1984 msg
->msg_namelen
= sizeof(*tmp_un
);
1987 if (si
->bound
== 0) {
1988 ret
= swrap_auto_bind(si
, si
->family
);
1989 if (ret
== -1) return -1;
1992 if (!si
->defer_connect
) {
1996 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
1998 if (ret
== -1) return -1;
2000 ret
= real_connect(si
->fd
, (struct sockaddr
*)(void *)tmp_un
,
2003 /* to give better errors */
2004 if (ret
== -1 && errno
== ENOENT
) {
2005 errno
= EHOSTUNREACH
;
2012 si
->defer_connect
= 0;
2015 errno
= EHOSTUNREACH
;
2022 static void swrap_sendmsg_after(struct socket_info
*si
,
2024 const struct sockaddr
*to
,
2027 int saved_errno
= errno
;
2034 /* to give better errors */
2035 if (ret
== -1 && saved_errno
== ENOENT
) {
2036 saved_errno
= EHOSTUNREACH
;
2039 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2040 avail
+= msg
->msg_iov
[i
].iov_len
;
2044 remain
= MIN(80, avail
);
2049 /* we capture it as one single packet */
2050 buf
= (uint8_t *)malloc(remain
);
2052 /* we just not capture the packet */
2053 errno
= saved_errno
;
2057 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2058 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2060 msg
->msg_iov
[i
].iov_base
,
2063 remain
-= this_time
;
2070 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2071 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2073 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2078 if (si
->connected
) {
2082 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2083 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
2085 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2091 errno
= saved_errno
;
2094 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
2096 struct sockaddr_un un_addr
;
2097 socklen_t un_addrlen
= sizeof(un_addr
);
2099 struct socket_info
*si
= find_socket_info(s
);
2100 struct sockaddr_storage ss
;
2101 socklen_t ss_len
= sizeof(ss
);
2104 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
2108 from
= (struct sockaddr
*)(void *)&ss
;
2112 if (si
->type
== SOCK_STREAM
) {
2113 /* cut down to 1500 byte packets for stream sockets,
2114 * which makes it easier to format PCAP capture files
2115 * (as the caller will simply continue from here) */
2116 len
= MIN(len
, 1500);
2119 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2120 memset(&un_addr
, 0, sizeof(un_addr
));
2121 ret
= real_recvfrom(s
, buf
, len
, flags
,
2122 (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2126 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
2127 si
->family
, from
, fromlen
) == -1) {
2131 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
2137 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
2141 struct sockaddr_un un_addr
;
2142 const struct sockaddr_un
*to_un
= NULL
;
2144 struct socket_info
*si
= find_socket_info(s
);
2148 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
2151 tmp
.iov_base
= discard_const_p(char, buf
);
2155 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
2156 msg
.msg_namelen
= tolen
; /* size of address */
2157 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2158 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2159 #if 0 /* not available on solaris */
2160 msg
.msg_control
= NULL
; /* ancillary data, see below */
2161 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2162 msg
.msg_flags
= 0; /* flags on received message */
2165 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2166 if (ret
== -1) return -1;
2168 buf
= msg
.msg_iov
[0].iov_base
;
2169 len
= msg
.msg_iov
[0].iov_len
;
2174 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2177 type
= SOCKET_TYPE_CHAR_UDP
;
2179 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2180 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2181 socket_wrapper_dir(), type
, iface
, prt
);
2182 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2184 /* ignore the any errors in broadcast sends */
2185 real_sendto(s
, buf
, len
, flags
,
2186 (struct sockaddr
*)(void *)&un_addr
,
2190 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2195 ret
= real_sendto(s
, buf
, len
, flags
, msg
.msg_name
, msg
.msg_namelen
);
2197 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2202 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2205 struct socket_info
*si
= find_socket_info(s
);
2208 return real_recv(s
, buf
, len
, flags
);
2211 if (si
->type
== SOCK_STREAM
) {
2212 /* cut down to 1500 byte packets for stream sockets,
2213 * which makes it easier to format PCAP capture files
2214 * (as the caller will simply continue from here) */
2215 len
= MIN(len
, 1500);
2218 ret
= real_recv(s
, buf
, len
, flags
);
2219 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2220 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2221 } else if (ret
== 0) { /* END OF FILE */
2222 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2223 } else if (ret
> 0) {
2224 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2230 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2233 struct socket_info
*si
= find_socket_info(s
);
2236 return real_read(s
, buf
, len
);
2239 if (si
->type
== SOCK_STREAM
) {
2240 /* cut down to 1500 byte packets for stream sockets,
2241 * which makes it easier to format PCAP capture files
2242 * (as the caller will simply continue from here) */
2243 len
= MIN(len
, 1500);
2246 ret
= real_read(s
, buf
, len
);
2247 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2248 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2249 } else if (ret
== 0) { /* END OF FILE */
2250 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2251 } else if (ret
> 0) {
2252 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2259 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2263 struct sockaddr_un un_addr
;
2265 struct socket_info
*si
= find_socket_info(s
);
2268 return real_send(s
, buf
, len
, flags
);
2271 tmp
.iov_base
= discard_const_p(char, buf
);
2275 msg
.msg_name
= NULL
; /* optional address */
2276 msg
.msg_namelen
= 0; /* size of address */
2277 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2278 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2279 #if 0 /* not available on solaris */
2280 msg
.msg_control
= NULL
; /* ancillary data, see below */
2281 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2282 msg
.msg_flags
= 0; /* flags on received message */
2285 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2286 if (ret
== -1) return -1;
2288 buf
= msg
.msg_iov
[0].iov_base
;
2289 len
= msg
.msg_iov
[0].iov_len
;
2291 ret
= real_send(s
, buf
, len
, flags
);
2293 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2298 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
2302 struct sockaddr_un un_addr
;
2303 const struct sockaddr_un
*to_un
= NULL
;
2304 const struct sockaddr
*to
= NULL
;
2306 struct socket_info
*si
= find_socket_info(s
);
2310 return real_sendmsg(s
, omsg
, flags
);
2313 tmp
.iov_base
= NULL
;
2318 msg
.msg_name
= omsg
->msg_name
; /* optional address */
2319 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
2320 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
2321 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
2322 /* the following is not available on solaris */
2323 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
2324 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
2325 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
2328 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2329 if (ret
== -1) return -1;
2334 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2342 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2343 avail
+= msg
.msg_iov
[i
].iov_len
;
2349 /* we capture it as one single packet */
2350 buf
= (uint8_t *)malloc(remain
);
2355 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2356 size_t this_time
= MIN(remain
, msg
.msg_iov
[i
].iov_len
);
2358 msg
.msg_iov
[i
].iov_base
,
2361 remain
-= this_time
;
2364 type
= SOCKET_TYPE_CHAR_UDP
;
2366 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2367 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2368 socket_wrapper_dir(), type
, iface
, prt
);
2369 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2371 msg
.msg_name
= &un_addr
; /* optional address */
2372 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
2374 /* ignore the any errors in broadcast sends */
2375 real_sendmsg(s
, &msg
, flags
);
2378 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2384 ret
= real_sendmsg(s
, &msg
, flags
);
2386 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2391 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2394 struct socket_info
*si
= find_socket_info(s
);
2398 return real_readv(s
, vector
, count
);
2401 if (!si
->connected
) {
2406 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2407 /* cut down to 1500 byte packets for stream sockets,
2408 * which makes it easier to format PCAP capture files
2409 * (as the caller will simply continue from here) */
2412 for (i
=0; i
< count
; i
++) {
2414 nlen
= len
+ vector
[i
].iov_len
;
2422 v
.iov_len
= MIN(v
.iov_len
, 1500);
2428 ret
= real_readv(s
, vector
, count
);
2429 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2430 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2431 } else if (ret
== 0) { /* END OF FILE */
2432 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2433 } else if (ret
> 0) {
2437 size_t remain
= ret
;
2439 /* we capture it as one single packet */
2440 buf
= (uint8_t *)malloc(ret
);
2442 /* we just not capture the packet */
2447 for (i
=0; i
< count
; i
++) {
2448 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2453 remain
-= this_time
;
2456 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2463 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2467 struct sockaddr_un un_addr
;
2469 struct socket_info
*si
= find_socket_info(s
);
2472 return real_writev(s
, vector
, count
);
2475 tmp
.iov_base
= NULL
;
2479 msg
.msg_name
= NULL
; /* optional address */
2480 msg
.msg_namelen
= 0; /* size of address */
2481 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
2482 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
2483 #if 0 /* not available on solaris */
2484 msg
.msg_control
= NULL
; /* ancillary data, see below */
2485 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2486 msg
.msg_flags
= 0; /* flags on received message */
2489 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2490 if (ret
== -1) return -1;
2492 ret
= real_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
2494 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2499 _PUBLIC_
int swrap_close(int fd
)
2501 struct socket_info
*si
= find_socket_info(fd
);
2505 return real_close(fd
);
2508 SWRAP_DLIST_REMOVE(sockets
, si
);
2510 if (si
->myname
&& si
->peername
) {
2511 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2514 ret
= real_close(fd
);
2516 if (si
->myname
&& si
->peername
) {
2517 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2518 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2521 if (si
->path
) free(si
->path
);
2522 if (si
->myname
) free(si
->myname
);
2523 if (si
->peername
) free(si
->peername
);
2525 unlink(si
->tmp_path
);