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 #define MAX_WRAPPED_INTERFACES 16
156 static const struct in6_addr
*swrap_ipv6(void)
158 static struct in6_addr v
;
159 static int initialized
;
167 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
176 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
178 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
179 memcpy(ret
, data
, len
);
183 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
187 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
191 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
197 static size_t socket_length(int family
)
201 return sizeof(struct sockaddr_in
);
204 return sizeof(struct sockaddr_in6
);
228 struct sockaddr
*myname
;
229 socklen_t myname_len
;
231 struct sockaddr
*peername
;
232 socklen_t peername_len
;
235 unsigned long pck_snd
;
236 unsigned long pck_rcv
;
239 struct socket_info
*prev
, *next
;
242 static struct socket_info
*sockets
;
244 const char *socket_wrapper_dir(void)
246 const char *s
= getenv("SOCKET_WRAPPER_DIR");
250 if (strncmp(s
, "./", 2) == 0) {
256 unsigned int socket_wrapper_default_iface(void)
258 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
261 if (sscanf(s
, "%u", &iface
) == 1) {
262 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
268 return 1;/* 127.0.0.1 */
271 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
278 p
= strrchr(un
->sun_path
, '/');
279 if (p
) p
++; else p
= un
->sun_path
;
281 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
286 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
297 case SOCKET_TYPE_CHAR_TCP
:
298 case SOCKET_TYPE_CHAR_UDP
: {
299 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
301 if ((*len
) < sizeof(*in2
)) {
306 memset(in2
, 0, sizeof(*in2
));
307 in2
->sin_family
= AF_INET
;
308 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
309 in2
->sin_port
= htons(prt
);
315 case SOCKET_TYPE_CHAR_TCP_V6
:
316 case SOCKET_TYPE_CHAR_UDP_V6
: {
317 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
319 if ((*len
) < sizeof(*in2
)) {
324 memset(in2
, 0, sizeof(*in2
));
325 in2
->sin6_family
= AF_INET6
;
326 in2
->sin6_addr
= *swrap_ipv6();
327 in2
->sin6_addr
.s6_addr
[15] = iface
;
328 in2
->sin6_port
= htons(prt
);
342 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
350 if (bcast
) *bcast
= 0;
352 switch (inaddr
->sa_family
) {
354 const struct sockaddr_in
*in
=
355 (const struct sockaddr_in
*)(const void *)inaddr
;
356 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
363 u_type
= SOCKET_TYPE_CHAR_TCP
;
366 u_type
= SOCKET_TYPE_CHAR_UDP
;
367 a_type
= SOCKET_TYPE_CHAR_UDP
;
368 b_type
= SOCKET_TYPE_CHAR_UDP
;
372 prt
= ntohs(in
->sin_port
);
373 if (a_type
&& addr
== 0xFFFFFFFF) {
374 /* 255.255.255.255 only udp */
377 iface
= socket_wrapper_default_iface();
378 } else if (b_type
&& addr
== 0x7FFFFFFF) {
379 /* 127.255.255.255 only udp */
382 iface
= socket_wrapper_default_iface();
383 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
387 iface
= (addr
& 0x000000FF);
392 if (bcast
) *bcast
= is_bcast
;
397 const struct sockaddr_in6
*in
=
398 (const struct sockaddr_in6
*)(const void *)inaddr
;
399 struct in6_addr cmp1
, cmp2
;
403 type
= SOCKET_TYPE_CHAR_TCP_V6
;
406 type
= SOCKET_TYPE_CHAR_UDP_V6
;
410 /* XXX no multicast/broadcast */
412 prt
= ntohs(in
->sin6_port
);
414 cmp1
= *swrap_ipv6();
415 cmp2
= in
->sin6_addr
;
416 cmp2
.s6_addr
[15] = 0;
417 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
418 iface
= in
->sin6_addr
.s6_addr
[15];
438 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
439 socket_wrapper_dir());
440 /* the caller need to do more processing */
444 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
445 socket_wrapper_dir(), type
, iface
, prt
);
450 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
459 if (bcast
) *bcast
= 0;
461 switch (si
->family
) {
463 const struct sockaddr_in
*in
=
464 (const struct sockaddr_in
*)(const void *)inaddr
;
465 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
471 prt
= ntohs(in
->sin_port
);
475 u_type
= SOCKET_TYPE_CHAR_TCP
;
476 d_type
= SOCKET_TYPE_CHAR_TCP
;
479 u_type
= SOCKET_TYPE_CHAR_UDP
;
480 d_type
= SOCKET_TYPE_CHAR_UDP
;
481 a_type
= SOCKET_TYPE_CHAR_UDP
;
482 b_type
= SOCKET_TYPE_CHAR_UDP
;
490 iface
= socket_wrapper_default_iface();
491 } else if (a_type
&& addr
== 0xFFFFFFFF) {
492 /* 255.255.255.255 only udp */
495 iface
= socket_wrapper_default_iface();
496 } else if (b_type
&& addr
== 0x7FFFFFFF) {
497 /* 127.255.255.255 only udp */
500 iface
= socket_wrapper_default_iface();
501 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
505 iface
= (addr
& 0x000000FF);
507 errno
= EADDRNOTAVAIL
;
514 const struct sockaddr_in6
*in
=
515 (const struct sockaddr_in6
*)(const void *)inaddr
;
516 struct in6_addr cmp1
, cmp2
;
520 type
= SOCKET_TYPE_CHAR_TCP_V6
;
523 type
= SOCKET_TYPE_CHAR_UDP_V6
;
527 /* XXX no multicast/broadcast */
529 prt
= ntohs(in
->sin6_port
);
531 cmp1
= *swrap_ipv6();
532 cmp2
= in
->sin6_addr
;
533 cmp2
.s6_addr
[15] = 0;
534 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
535 iface
= socket_wrapper_default_iface();
536 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
537 iface
= in
->sin6_addr
.s6_addr
[15];
539 errno
= EADDRNOTAVAIL
;
547 errno
= EADDRNOTAVAIL
;
552 if (bcast
) *bcast
= is_bcast
;
555 /* handle auto-allocation of ephemeral ports */
556 for (prt
= 5001; prt
< 10000; prt
++) {
557 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
558 socket_wrapper_dir(), type
, iface
, prt
);
559 if (stat(un
->sun_path
, &st
) == 0) continue;
561 set_port(si
->family
, prt
, si
->myname
);
570 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
571 socket_wrapper_dir(), type
, iface
, prt
);
575 static struct socket_info
*find_socket_info(int fd
)
577 struct socket_info
*i
;
578 for (i
= sockets
; i
; i
= i
->next
) {
586 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
587 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
589 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
593 out
->sa_family
= AF_UNIX
;
594 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
595 out
->sa_len
= sizeof(*out_addr
);
598 switch (in_addr
->sa_family
) {
608 errno
= ESOCKTNOSUPPORT
;
612 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
614 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
620 errno
= EAFNOSUPPORT
;
624 static int sockaddr_convert_from_un(const struct socket_info
*si
,
625 const struct sockaddr_un
*in_addr
,
626 socklen_t un_addrlen
,
628 struct sockaddr
*out_addr
,
629 socklen_t
*out_addrlen
)
633 if (out_addr
== NULL
|| out_addrlen
== NULL
)
636 if (un_addrlen
== 0) {
651 errno
= ESOCKTNOSUPPORT
;
654 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
655 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
656 out_addr
->sa_len
= *out_addrlen
;
663 errno
= EAFNOSUPPORT
;
667 enum swrap_packet_type
{
669 SWRAP_CONNECT_UNREACH
,
677 SWRAP_SENDTO_UNREACH
,
688 struct swrap_file_hdr
{
690 uint16_t version_major
;
691 uint16_t version_minor
;
694 uint32_t frame_max_len
;
695 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
698 #define SWRAP_FILE_HDR_SIZE 24
700 struct swrap_packet_frame
{
702 uint32_t micro_seconds
;
703 uint32_t recorded_length
;
704 uint32_t full_length
;
706 #define SWRAP_PACKET_FRAME_SIZE 16
708 union swrap_packet_ip
{
712 uint16_t packet_length
;
713 uint16_t identification
;
718 uint16_t hdr_checksum
;
722 #define SWRAP_PACKET_IP_V4_SIZE 20
725 uint8_t flow_label_high
;
726 uint16_t flow_label_low
;
727 uint16_t payload_length
;
730 uint8_t src_addr
[16];
731 uint8_t dest_addr
[16];
733 #define SWRAP_PACKET_IP_V6_SIZE 40
735 #define SWRAP_PACKET_IP_SIZE 40
737 union swrap_packet_payload
{
739 uint16_t source_port
;
749 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
751 uint16_t source_port
;
756 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
763 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
770 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
772 #define SWRAP_PACKET_PAYLOAD_SIZE 20
774 #define SWRAP_PACKET_MIN_ALLOC \
775 (SWRAP_PACKET_FRAME_SIZE + \
776 SWRAP_PACKET_IP_SIZE + \
777 SWRAP_PACKET_PAYLOAD_SIZE)
779 static const char *socket_wrapper_pcap_file(void)
781 static int initialized
= 0;
782 static const char *s
= NULL
;
783 static const struct swrap_file_hdr h
;
784 static const struct swrap_packet_frame f
;
785 static const union swrap_packet_ip i
;
786 static const union swrap_packet_payload p
;
788 if (initialized
== 1) {
794 * TODO: don't use the structs use plain buffer offsets
795 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
797 * for now make sure we disable PCAP support
798 * if the struct has alignment!
800 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
803 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
806 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
809 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
812 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
815 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
818 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
821 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
824 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
827 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
831 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
835 if (strncmp(s
, "./", 2) == 0) {
841 static uint8_t *swrap_packet_init(struct timeval
*tval
,
842 const struct sockaddr
*src
,
843 const struct sockaddr
*dest
,
845 const uint8_t *payload
,
847 unsigned long tcp_seqno
,
848 unsigned long tcp_ack
,
849 unsigned char tcp_ctl
,
855 struct swrap_packet_frame
*frame
;
856 union swrap_packet_ip
*ip
;
857 union swrap_packet_payload
*pay
;
860 size_t nonwire_len
= sizeof(*frame
);
861 size_t wire_hdr_len
= 0;
863 size_t ip_hdr_len
= 0;
864 size_t icmp_hdr_len
= 0;
865 size_t icmp_truncate_len
= 0;
866 uint8_t protocol
= 0, icmp_protocol
= 0;
867 const struct sockaddr_in
*src_in
= NULL
;
868 const struct sockaddr_in
*dest_in
= NULL
;
870 const struct sockaddr_in6
*src_in6
= NULL
;
871 const struct sockaddr_in6
*dest_in6
= NULL
;
876 switch (src
->sa_family
) {
878 src_in
= (const struct sockaddr_in
*)src
;
879 dest_in
= (const struct sockaddr_in
*)dest
;
880 src_port
= src_in
->sin_port
;
881 dest_port
= dest_in
->sin_port
;
882 ip_hdr_len
= sizeof(ip
->v4
);
886 src_in6
= (const struct sockaddr_in6
*)src
;
887 dest_in6
= (const struct sockaddr_in6
*)dest
;
888 src_port
= src_in6
->sin6_port
;
889 dest_port
= dest_in6
->sin6_port
;
890 ip_hdr_len
= sizeof(ip
->v6
);
897 switch (socket_type
) {
899 protocol
= 0x06; /* TCP */
900 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
901 wire_len
= wire_hdr_len
+ payload_len
;
905 protocol
= 0x11; /* UDP */
906 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
907 wire_len
= wire_hdr_len
+ payload_len
;
915 icmp_protocol
= protocol
;
916 switch (src
->sa_family
) {
918 protocol
= 0x01; /* ICMPv4 */
919 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
923 protocol
= 0x3A; /* ICMPv6 */
924 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
928 if (wire_len
> 64 ) {
929 icmp_truncate_len
= wire_len
- 64;
931 wire_hdr_len
+= icmp_hdr_len
;
932 wire_len
+= icmp_hdr_len
;
935 packet_len
= nonwire_len
+ wire_len
;
936 alloc_len
= packet_len
;
937 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
938 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
941 base
= (uint8_t *)malloc(alloc_len
);
942 if (!base
) return NULL
;
946 frame
= (struct swrap_packet_frame
*)buf
;
947 frame
->seconds
= tval
->tv_sec
;
948 frame
->micro_seconds
= tval
->tv_usec
;
949 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
950 frame
->full_length
= wire_len
- icmp_truncate_len
;
951 buf
+= SWRAP_PACKET_FRAME_SIZE
;
953 ip
= (union swrap_packet_ip
*)buf
;
954 switch (src
->sa_family
) {
956 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
958 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
959 ip
->v4
.identification
= htons(0xFFFF);
960 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
961 ip
->v4
.fragment
= htons(0x0000);
963 ip
->v4
.protocol
= protocol
;
964 ip
->v4
.hdr_checksum
= htons(0x0000);
965 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
966 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
967 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
971 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
972 ip
->v6
.flow_label_high
= 0x00;
973 ip
->v6
.flow_label_low
= 0x0000;
974 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
975 ip
->v6
.next_header
= protocol
;
976 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
977 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
978 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
984 pay
= (union swrap_packet_payload
*)buf
;
985 switch (src
->sa_family
) {
987 pay
->icmp4
.type
= 0x03; /* destination unreachable */
988 pay
->icmp4
.code
= 0x01; /* host unreachable */
989 pay
->icmp4
.checksum
= htons(0x0000);
990 pay
->icmp4
.unused
= htonl(0x00000000);
991 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
993 /* set the ip header in the ICMP payload */
994 ip
= (union swrap_packet_ip
*)buf
;
995 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
997 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
998 ip
->v4
.identification
= htons(0xFFFF);
999 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
1000 ip
->v4
.fragment
= htons(0x0000);
1002 ip
->v4
.protocol
= icmp_protocol
;
1003 ip
->v4
.hdr_checksum
= htons(0x0000);
1004 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1005 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1006 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1008 src_port
= dest_in
->sin_port
;
1009 dest_port
= src_in
->sin_port
;
1013 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1014 pay
->icmp6
.code
= 0x03; /* address unreachable */
1015 pay
->icmp6
.checksum
= htons(0x0000);
1016 pay
->icmp6
.unused
= htonl(0x00000000);
1017 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1019 /* set the ip header in the ICMP payload */
1020 ip
= (union swrap_packet_ip
*)buf
;
1021 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1022 ip
->v6
.flow_label_high
= 0x00;
1023 ip
->v6
.flow_label_low
= 0x0000;
1024 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1025 ip
->v6
.next_header
= protocol
;
1026 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1027 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1028 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1030 src_port
= dest_in6
->sin6_port
;
1031 dest_port
= src_in6
->sin6_port
;
1037 pay
= (union swrap_packet_payload
*)buf
;
1039 switch (socket_type
) {
1041 pay
->tcp
.source_port
= src_port
;
1042 pay
->tcp
.dest_port
= dest_port
;
1043 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1044 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1045 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1046 pay
->tcp
.control
= tcp_ctl
;
1047 pay
->tcp
.window
= htons(0x7FFF);
1048 pay
->tcp
.checksum
= htons(0x0000);
1049 pay
->tcp
.urg
= htons(0x0000);
1050 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1055 pay
->udp
.source_port
= src_port
;
1056 pay
->udp
.dest_port
= dest_port
;
1057 pay
->udp
.length
= htons(8 + payload_len
);
1058 pay
->udp
.checksum
= htons(0x0000);
1059 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1064 if (payload
&& payload_len
> 0) {
1065 memcpy(buf
, payload
, payload_len
);
1068 *_packet_len
= packet_len
- icmp_truncate_len
;
1072 static int swrap_get_pcap_fd(const char *fname
)
1076 if (fd
!= -1) return fd
;
1078 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1080 struct swrap_file_hdr file_hdr
;
1081 file_hdr
.magic
= 0xA1B2C3D4;
1082 file_hdr
.version_major
= 0x0002;
1083 file_hdr
.version_minor
= 0x0004;
1084 file_hdr
.timezone
= 0x00000000;
1085 file_hdr
.sigfigs
= 0x00000000;
1086 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1087 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1089 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1096 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1101 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1102 const struct sockaddr
*addr
,
1103 enum swrap_packet_type type
,
1104 const void *buf
, size_t len
,
1107 const struct sockaddr
*src_addr
;
1108 const struct sockaddr
*dest_addr
;
1109 unsigned long tcp_seqno
= 0;
1110 unsigned long tcp_ack
= 0;
1111 unsigned char tcp_ctl
= 0;
1112 int unreachable
= 0;
1116 switch (si
->family
) {
1128 case SWRAP_CONNECT_SEND
:
1129 if (si
->type
!= SOCK_STREAM
) return NULL
;
1131 src_addr
= si
->myname
;
1134 tcp_seqno
= si
->io
.pck_snd
;
1135 tcp_ack
= si
->io
.pck_rcv
;
1136 tcp_ctl
= 0x02; /* SYN */
1138 si
->io
.pck_snd
+= 1;
1142 case SWRAP_CONNECT_RECV
:
1143 if (si
->type
!= SOCK_STREAM
) return NULL
;
1145 dest_addr
= si
->myname
;
1148 tcp_seqno
= si
->io
.pck_rcv
;
1149 tcp_ack
= si
->io
.pck_snd
;
1150 tcp_ctl
= 0x12; /** SYN,ACK */
1152 si
->io
.pck_rcv
+= 1;
1156 case SWRAP_CONNECT_UNREACH
:
1157 if (si
->type
!= SOCK_STREAM
) return NULL
;
1159 dest_addr
= si
->myname
;
1162 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1163 tcp_seqno
= si
->io
.pck_snd
- 1;
1164 tcp_ack
= si
->io
.pck_rcv
;
1165 tcp_ctl
= 0x02; /* SYN */
1170 case SWRAP_CONNECT_ACK
:
1171 if (si
->type
!= SOCK_STREAM
) return NULL
;
1173 src_addr
= si
->myname
;
1176 tcp_seqno
= si
->io
.pck_snd
;
1177 tcp_ack
= si
->io
.pck_rcv
;
1178 tcp_ctl
= 0x10; /* ACK */
1182 case SWRAP_ACCEPT_SEND
:
1183 if (si
->type
!= SOCK_STREAM
) return NULL
;
1185 dest_addr
= si
->myname
;
1188 tcp_seqno
= si
->io
.pck_rcv
;
1189 tcp_ack
= si
->io
.pck_snd
;
1190 tcp_ctl
= 0x02; /* SYN */
1192 si
->io
.pck_rcv
+= 1;
1196 case SWRAP_ACCEPT_RECV
:
1197 if (si
->type
!= SOCK_STREAM
) return NULL
;
1199 src_addr
= si
->myname
;
1202 tcp_seqno
= si
->io
.pck_snd
;
1203 tcp_ack
= si
->io
.pck_rcv
;
1204 tcp_ctl
= 0x12; /* SYN,ACK */
1206 si
->io
.pck_snd
+= 1;
1210 case SWRAP_ACCEPT_ACK
:
1211 if (si
->type
!= SOCK_STREAM
) return NULL
;
1213 dest_addr
= si
->myname
;
1216 tcp_seqno
= si
->io
.pck_rcv
;
1217 tcp_ack
= si
->io
.pck_snd
;
1218 tcp_ctl
= 0x10; /* ACK */
1223 src_addr
= si
->myname
;
1224 dest_addr
= si
->peername
;
1226 tcp_seqno
= si
->io
.pck_snd
;
1227 tcp_ack
= si
->io
.pck_rcv
;
1228 tcp_ctl
= 0x18; /* PSH,ACK */
1230 si
->io
.pck_snd
+= len
;
1234 case SWRAP_SEND_RST
:
1235 dest_addr
= si
->myname
;
1236 src_addr
= si
->peername
;
1238 if (si
->type
== SOCK_DGRAM
) {
1239 return swrap_marshall_packet(si
, si
->peername
,
1240 SWRAP_SENDTO_UNREACH
,
1241 buf
, len
, packet_len
);
1244 tcp_seqno
= si
->io
.pck_rcv
;
1245 tcp_ack
= si
->io
.pck_snd
;
1246 tcp_ctl
= 0x14; /** RST,ACK */
1250 case SWRAP_PENDING_RST
:
1251 dest_addr
= si
->myname
;
1252 src_addr
= si
->peername
;
1254 if (si
->type
== SOCK_DGRAM
) {
1258 tcp_seqno
= si
->io
.pck_rcv
;
1259 tcp_ack
= si
->io
.pck_snd
;
1260 tcp_ctl
= 0x14; /* RST,ACK */
1265 dest_addr
= si
->myname
;
1266 src_addr
= si
->peername
;
1268 tcp_seqno
= si
->io
.pck_rcv
;
1269 tcp_ack
= si
->io
.pck_snd
;
1270 tcp_ctl
= 0x18; /* PSH,ACK */
1272 si
->io
.pck_rcv
+= len
;
1276 case SWRAP_RECV_RST
:
1277 dest_addr
= si
->myname
;
1278 src_addr
= si
->peername
;
1280 if (si
->type
== SOCK_DGRAM
) {
1284 tcp_seqno
= si
->io
.pck_rcv
;
1285 tcp_ack
= si
->io
.pck_snd
;
1286 tcp_ctl
= 0x14; /* RST,ACK */
1291 src_addr
= si
->myname
;
1294 si
->io
.pck_snd
+= len
;
1298 case SWRAP_SENDTO_UNREACH
:
1299 dest_addr
= si
->myname
;
1306 case SWRAP_RECVFROM
:
1307 dest_addr
= si
->myname
;
1310 si
->io
.pck_rcv
+= len
;
1314 case SWRAP_CLOSE_SEND
:
1315 if (si
->type
!= SOCK_STREAM
) return NULL
;
1317 src_addr
= si
->myname
;
1318 dest_addr
= si
->peername
;
1320 tcp_seqno
= si
->io
.pck_snd
;
1321 tcp_ack
= si
->io
.pck_rcv
;
1322 tcp_ctl
= 0x11; /* FIN, ACK */
1324 si
->io
.pck_snd
+= 1;
1328 case SWRAP_CLOSE_RECV
:
1329 if (si
->type
!= SOCK_STREAM
) return NULL
;
1331 dest_addr
= si
->myname
;
1332 src_addr
= si
->peername
;
1334 tcp_seqno
= si
->io
.pck_rcv
;
1335 tcp_ack
= si
->io
.pck_snd
;
1336 tcp_ctl
= 0x11; /* FIN,ACK */
1338 si
->io
.pck_rcv
+= 1;
1342 case SWRAP_CLOSE_ACK
:
1343 if (si
->type
!= SOCK_STREAM
) return NULL
;
1345 src_addr
= si
->myname
;
1346 dest_addr
= si
->peername
;
1348 tcp_seqno
= si
->io
.pck_snd
;
1349 tcp_ack
= si
->io
.pck_rcv
;
1350 tcp_ctl
= 0x10; /* ACK */
1357 swrapGetTimeOfDay(&tv
);
1359 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1360 (const uint8_t *)buf
, len
,
1361 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1365 static void swrap_dump_packet(struct socket_info
*si
,
1366 const struct sockaddr
*addr
,
1367 enum swrap_packet_type type
,
1368 const void *buf
, size_t len
)
1370 const char *file_name
;
1372 size_t packet_len
= 0;
1375 file_name
= socket_wrapper_pcap_file();
1380 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1385 fd
= swrap_get_pcap_fd(file_name
);
1387 if (write(fd
, packet
, packet_len
) != packet_len
) {
1396 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1398 struct socket_info
*si
;
1400 int real_type
= type
;
1402 real_type
&= ~SOCK_CLOEXEC
;
1404 #ifdef SOCK_NONBLOCK
1405 real_type
&= ~SOCK_NONBLOCK
;
1408 if (!socket_wrapper_dir()) {
1409 return real_socket(family
, type
, protocol
);
1419 return real_socket(family
, type
, protocol
);
1421 errno
= EAFNOSUPPORT
;
1425 switch (real_type
) {
1431 errno
= EPROTONOSUPPORT
;
1439 if (real_type
== SOCK_STREAM
) {
1444 if (real_type
== SOCK_DGRAM
) {
1449 errno
= EPROTONOSUPPORT
;
1453 /* We must call real_socket with type, from the caller, not the version we removed
1454 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1455 fd
= real_socket(AF_UNIX
, type
, 0);
1457 if (fd
== -1) return -1;
1459 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1461 si
->family
= family
;
1463 /* however, the rest of the socket_wrapper code expects just
1464 * the type, not the flags */
1465 si
->type
= real_type
;
1466 si
->protocol
= protocol
;
1469 SWRAP_DLIST_ADD(sockets
, si
);
1474 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1476 struct socket_info
*parent_si
, *child_si
;
1478 struct sockaddr_un un_addr
;
1479 socklen_t un_addrlen
= sizeof(un_addr
);
1480 struct sockaddr_un un_my_addr
;
1481 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1482 struct sockaddr
*my_addr
;
1483 socklen_t my_addrlen
, len
;
1486 parent_si
= find_socket_info(s
);
1488 return real_accept(s
, addr
, addrlen
);
1492 * assume out sockaddr have the same size as the in parent
1495 my_addrlen
= socket_length(parent_si
->family
);
1496 if (my_addrlen
<= 0) {
1501 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1502 if (my_addr
== NULL
) {
1506 memset(&un_addr
, 0, sizeof(un_addr
));
1507 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1509 ret
= real_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
1518 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1519 parent_si
->family
, my_addr
, &len
);
1526 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1527 memset(child_si
, 0, sizeof(*child_si
));
1530 child_si
->family
= parent_si
->family
;
1531 child_si
->type
= parent_si
->type
;
1532 child_si
->protocol
= parent_si
->protocol
;
1533 child_si
->bound
= 1;
1534 child_si
->is_server
= 1;
1535 child_si
->connected
= 1;
1537 child_si
->peername_len
= len
;
1538 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1540 if (addr
!= NULL
&& addrlen
!= NULL
) {
1541 size_t copy_len
= MIN(*addrlen
, len
);
1543 memcpy(addr
, my_addr
, copy_len
);
1548 ret
= real_getsockname(fd
, (struct sockaddr
*)(void *)&un_my_addr
,
1557 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1558 child_si
->family
, my_addr
, &len
);
1566 child_si
->myname_len
= len
;
1567 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1570 SWRAP_DLIST_ADD(sockets
, child_si
);
1572 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1573 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1574 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1579 static int autobind_start_init
;
1580 static int autobind_start
;
1582 /* using sendto() or connect() on an unbound socket would give the
1583 recipient no way to reply, as unlike UDP and TCP, a unix domain
1584 socket can't auto-assign emphemeral port numbers, so we need to
1586 Note: this might change the family from ipv6 to ipv4
1588 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1590 struct sockaddr_un un_addr
;
1597 if (autobind_start_init
!= 1) {
1598 autobind_start_init
= 1;
1599 autobind_start
= getpid();
1600 autobind_start
%= 50000;
1601 autobind_start
+= 10000;
1604 un_addr
.sun_family
= AF_UNIX
;
1608 struct sockaddr_in in
;
1612 type
= SOCKET_TYPE_CHAR_TCP
;
1615 type
= SOCKET_TYPE_CHAR_UDP
;
1618 errno
= ESOCKTNOSUPPORT
;
1622 memset(&in
, 0, sizeof(in
));
1623 in
.sin_family
= AF_INET
;
1624 in
.sin_addr
.s_addr
= htonl(127<<24 |
1625 socket_wrapper_default_iface());
1627 si
->myname_len
= sizeof(in
);
1628 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1633 struct sockaddr_in6 in6
;
1635 if (si
->family
!= family
) {
1636 errno
= ENETUNREACH
;
1642 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1645 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1648 errno
= ESOCKTNOSUPPORT
;
1652 memset(&in6
, 0, sizeof(in6
));
1653 in6
.sin6_family
= AF_INET6
;
1654 in6
.sin6_addr
= *swrap_ipv6();
1655 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1656 si
->myname_len
= sizeof(in6
);
1657 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1662 errno
= ESOCKTNOSUPPORT
;
1666 if (autobind_start
> 60000) {
1667 autobind_start
= 10000;
1670 for (i
=0;i
<1000;i
++) {
1671 port
= autobind_start
+ i
;
1672 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1673 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1674 type
, socket_wrapper_default_iface(), port
);
1675 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1677 ret
= real_bind(si
->fd
, (struct sockaddr
*)(void *)&un_addr
,
1679 if (ret
== -1) return ret
;
1681 si
->tmp_path
= strdup(un_addr
.sun_path
);
1683 autobind_start
= port
+ 1;
1691 si
->family
= family
;
1692 set_port(si
->family
, port
, si
->myname
);
1698 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1701 struct sockaddr_un un_addr
;
1702 struct socket_info
*si
= find_socket_info(s
);
1706 return real_connect(s
, serv_addr
, addrlen
);
1709 if (si
->bound
== 0) {
1710 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1711 if (ret
== -1) return -1;
1714 if (si
->family
!= serv_addr
->sa_family
) {
1719 ret
= sockaddr_convert_to_un(si
, serv_addr
,
1720 addrlen
, &un_addr
, 0, &bcast
);
1721 if (ret
== -1) return -1;
1724 errno
= ENETUNREACH
;
1728 if (si
->type
== SOCK_DGRAM
) {
1729 si
->defer_connect
= 1;
1732 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1734 ret
= real_connect(s
, (struct sockaddr
*)(void *)&un_addr
,
1735 sizeof(struct sockaddr_un
));
1738 /* to give better errors */
1739 if (ret
== -1 && errno
== ENOENT
) {
1740 errno
= EHOSTUNREACH
;
1744 si
->peername_len
= addrlen
;
1745 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1748 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1749 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1751 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1757 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1760 struct sockaddr_un un_addr
;
1761 struct socket_info
*si
= find_socket_info(s
);
1764 return real_bind(s
, myaddr
, addrlen
);
1767 si
->myname_len
= addrlen
;
1768 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1770 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1771 if (ret
== -1) return -1;
1773 unlink(un_addr
.sun_path
);
1775 ret
= real_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
1776 sizeof(struct sockaddr_un
));
1785 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1788 struct socket_info
*si
= find_socket_info(s
);
1791 return real_listen(s
, backlog
);
1794 ret
= real_listen(s
, backlog
);
1799 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1801 struct socket_info
*si
= find_socket_info(s
);
1804 return real_getpeername(s
, name
, addrlen
);
1813 memcpy(name
, si
->peername
, si
->peername_len
);
1814 *addrlen
= si
->peername_len
;
1819 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1821 struct socket_info
*si
= find_socket_info(s
);
1824 return real_getsockname(s
, name
, addrlen
);
1827 memcpy(name
, si
->myname
, si
->myname_len
);
1828 *addrlen
= si
->myname_len
;
1833 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1835 struct socket_info
*si
= find_socket_info(s
);
1838 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1841 if (level
== SOL_SOCKET
) {
1842 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1845 errno
= ENOPROTOOPT
;
1849 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1851 struct socket_info
*si
= find_socket_info(s
);
1854 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1857 if (level
== SOL_SOCKET
) {
1858 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1861 switch (si
->family
) {
1869 errno
= ENOPROTOOPT
;
1874 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1877 struct socket_info
*si
= find_socket_info(s
);
1881 return real_ioctl(s
, r
, p
);
1884 ret
= real_ioctl(s
, r
, p
);
1888 value
= *((int *)p
);
1889 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1890 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1891 } else if (value
== 0) { /* END OF FILE */
1892 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1900 static ssize_t
swrap_sendmsg_before(struct socket_info
*si
,
1902 struct iovec
*tmp_iov
,
1903 struct sockaddr_un
*tmp_un
,
1904 const struct sockaddr_un
**to_un
,
1905 const struct sockaddr
**to
,
1923 if (!si
->connected
) {
1928 if (msg
->msg_iovlen
== 0) {
1933 * cut down to 1500 byte packets for stream sockets,
1934 * which makes it easier to format PCAP capture files
1935 * (as the caller will simply continue from here)
1938 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
1940 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
1945 msg
->msg_iovlen
= i
;
1946 if (msg
->msg_iovlen
== 0) {
1947 *tmp_iov
= msg
->msg_iov
[0];
1948 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, 1500);
1949 msg
->msg_iov
= tmp_iov
;
1950 msg
->msg_iovlen
= 1;
1955 if (si
->connected
) {
1956 if (msg
->msg_name
) {
1961 const struct sockaddr
*msg_name
;
1962 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
1964 if (msg_name
== NULL
) {
1970 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
1972 if (ret
== -1) return -1;
1980 msg
->msg_name
= tmp_un
;
1981 msg
->msg_namelen
= sizeof(*tmp_un
);
1984 if (si
->bound
== 0) {
1985 ret
= swrap_auto_bind(si
, si
->family
);
1986 if (ret
== -1) return -1;
1989 if (!si
->defer_connect
) {
1993 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
1995 if (ret
== -1) return -1;
1997 ret
= real_connect(si
->fd
, (struct sockaddr
*)(void *)tmp_un
,
2000 /* to give better errors */
2001 if (ret
== -1 && errno
== ENOENT
) {
2002 errno
= EHOSTUNREACH
;
2009 si
->defer_connect
= 0;
2012 errno
= EHOSTUNREACH
;
2019 static void swrap_sendmsg_after(struct socket_info
*si
,
2021 const struct sockaddr
*to
,
2024 int saved_errno
= errno
;
2031 /* to give better errors */
2032 if (ret
== -1 && saved_errno
== ENOENT
) {
2033 saved_errno
= EHOSTUNREACH
;
2036 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2037 avail
+= msg
->msg_iov
[i
].iov_len
;
2041 remain
= MIN(80, avail
);
2046 /* we capture it as one single packet */
2047 buf
= (uint8_t *)malloc(remain
);
2049 /* we just not capture the packet */
2050 errno
= saved_errno
;
2054 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2055 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2057 msg
->msg_iov
[i
].iov_base
,
2060 remain
-= this_time
;
2067 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2068 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2070 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2075 if (si
->connected
) {
2079 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2080 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
2082 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2088 errno
= saved_errno
;
2091 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
2093 struct sockaddr_un un_addr
;
2094 socklen_t un_addrlen
= sizeof(un_addr
);
2096 struct socket_info
*si
= find_socket_info(s
);
2097 struct sockaddr_storage ss
;
2098 socklen_t ss_len
= sizeof(ss
);
2101 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
2105 from
= (struct sockaddr
*)(void *)&ss
;
2109 if (si
->type
== SOCK_STREAM
) {
2110 /* cut down to 1500 byte packets for stream sockets,
2111 * which makes it easier to format PCAP capture files
2112 * (as the caller will simply continue from here) */
2113 len
= MIN(len
, 1500);
2116 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2117 memset(&un_addr
, 0, sizeof(un_addr
));
2118 ret
= real_recvfrom(s
, buf
, len
, flags
,
2119 (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2123 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
2124 si
->family
, from
, fromlen
) == -1) {
2128 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
2134 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
2138 struct sockaddr_un un_addr
;
2139 const struct sockaddr_un
*to_un
= NULL
;
2141 struct socket_info
*si
= find_socket_info(s
);
2145 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
2148 tmp
.iov_base
= discard_const_p(char, buf
);
2152 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
2153 msg
.msg_namelen
= tolen
; /* size of address */
2154 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2155 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2156 #if 0 /* not available on solaris */
2157 msg
.msg_control
= NULL
; /* ancillary data, see below */
2158 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2159 msg
.msg_flags
= 0; /* flags on received message */
2162 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2163 if (ret
== -1) return -1;
2165 buf
= msg
.msg_iov
[0].iov_base
;
2166 len
= msg
.msg_iov
[0].iov_len
;
2171 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2174 type
= SOCKET_TYPE_CHAR_UDP
;
2176 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2177 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2178 socket_wrapper_dir(), type
, iface
, prt
);
2179 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2181 /* ignore the any errors in broadcast sends */
2182 real_sendto(s
, buf
, len
, flags
,
2183 (struct sockaddr
*)(void *)&un_addr
,
2187 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2192 ret
= real_sendto(s
, buf
, len
, flags
, msg
.msg_name
, msg
.msg_namelen
);
2194 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2199 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2202 struct socket_info
*si
= find_socket_info(s
);
2205 return real_recv(s
, buf
, len
, flags
);
2208 if (si
->type
== SOCK_STREAM
) {
2209 /* cut down to 1500 byte packets for stream sockets,
2210 * which makes it easier to format PCAP capture files
2211 * (as the caller will simply continue from here) */
2212 len
= MIN(len
, 1500);
2215 ret
= real_recv(s
, buf
, len
, flags
);
2216 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2217 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2218 } else if (ret
== 0) { /* END OF FILE */
2219 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2220 } else if (ret
> 0) {
2221 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2227 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2230 struct socket_info
*si
= find_socket_info(s
);
2233 return real_read(s
, buf
, len
);
2236 if (si
->type
== SOCK_STREAM
) {
2237 /* cut down to 1500 byte packets for stream sockets,
2238 * which makes it easier to format PCAP capture files
2239 * (as the caller will simply continue from here) */
2240 len
= MIN(len
, 1500);
2243 ret
= real_read(s
, buf
, len
);
2244 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2245 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2246 } else if (ret
== 0) { /* END OF FILE */
2247 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2248 } else if (ret
> 0) {
2249 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2256 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2260 struct sockaddr_un un_addr
;
2262 struct socket_info
*si
= find_socket_info(s
);
2265 return real_send(s
, buf
, len
, flags
);
2268 tmp
.iov_base
= discard_const_p(char, buf
);
2272 msg
.msg_name
= NULL
; /* optional address */
2273 msg
.msg_namelen
= 0; /* size of address */
2274 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2275 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2276 #if 0 /* not available on solaris */
2277 msg
.msg_control
= NULL
; /* ancillary data, see below */
2278 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2279 msg
.msg_flags
= 0; /* flags on received message */
2282 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2283 if (ret
== -1) return -1;
2285 buf
= msg
.msg_iov
[0].iov_base
;
2286 len
= msg
.msg_iov
[0].iov_len
;
2288 ret
= real_send(s
, buf
, len
, flags
);
2290 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2295 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
2299 struct sockaddr_un un_addr
;
2300 const struct sockaddr_un
*to_un
= NULL
;
2301 const struct sockaddr
*to
= NULL
;
2303 struct socket_info
*si
= find_socket_info(s
);
2307 return real_sendmsg(s
, omsg
, flags
);
2310 tmp
.iov_base
= NULL
;
2315 msg
.msg_name
= omsg
->msg_name
; /* optional address */
2316 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
2317 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
2318 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
2319 /* the following is not available on solaris */
2320 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
2321 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
2322 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
2325 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2326 if (ret
== -1) return -1;
2331 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2339 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2340 avail
+= msg
.msg_iov
[i
].iov_len
;
2346 /* we capture it as one single packet */
2347 buf
= (uint8_t *)malloc(remain
);
2352 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2353 size_t this_time
= MIN(remain
, msg
.msg_iov
[i
].iov_len
);
2355 msg
.msg_iov
[i
].iov_base
,
2358 remain
-= this_time
;
2361 type
= SOCKET_TYPE_CHAR_UDP
;
2363 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2364 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2365 socket_wrapper_dir(), type
, iface
, prt
);
2366 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2368 msg
.msg_name
= &un_addr
; /* optional address */
2369 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
2371 /* ignore the any errors in broadcast sends */
2372 real_sendmsg(s
, &msg
, flags
);
2375 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2381 ret
= real_sendmsg(s
, &msg
, flags
);
2383 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2388 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2391 struct socket_info
*si
= find_socket_info(s
);
2395 return real_readv(s
, vector
, count
);
2398 if (!si
->connected
) {
2403 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2404 /* cut down to 1500 byte packets for stream sockets,
2405 * which makes it easier to format PCAP capture files
2406 * (as the caller will simply continue from here) */
2409 for (i
=0; i
< count
; i
++) {
2411 nlen
= len
+ vector
[i
].iov_len
;
2419 v
.iov_len
= MIN(v
.iov_len
, 1500);
2425 ret
= real_readv(s
, vector
, count
);
2426 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2427 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2428 } else if (ret
== 0) { /* END OF FILE */
2429 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2430 } else if (ret
> 0) {
2434 size_t remain
= ret
;
2436 /* we capture it as one single packet */
2437 buf
= (uint8_t *)malloc(ret
);
2439 /* we just not capture the packet */
2444 for (i
=0; i
< count
; i
++) {
2445 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2450 remain
-= this_time
;
2453 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2460 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2464 struct sockaddr_un un_addr
;
2466 struct socket_info
*si
= find_socket_info(s
);
2469 return real_writev(s
, vector
, count
);
2472 tmp
.iov_base
= NULL
;
2476 msg
.msg_name
= NULL
; /* optional address */
2477 msg
.msg_namelen
= 0; /* size of address */
2478 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
2479 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
2480 #if 0 /* not available on solaris */
2481 msg
.msg_control
= NULL
; /* ancillary data, see below */
2482 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2483 msg
.msg_flags
= 0; /* flags on received message */
2486 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2487 if (ret
== -1) return -1;
2489 ret
= real_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
2491 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2496 _PUBLIC_
int swrap_close(int fd
)
2498 struct socket_info
*si
= find_socket_info(fd
);
2502 return real_close(fd
);
2505 SWRAP_DLIST_REMOVE(sockets
, si
);
2507 if (si
->myname
&& si
->peername
) {
2508 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2511 ret
= real_close(fd
);
2513 if (si
->myname
&& si
->peername
) {
2514 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2515 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2518 if (si
->path
) free(si
->path
);
2519 if (si
->myname
) free(si
->myname
);
2520 if (si
->peername
) free(si
->peername
);
2522 unlink(si
->tmp_path
);