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
131 #define real_dup2 dup2
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
140 /* we need to use a very terse format here as IRIX 6.4 silently
141 truncates names to 16 chars, so if we use a longer name then we
142 can't tell which port a packet came from with recvfrom()
144 with this format we have 8 chars left for the directory name
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
149 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
150 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
152 /* This limit is to avoid broadcast sendto() needing to stat too many
153 * files. It may be raised (with a performance cost) to up to 254
154 * without changing the format above */
155 #define MAX_WRAPPED_INTERFACES 32
161 static const struct in6_addr
*swrap_ipv6(void)
163 static struct in6_addr v
;
164 static int initialized
;
172 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
181 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
183 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
184 memcpy(ret
, data
, len
);
188 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
192 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
196 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
202 static size_t socket_length(int family
)
206 return sizeof(struct sockaddr_in
);
209 return sizeof(struct sockaddr_in6
);
232 struct sockaddr
*myname
;
233 socklen_t myname_len
;
235 struct sockaddr
*peername
;
236 socklen_t peername_len
;
239 unsigned long pck_snd
;
240 unsigned long pck_rcv
;
243 struct socket_info
*prev
, *next
;
246 static struct socket_info
*sockets
;
248 const char *socket_wrapper_dir(void)
250 const char *s
= getenv("SOCKET_WRAPPER_DIR");
254 if (strncmp(s
, "./", 2) == 0) {
260 unsigned int socket_wrapper_default_iface(void)
262 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
265 if (sscanf(s
, "%u", &iface
) == 1) {
266 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
272 return 1;/* 127.0.0.1 */
275 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
282 p
= strrchr(un
->sun_path
, '/');
283 if (p
) p
++; else p
= un
->sun_path
;
285 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
290 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
301 case SOCKET_TYPE_CHAR_TCP
:
302 case SOCKET_TYPE_CHAR_UDP
: {
303 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
305 if ((*len
) < sizeof(*in2
)) {
310 memset(in2
, 0, sizeof(*in2
));
311 in2
->sin_family
= AF_INET
;
312 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
313 in2
->sin_port
= htons(prt
);
319 case SOCKET_TYPE_CHAR_TCP_V6
:
320 case SOCKET_TYPE_CHAR_UDP_V6
: {
321 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
323 if ((*len
) < sizeof(*in2
)) {
328 memset(in2
, 0, sizeof(*in2
));
329 in2
->sin6_family
= AF_INET6
;
330 in2
->sin6_addr
= *swrap_ipv6();
331 in2
->sin6_addr
.s6_addr
[15] = iface
;
332 in2
->sin6_port
= htons(prt
);
346 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
354 if (bcast
) *bcast
= 0;
356 switch (inaddr
->sa_family
) {
358 const struct sockaddr_in
*in
=
359 (const struct sockaddr_in
*)(const void *)inaddr
;
360 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
367 u_type
= SOCKET_TYPE_CHAR_TCP
;
370 u_type
= SOCKET_TYPE_CHAR_UDP
;
371 a_type
= SOCKET_TYPE_CHAR_UDP
;
372 b_type
= SOCKET_TYPE_CHAR_UDP
;
376 prt
= ntohs(in
->sin_port
);
377 if (a_type
&& addr
== 0xFFFFFFFF) {
378 /* 255.255.255.255 only udp */
381 iface
= socket_wrapper_default_iface();
382 } else if (b_type
&& addr
== 0x7FFFFFFF) {
383 /* 127.255.255.255 only udp */
386 iface
= socket_wrapper_default_iface();
387 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
391 iface
= (addr
& 0x000000FF);
396 if (bcast
) *bcast
= is_bcast
;
401 const struct sockaddr_in6
*in
=
402 (const struct sockaddr_in6
*)(const void *)inaddr
;
403 struct in6_addr cmp1
, cmp2
;
407 type
= SOCKET_TYPE_CHAR_TCP_V6
;
410 type
= SOCKET_TYPE_CHAR_UDP_V6
;
414 /* XXX no multicast/broadcast */
416 prt
= ntohs(in
->sin6_port
);
418 cmp1
= *swrap_ipv6();
419 cmp2
= in
->sin6_addr
;
420 cmp2
.s6_addr
[15] = 0;
421 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
422 iface
= in
->sin6_addr
.s6_addr
[15];
442 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
443 socket_wrapper_dir());
444 /* the caller need to do more processing */
448 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
449 socket_wrapper_dir(), type
, iface
, prt
);
454 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
463 if (bcast
) *bcast
= 0;
465 switch (si
->family
) {
467 const struct sockaddr_in
*in
=
468 (const struct sockaddr_in
*)(const void *)inaddr
;
469 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
475 prt
= ntohs(in
->sin_port
);
479 u_type
= SOCKET_TYPE_CHAR_TCP
;
480 d_type
= SOCKET_TYPE_CHAR_TCP
;
483 u_type
= SOCKET_TYPE_CHAR_UDP
;
484 d_type
= SOCKET_TYPE_CHAR_UDP
;
485 a_type
= SOCKET_TYPE_CHAR_UDP
;
486 b_type
= SOCKET_TYPE_CHAR_UDP
;
494 iface
= socket_wrapper_default_iface();
495 } else if (a_type
&& addr
== 0xFFFFFFFF) {
496 /* 255.255.255.255 only udp */
499 iface
= socket_wrapper_default_iface();
500 } else if (b_type
&& addr
== 0x7FFFFFFF) {
501 /* 127.255.255.255 only udp */
504 iface
= socket_wrapper_default_iface();
505 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
509 iface
= (addr
& 0x000000FF);
511 errno
= EADDRNOTAVAIL
;
518 const struct sockaddr_in6
*in
=
519 (const struct sockaddr_in6
*)(const void *)inaddr
;
520 struct in6_addr cmp1
, cmp2
;
524 type
= SOCKET_TYPE_CHAR_TCP_V6
;
527 type
= SOCKET_TYPE_CHAR_UDP_V6
;
531 /* XXX no multicast/broadcast */
533 prt
= ntohs(in
->sin6_port
);
535 cmp1
= *swrap_ipv6();
536 cmp2
= in
->sin6_addr
;
537 cmp2
.s6_addr
[15] = 0;
538 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
539 iface
= socket_wrapper_default_iface();
540 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
541 iface
= in
->sin6_addr
.s6_addr
[15];
543 errno
= EADDRNOTAVAIL
;
551 errno
= EADDRNOTAVAIL
;
556 if (bcast
) *bcast
= is_bcast
;
558 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
564 /* handle auto-allocation of ephemeral ports */
565 for (prt
= 5001; prt
< 10000; prt
++) {
566 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
567 socket_wrapper_dir(), type
, iface
, prt
);
568 if (stat(un
->sun_path
, &st
) == 0) continue;
570 set_port(si
->family
, prt
, si
->myname
);
579 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
580 socket_wrapper_dir(), type
, iface
, prt
);
584 static struct socket_info
*find_socket_info(int fd
)
586 struct socket_info
*i
;
587 for (i
= sockets
; i
; i
= i
->next
) {
595 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
596 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
598 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
602 out
->sa_family
= AF_UNIX
;
603 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
604 out
->sa_len
= sizeof(*out_addr
);
607 switch (in_addr
->sa_family
) {
617 errno
= ESOCKTNOSUPPORT
;
621 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
623 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
629 errno
= EAFNOSUPPORT
;
633 static int sockaddr_convert_from_un(const struct socket_info
*si
,
634 const struct sockaddr_un
*in_addr
,
635 socklen_t un_addrlen
,
637 struct sockaddr
*out_addr
,
638 socklen_t
*out_addrlen
)
642 if (out_addr
== NULL
|| out_addrlen
== NULL
)
645 if (un_addrlen
== 0) {
660 errno
= ESOCKTNOSUPPORT
;
663 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
664 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
665 out_addr
->sa_len
= *out_addrlen
;
672 errno
= EAFNOSUPPORT
;
676 enum swrap_packet_type
{
678 SWRAP_CONNECT_UNREACH
,
686 SWRAP_SENDTO_UNREACH
,
697 struct swrap_file_hdr
{
699 uint16_t version_major
;
700 uint16_t version_minor
;
703 uint32_t frame_max_len
;
704 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
707 #define SWRAP_FILE_HDR_SIZE 24
709 struct swrap_packet_frame
{
711 uint32_t micro_seconds
;
712 uint32_t recorded_length
;
713 uint32_t full_length
;
715 #define SWRAP_PACKET_FRAME_SIZE 16
717 union swrap_packet_ip
{
721 uint16_t packet_length
;
722 uint16_t identification
;
727 uint16_t hdr_checksum
;
731 #define SWRAP_PACKET_IP_V4_SIZE 20
734 uint8_t flow_label_high
;
735 uint16_t flow_label_low
;
736 uint16_t payload_length
;
739 uint8_t src_addr
[16];
740 uint8_t dest_addr
[16];
742 #define SWRAP_PACKET_IP_V6_SIZE 40
744 #define SWRAP_PACKET_IP_SIZE 40
746 union swrap_packet_payload
{
748 uint16_t source_port
;
758 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
760 uint16_t source_port
;
765 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
772 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
779 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
781 #define SWRAP_PACKET_PAYLOAD_SIZE 20
783 #define SWRAP_PACKET_MIN_ALLOC \
784 (SWRAP_PACKET_FRAME_SIZE + \
785 SWRAP_PACKET_IP_SIZE + \
786 SWRAP_PACKET_PAYLOAD_SIZE)
788 static const char *socket_wrapper_pcap_file(void)
790 static int initialized
= 0;
791 static const char *s
= NULL
;
792 static const struct swrap_file_hdr h
;
793 static const struct swrap_packet_frame f
;
794 static const union swrap_packet_ip i
;
795 static const union swrap_packet_payload p
;
797 if (initialized
== 1) {
803 * TODO: don't use the structs use plain buffer offsets
804 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
806 * for now make sure we disable PCAP support
807 * if the struct has alignment!
809 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
812 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
815 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
818 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
821 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
824 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
827 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
830 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
833 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
836 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
840 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
844 if (strncmp(s
, "./", 2) == 0) {
850 static uint8_t *swrap_packet_init(struct timeval
*tval
,
851 const struct sockaddr
*src
,
852 const struct sockaddr
*dest
,
854 const uint8_t *payload
,
856 unsigned long tcp_seqno
,
857 unsigned long tcp_ack
,
858 unsigned char tcp_ctl
,
864 struct swrap_packet_frame
*frame
;
865 union swrap_packet_ip
*ip
;
866 union swrap_packet_payload
*pay
;
869 size_t nonwire_len
= sizeof(*frame
);
870 size_t wire_hdr_len
= 0;
872 size_t ip_hdr_len
= 0;
873 size_t icmp_hdr_len
= 0;
874 size_t icmp_truncate_len
= 0;
875 uint8_t protocol
= 0, icmp_protocol
= 0;
876 const struct sockaddr_in
*src_in
= NULL
;
877 const struct sockaddr_in
*dest_in
= NULL
;
879 const struct sockaddr_in6
*src_in6
= NULL
;
880 const struct sockaddr_in6
*dest_in6
= NULL
;
885 switch (src
->sa_family
) {
887 src_in
= (const struct sockaddr_in
*)src
;
888 dest_in
= (const struct sockaddr_in
*)dest
;
889 src_port
= src_in
->sin_port
;
890 dest_port
= dest_in
->sin_port
;
891 ip_hdr_len
= sizeof(ip
->v4
);
895 src_in6
= (const struct sockaddr_in6
*)src
;
896 dest_in6
= (const struct sockaddr_in6
*)dest
;
897 src_port
= src_in6
->sin6_port
;
898 dest_port
= dest_in6
->sin6_port
;
899 ip_hdr_len
= sizeof(ip
->v6
);
906 switch (socket_type
) {
908 protocol
= 0x06; /* TCP */
909 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
910 wire_len
= wire_hdr_len
+ payload_len
;
914 protocol
= 0x11; /* UDP */
915 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
916 wire_len
= wire_hdr_len
+ payload_len
;
924 icmp_protocol
= protocol
;
925 switch (src
->sa_family
) {
927 protocol
= 0x01; /* ICMPv4 */
928 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
932 protocol
= 0x3A; /* ICMPv6 */
933 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
937 if (wire_len
> 64 ) {
938 icmp_truncate_len
= wire_len
- 64;
940 wire_hdr_len
+= icmp_hdr_len
;
941 wire_len
+= icmp_hdr_len
;
944 packet_len
= nonwire_len
+ wire_len
;
945 alloc_len
= packet_len
;
946 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
947 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
950 base
= (uint8_t *)malloc(alloc_len
);
951 if (!base
) return NULL
;
955 frame
= (struct swrap_packet_frame
*)buf
;
956 frame
->seconds
= tval
->tv_sec
;
957 frame
->micro_seconds
= tval
->tv_usec
;
958 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
959 frame
->full_length
= wire_len
- icmp_truncate_len
;
960 buf
+= SWRAP_PACKET_FRAME_SIZE
;
962 ip
= (union swrap_packet_ip
*)buf
;
963 switch (src
->sa_family
) {
965 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
967 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
968 ip
->v4
.identification
= htons(0xFFFF);
969 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
970 ip
->v4
.fragment
= htons(0x0000);
972 ip
->v4
.protocol
= protocol
;
973 ip
->v4
.hdr_checksum
= htons(0x0000);
974 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
975 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
976 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
980 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
981 ip
->v6
.flow_label_high
= 0x00;
982 ip
->v6
.flow_label_low
= 0x0000;
983 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
984 ip
->v6
.next_header
= protocol
;
985 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
986 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
987 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
993 pay
= (union swrap_packet_payload
*)buf
;
994 switch (src
->sa_family
) {
996 pay
->icmp4
.type
= 0x03; /* destination unreachable */
997 pay
->icmp4
.code
= 0x01; /* host unreachable */
998 pay
->icmp4
.checksum
= htons(0x0000);
999 pay
->icmp4
.unused
= htonl(0x00000000);
1000 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1002 /* set the ip header in the ICMP payload */
1003 ip
= (union swrap_packet_ip
*)buf
;
1004 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1006 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1007 ip
->v4
.identification
= htons(0xFFFF);
1008 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
1009 ip
->v4
.fragment
= htons(0x0000);
1011 ip
->v4
.protocol
= icmp_protocol
;
1012 ip
->v4
.hdr_checksum
= htons(0x0000);
1013 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1014 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1015 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1017 src_port
= dest_in
->sin_port
;
1018 dest_port
= src_in
->sin_port
;
1022 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1023 pay
->icmp6
.code
= 0x03; /* address unreachable */
1024 pay
->icmp6
.checksum
= htons(0x0000);
1025 pay
->icmp6
.unused
= htonl(0x00000000);
1026 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1028 /* set the ip header in the ICMP payload */
1029 ip
= (union swrap_packet_ip
*)buf
;
1030 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1031 ip
->v6
.flow_label_high
= 0x00;
1032 ip
->v6
.flow_label_low
= 0x0000;
1033 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1034 ip
->v6
.next_header
= protocol
;
1035 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1036 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1037 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1039 src_port
= dest_in6
->sin6_port
;
1040 dest_port
= src_in6
->sin6_port
;
1046 pay
= (union swrap_packet_payload
*)buf
;
1048 switch (socket_type
) {
1050 pay
->tcp
.source_port
= src_port
;
1051 pay
->tcp
.dest_port
= dest_port
;
1052 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1053 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1054 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1055 pay
->tcp
.control
= tcp_ctl
;
1056 pay
->tcp
.window
= htons(0x7FFF);
1057 pay
->tcp
.checksum
= htons(0x0000);
1058 pay
->tcp
.urg
= htons(0x0000);
1059 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1064 pay
->udp
.source_port
= src_port
;
1065 pay
->udp
.dest_port
= dest_port
;
1066 pay
->udp
.length
= htons(8 + payload_len
);
1067 pay
->udp
.checksum
= htons(0x0000);
1068 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1073 if (payload
&& payload_len
> 0) {
1074 memcpy(buf
, payload
, payload_len
);
1077 *_packet_len
= packet_len
- icmp_truncate_len
;
1081 static int swrap_get_pcap_fd(const char *fname
)
1085 if (fd
!= -1) return fd
;
1087 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1089 struct swrap_file_hdr file_hdr
;
1090 file_hdr
.magic
= 0xA1B2C3D4;
1091 file_hdr
.version_major
= 0x0002;
1092 file_hdr
.version_minor
= 0x0004;
1093 file_hdr
.timezone
= 0x00000000;
1094 file_hdr
.sigfigs
= 0x00000000;
1095 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1096 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1098 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1105 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1110 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1111 const struct sockaddr
*addr
,
1112 enum swrap_packet_type type
,
1113 const void *buf
, size_t len
,
1116 const struct sockaddr
*src_addr
;
1117 const struct sockaddr
*dest_addr
;
1118 unsigned long tcp_seqno
= 0;
1119 unsigned long tcp_ack
= 0;
1120 unsigned char tcp_ctl
= 0;
1121 int unreachable
= 0;
1125 switch (si
->family
) {
1137 case SWRAP_CONNECT_SEND
:
1138 if (si
->type
!= SOCK_STREAM
) return NULL
;
1140 src_addr
= si
->myname
;
1143 tcp_seqno
= si
->io
.pck_snd
;
1144 tcp_ack
= si
->io
.pck_rcv
;
1145 tcp_ctl
= 0x02; /* SYN */
1147 si
->io
.pck_snd
+= 1;
1151 case SWRAP_CONNECT_RECV
:
1152 if (si
->type
!= SOCK_STREAM
) return NULL
;
1154 dest_addr
= si
->myname
;
1157 tcp_seqno
= si
->io
.pck_rcv
;
1158 tcp_ack
= si
->io
.pck_snd
;
1159 tcp_ctl
= 0x12; /** SYN,ACK */
1161 si
->io
.pck_rcv
+= 1;
1165 case SWRAP_CONNECT_UNREACH
:
1166 if (si
->type
!= SOCK_STREAM
) return NULL
;
1168 dest_addr
= si
->myname
;
1171 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1172 tcp_seqno
= si
->io
.pck_snd
- 1;
1173 tcp_ack
= si
->io
.pck_rcv
;
1174 tcp_ctl
= 0x02; /* SYN */
1179 case SWRAP_CONNECT_ACK
:
1180 if (si
->type
!= SOCK_STREAM
) return NULL
;
1182 src_addr
= si
->myname
;
1185 tcp_seqno
= si
->io
.pck_snd
;
1186 tcp_ack
= si
->io
.pck_rcv
;
1187 tcp_ctl
= 0x10; /* ACK */
1191 case SWRAP_ACCEPT_SEND
:
1192 if (si
->type
!= SOCK_STREAM
) return NULL
;
1194 dest_addr
= si
->myname
;
1197 tcp_seqno
= si
->io
.pck_rcv
;
1198 tcp_ack
= si
->io
.pck_snd
;
1199 tcp_ctl
= 0x02; /* SYN */
1201 si
->io
.pck_rcv
+= 1;
1205 case SWRAP_ACCEPT_RECV
:
1206 if (si
->type
!= SOCK_STREAM
) return NULL
;
1208 src_addr
= si
->myname
;
1211 tcp_seqno
= si
->io
.pck_snd
;
1212 tcp_ack
= si
->io
.pck_rcv
;
1213 tcp_ctl
= 0x12; /* SYN,ACK */
1215 si
->io
.pck_snd
+= 1;
1219 case SWRAP_ACCEPT_ACK
:
1220 if (si
->type
!= SOCK_STREAM
) return NULL
;
1222 dest_addr
= si
->myname
;
1225 tcp_seqno
= si
->io
.pck_rcv
;
1226 tcp_ack
= si
->io
.pck_snd
;
1227 tcp_ctl
= 0x10; /* ACK */
1232 src_addr
= si
->myname
;
1233 dest_addr
= si
->peername
;
1235 tcp_seqno
= si
->io
.pck_snd
;
1236 tcp_ack
= si
->io
.pck_rcv
;
1237 tcp_ctl
= 0x18; /* PSH,ACK */
1239 si
->io
.pck_snd
+= len
;
1243 case SWRAP_SEND_RST
:
1244 dest_addr
= si
->myname
;
1245 src_addr
= si
->peername
;
1247 if (si
->type
== SOCK_DGRAM
) {
1248 return swrap_marshall_packet(si
, si
->peername
,
1249 SWRAP_SENDTO_UNREACH
,
1250 buf
, len
, packet_len
);
1253 tcp_seqno
= si
->io
.pck_rcv
;
1254 tcp_ack
= si
->io
.pck_snd
;
1255 tcp_ctl
= 0x14; /** RST,ACK */
1259 case SWRAP_PENDING_RST
:
1260 dest_addr
= si
->myname
;
1261 src_addr
= si
->peername
;
1263 if (si
->type
== SOCK_DGRAM
) {
1267 tcp_seqno
= si
->io
.pck_rcv
;
1268 tcp_ack
= si
->io
.pck_snd
;
1269 tcp_ctl
= 0x14; /* RST,ACK */
1274 dest_addr
= si
->myname
;
1275 src_addr
= si
->peername
;
1277 tcp_seqno
= si
->io
.pck_rcv
;
1278 tcp_ack
= si
->io
.pck_snd
;
1279 tcp_ctl
= 0x18; /* PSH,ACK */
1281 si
->io
.pck_rcv
+= len
;
1285 case SWRAP_RECV_RST
:
1286 dest_addr
= si
->myname
;
1287 src_addr
= si
->peername
;
1289 if (si
->type
== SOCK_DGRAM
) {
1293 tcp_seqno
= si
->io
.pck_rcv
;
1294 tcp_ack
= si
->io
.pck_snd
;
1295 tcp_ctl
= 0x14; /* RST,ACK */
1300 src_addr
= si
->myname
;
1303 si
->io
.pck_snd
+= len
;
1307 case SWRAP_SENDTO_UNREACH
:
1308 dest_addr
= si
->myname
;
1315 case SWRAP_RECVFROM
:
1316 dest_addr
= si
->myname
;
1319 si
->io
.pck_rcv
+= len
;
1323 case SWRAP_CLOSE_SEND
:
1324 if (si
->type
!= SOCK_STREAM
) return NULL
;
1326 src_addr
= si
->myname
;
1327 dest_addr
= si
->peername
;
1329 tcp_seqno
= si
->io
.pck_snd
;
1330 tcp_ack
= si
->io
.pck_rcv
;
1331 tcp_ctl
= 0x11; /* FIN, ACK */
1333 si
->io
.pck_snd
+= 1;
1337 case SWRAP_CLOSE_RECV
:
1338 if (si
->type
!= SOCK_STREAM
) return NULL
;
1340 dest_addr
= si
->myname
;
1341 src_addr
= si
->peername
;
1343 tcp_seqno
= si
->io
.pck_rcv
;
1344 tcp_ack
= si
->io
.pck_snd
;
1345 tcp_ctl
= 0x11; /* FIN,ACK */
1347 si
->io
.pck_rcv
+= 1;
1351 case SWRAP_CLOSE_ACK
:
1352 if (si
->type
!= SOCK_STREAM
) return NULL
;
1354 src_addr
= si
->myname
;
1355 dest_addr
= si
->peername
;
1357 tcp_seqno
= si
->io
.pck_snd
;
1358 tcp_ack
= si
->io
.pck_rcv
;
1359 tcp_ctl
= 0x10; /* ACK */
1366 swrapGetTimeOfDay(&tv
);
1368 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1369 (const uint8_t *)buf
, len
,
1370 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1374 static void swrap_dump_packet(struct socket_info
*si
,
1375 const struct sockaddr
*addr
,
1376 enum swrap_packet_type type
,
1377 const void *buf
, size_t len
)
1379 const char *file_name
;
1381 size_t packet_len
= 0;
1384 file_name
= socket_wrapper_pcap_file();
1389 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1394 fd
= swrap_get_pcap_fd(file_name
);
1396 if (write(fd
, packet
, packet_len
) != packet_len
) {
1405 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1407 struct socket_info
*si
;
1409 int real_type
= type
;
1411 real_type
&= ~SOCK_CLOEXEC
;
1413 #ifdef SOCK_NONBLOCK
1414 real_type
&= ~SOCK_NONBLOCK
;
1417 if (!socket_wrapper_dir()) {
1418 return real_socket(family
, type
, protocol
);
1428 return real_socket(family
, type
, protocol
);
1430 errno
= EAFNOSUPPORT
;
1434 switch (real_type
) {
1440 errno
= EPROTONOSUPPORT
;
1448 if (real_type
== SOCK_STREAM
) {
1453 if (real_type
== SOCK_DGRAM
) {
1458 errno
= EPROTONOSUPPORT
;
1462 /* We must call real_socket with type, from the caller, not the version we removed
1463 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1464 fd
= real_socket(AF_UNIX
, type
, 0);
1466 if (fd
== -1) return -1;
1468 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1470 si
->family
= family
;
1472 /* however, the rest of the socket_wrapper code expects just
1473 * the type, not the flags */
1474 si
->type
= real_type
;
1475 si
->protocol
= protocol
;
1478 SWRAP_DLIST_ADD(sockets
, si
);
1483 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1485 struct socket_info
*parent_si
, *child_si
;
1487 struct sockaddr_un un_addr
;
1488 socklen_t un_addrlen
= sizeof(un_addr
);
1489 struct sockaddr_un un_my_addr
;
1490 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1491 struct sockaddr
*my_addr
;
1492 socklen_t my_addrlen
, len
;
1495 parent_si
= find_socket_info(s
);
1497 return real_accept(s
, addr
, addrlen
);
1501 * assume out sockaddr have the same size as the in parent
1504 my_addrlen
= socket_length(parent_si
->family
);
1505 if (my_addrlen
<= 0) {
1510 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1511 if (my_addr
== NULL
) {
1515 memset(&un_addr
, 0, sizeof(un_addr
));
1516 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1518 ret
= real_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
1527 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1528 parent_si
->family
, my_addr
, &len
);
1535 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1536 memset(child_si
, 0, sizeof(*child_si
));
1539 child_si
->family
= parent_si
->family
;
1540 child_si
->type
= parent_si
->type
;
1541 child_si
->protocol
= parent_si
->protocol
;
1542 child_si
->bound
= 1;
1543 child_si
->is_server
= 1;
1544 child_si
->connected
= 1;
1546 child_si
->peername_len
= len
;
1547 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1549 if (addr
!= NULL
&& addrlen
!= NULL
) {
1550 size_t copy_len
= MIN(*addrlen
, len
);
1552 memcpy(addr
, my_addr
, copy_len
);
1557 ret
= real_getsockname(fd
, (struct sockaddr
*)(void *)&un_my_addr
,
1566 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1567 child_si
->family
, my_addr
, &len
);
1575 child_si
->myname_len
= len
;
1576 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1579 SWRAP_DLIST_ADD(sockets
, child_si
);
1581 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1582 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1583 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1588 static int autobind_start_init
;
1589 static int autobind_start
;
1591 /* using sendto() or connect() on an unbound socket would give the
1592 recipient no way to reply, as unlike UDP and TCP, a unix domain
1593 socket can't auto-assign emphemeral port numbers, so we need to
1595 Note: this might change the family from ipv6 to ipv4
1597 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1599 struct sockaddr_un un_addr
;
1606 if (autobind_start_init
!= 1) {
1607 autobind_start_init
= 1;
1608 autobind_start
= getpid();
1609 autobind_start
%= 50000;
1610 autobind_start
+= 10000;
1613 un_addr
.sun_family
= AF_UNIX
;
1617 struct sockaddr_in in
;
1621 type
= SOCKET_TYPE_CHAR_TCP
;
1624 type
= SOCKET_TYPE_CHAR_UDP
;
1627 errno
= ESOCKTNOSUPPORT
;
1631 memset(&in
, 0, sizeof(in
));
1632 in
.sin_family
= AF_INET
;
1633 in
.sin_addr
.s_addr
= htonl(127<<24 |
1634 socket_wrapper_default_iface());
1636 si
->myname_len
= sizeof(in
);
1637 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1642 struct sockaddr_in6 in6
;
1644 if (si
->family
!= family
) {
1645 errno
= ENETUNREACH
;
1651 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1654 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1657 errno
= ESOCKTNOSUPPORT
;
1661 memset(&in6
, 0, sizeof(in6
));
1662 in6
.sin6_family
= AF_INET6
;
1663 in6
.sin6_addr
= *swrap_ipv6();
1664 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1665 si
->myname_len
= sizeof(in6
);
1666 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1671 errno
= ESOCKTNOSUPPORT
;
1675 if (autobind_start
> 60000) {
1676 autobind_start
= 10000;
1679 for (i
=0;i
<1000;i
++) {
1680 port
= autobind_start
+ i
;
1681 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1682 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1683 type
, socket_wrapper_default_iface(), port
);
1684 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1686 ret
= real_bind(si
->fd
, (struct sockaddr
*)(void *)&un_addr
,
1688 if (ret
== -1) return ret
;
1690 si
->tmp_path
= strdup(un_addr
.sun_path
);
1692 autobind_start
= port
+ 1;
1700 si
->family
= family
;
1701 set_port(si
->family
, port
, si
->myname
);
1707 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1710 struct sockaddr_un un_addr
;
1711 struct socket_info
*si
= find_socket_info(s
);
1715 return real_connect(s
, serv_addr
, addrlen
);
1718 if (si
->bound
== 0) {
1719 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1720 if (ret
== -1) return -1;
1723 if (si
->family
!= serv_addr
->sa_family
) {
1728 ret
= sockaddr_convert_to_un(si
, serv_addr
,
1729 addrlen
, &un_addr
, 0, &bcast
);
1730 if (ret
== -1) return -1;
1733 errno
= ENETUNREACH
;
1737 if (si
->type
== SOCK_DGRAM
) {
1738 si
->defer_connect
= 1;
1741 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1743 ret
= real_connect(s
, (struct sockaddr
*)(void *)&un_addr
,
1744 sizeof(struct sockaddr_un
));
1747 /* to give better errors */
1748 if (ret
== -1 && errno
== ENOENT
) {
1749 errno
= EHOSTUNREACH
;
1753 si
->peername_len
= addrlen
;
1754 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1757 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1758 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1760 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1766 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1769 struct sockaddr_un un_addr
;
1770 struct socket_info
*si
= find_socket_info(s
);
1773 return real_bind(s
, myaddr
, addrlen
);
1776 si
->myname_len
= addrlen
;
1777 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1779 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1780 if (ret
== -1) return -1;
1782 unlink(un_addr
.sun_path
);
1784 ret
= real_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
1785 sizeof(struct sockaddr_un
));
1794 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1797 struct socket_info
*si
= find_socket_info(s
);
1800 return real_listen(s
, backlog
);
1803 ret
= real_listen(s
, backlog
);
1808 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1810 struct socket_info
*si
= find_socket_info(s
);
1813 return real_getpeername(s
, name
, addrlen
);
1822 memcpy(name
, si
->peername
, si
->peername_len
);
1823 *addrlen
= si
->peername_len
;
1828 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1830 struct socket_info
*si
= find_socket_info(s
);
1833 return real_getsockname(s
, name
, addrlen
);
1836 memcpy(name
, si
->myname
, si
->myname_len
);
1837 *addrlen
= si
->myname_len
;
1842 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1844 struct socket_info
*si
= find_socket_info(s
);
1847 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1850 if (level
== SOL_SOCKET
) {
1851 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1854 errno
= ENOPROTOOPT
;
1858 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1860 struct socket_info
*si
= find_socket_info(s
);
1863 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1866 if (level
== SOL_SOCKET
) {
1867 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1870 switch (si
->family
) {
1878 errno
= ENOPROTOOPT
;
1883 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1886 struct socket_info
*si
= find_socket_info(s
);
1890 return real_ioctl(s
, r
, p
);
1893 ret
= real_ioctl(s
, r
, p
);
1897 value
= *((int *)p
);
1898 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1899 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1900 } else if (value
== 0) { /* END OF FILE */
1901 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1909 static ssize_t
swrap_sendmsg_before(struct socket_info
*si
,
1911 struct iovec
*tmp_iov
,
1912 struct sockaddr_un
*tmp_un
,
1913 const struct sockaddr_un
**to_un
,
1914 const struct sockaddr
**to
,
1932 if (!si
->connected
) {
1937 if (msg
->msg_iovlen
== 0) {
1942 * cut down to 1500 byte packets for stream sockets,
1943 * which makes it easier to format PCAP capture files
1944 * (as the caller will simply continue from here)
1947 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
1949 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
1954 msg
->msg_iovlen
= i
;
1955 if (msg
->msg_iovlen
== 0) {
1956 *tmp_iov
= msg
->msg_iov
[0];
1957 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, 1500);
1958 msg
->msg_iov
= tmp_iov
;
1959 msg
->msg_iovlen
= 1;
1964 if (si
->connected
) {
1965 if (msg
->msg_name
) {
1970 const struct sockaddr
*msg_name
;
1971 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
1973 if (msg_name
== NULL
) {
1979 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
1981 if (ret
== -1) return -1;
1989 msg
->msg_name
= tmp_un
;
1990 msg
->msg_namelen
= sizeof(*tmp_un
);
1993 if (si
->bound
== 0) {
1994 ret
= swrap_auto_bind(si
, si
->family
);
1995 if (ret
== -1) return -1;
1998 if (!si
->defer_connect
) {
2002 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2004 if (ret
== -1) return -1;
2006 ret
= real_connect(si
->fd
, (struct sockaddr
*)(void *)tmp_un
,
2009 /* to give better errors */
2010 if (ret
== -1 && errno
== ENOENT
) {
2011 errno
= EHOSTUNREACH
;
2018 si
->defer_connect
= 0;
2021 errno
= EHOSTUNREACH
;
2028 static void swrap_sendmsg_after(struct socket_info
*si
,
2030 const struct sockaddr
*to
,
2033 int saved_errno
= errno
;
2040 /* to give better errors */
2041 if (ret
== -1 && saved_errno
== ENOENT
) {
2042 saved_errno
= EHOSTUNREACH
;
2045 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2046 avail
+= msg
->msg_iov
[i
].iov_len
;
2050 remain
= MIN(80, avail
);
2055 /* we capture it as one single packet */
2056 buf
= (uint8_t *)malloc(remain
);
2058 /* we just not capture the packet */
2059 errno
= saved_errno
;
2063 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2064 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2066 msg
->msg_iov
[i
].iov_base
,
2069 remain
-= this_time
;
2076 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2077 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2079 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2084 if (si
->connected
) {
2088 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2089 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
2091 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2097 errno
= saved_errno
;
2100 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
2102 struct sockaddr_un un_addr
;
2103 socklen_t un_addrlen
= sizeof(un_addr
);
2105 struct socket_info
*si
= find_socket_info(s
);
2106 struct sockaddr_storage ss
;
2107 socklen_t ss_len
= sizeof(ss
);
2110 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
2114 from
= (struct sockaddr
*)(void *)&ss
;
2118 if (si
->type
== SOCK_STREAM
) {
2119 /* cut down to 1500 byte packets for stream sockets,
2120 * which makes it easier to format PCAP capture files
2121 * (as the caller will simply continue from here) */
2122 len
= MIN(len
, 1500);
2125 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2126 memset(&un_addr
, 0, sizeof(un_addr
));
2127 ret
= real_recvfrom(s
, buf
, len
, flags
,
2128 (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2132 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
2133 si
->family
, from
, fromlen
) == -1) {
2137 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
2143 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
2147 struct sockaddr_un un_addr
;
2148 const struct sockaddr_un
*to_un
= NULL
;
2150 struct socket_info
*si
= find_socket_info(s
);
2154 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
2157 tmp
.iov_base
= discard_const_p(char, buf
);
2161 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
2162 msg
.msg_namelen
= tolen
; /* size of address */
2163 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2164 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2165 #if 0 /* not available on solaris */
2166 msg
.msg_control
= NULL
; /* ancillary data, see below */
2167 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2168 msg
.msg_flags
= 0; /* flags on received message */
2171 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2172 if (ret
== -1) return -1;
2174 buf
= msg
.msg_iov
[0].iov_base
;
2175 len
= msg
.msg_iov
[0].iov_len
;
2180 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2183 type
= SOCKET_TYPE_CHAR_UDP
;
2185 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2186 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2187 socket_wrapper_dir(), type
, iface
, prt
);
2188 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2190 /* ignore the any errors in broadcast sends */
2191 real_sendto(s
, buf
, len
, flags
,
2192 (struct sockaddr
*)(void *)&un_addr
,
2196 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2201 ret
= real_sendto(s
, buf
, len
, flags
, msg
.msg_name
, msg
.msg_namelen
);
2203 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2208 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2211 struct socket_info
*si
= find_socket_info(s
);
2214 return real_recv(s
, buf
, len
, flags
);
2217 if (si
->type
== SOCK_STREAM
) {
2218 /* cut down to 1500 byte packets for stream sockets,
2219 * which makes it easier to format PCAP capture files
2220 * (as the caller will simply continue from here) */
2221 len
= MIN(len
, 1500);
2224 ret
= real_recv(s
, buf
, len
, flags
);
2225 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2226 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2227 } else if (ret
== 0) { /* END OF FILE */
2228 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2229 } else if (ret
> 0) {
2230 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2236 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2239 struct socket_info
*si
= find_socket_info(s
);
2242 return real_read(s
, buf
, len
);
2245 if (si
->type
== SOCK_STREAM
) {
2246 /* cut down to 1500 byte packets for stream sockets,
2247 * which makes it easier to format PCAP capture files
2248 * (as the caller will simply continue from here) */
2249 len
= MIN(len
, 1500);
2252 ret
= real_read(s
, buf
, len
);
2253 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2254 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2255 } else if (ret
== 0) { /* END OF FILE */
2256 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2257 } else if (ret
> 0) {
2258 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2265 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2269 struct sockaddr_un un_addr
;
2271 struct socket_info
*si
= find_socket_info(s
);
2274 return real_send(s
, buf
, len
, flags
);
2277 tmp
.iov_base
= discard_const_p(char, buf
);
2281 msg
.msg_name
= NULL
; /* optional address */
2282 msg
.msg_namelen
= 0; /* size of address */
2283 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2284 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2285 #if 0 /* not available on solaris */
2286 msg
.msg_control
= NULL
; /* ancillary data, see below */
2287 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2288 msg
.msg_flags
= 0; /* flags on received message */
2291 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2292 if (ret
== -1) return -1;
2294 buf
= msg
.msg_iov
[0].iov_base
;
2295 len
= msg
.msg_iov
[0].iov_len
;
2297 ret
= real_send(s
, buf
, len
, flags
);
2299 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2304 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
2308 struct sockaddr_un un_addr
;
2309 const struct sockaddr_un
*to_un
= NULL
;
2310 const struct sockaddr
*to
= NULL
;
2312 struct socket_info
*si
= find_socket_info(s
);
2316 return real_sendmsg(s
, omsg
, flags
);
2319 tmp
.iov_base
= NULL
;
2324 msg
.msg_name
= omsg
->msg_name
; /* optional address */
2325 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
2326 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
2327 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
2328 /* the following is not available on solaris */
2329 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
2330 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
2331 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
2334 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2335 if (ret
== -1) return -1;
2340 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2348 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2349 avail
+= msg
.msg_iov
[i
].iov_len
;
2355 /* we capture it as one single packet */
2356 buf
= (uint8_t *)malloc(remain
);
2361 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2362 size_t this_time
= MIN(remain
, msg
.msg_iov
[i
].iov_len
);
2364 msg
.msg_iov
[i
].iov_base
,
2367 remain
-= this_time
;
2370 type
= SOCKET_TYPE_CHAR_UDP
;
2372 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2373 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2374 socket_wrapper_dir(), type
, iface
, prt
);
2375 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2377 msg
.msg_name
= &un_addr
; /* optional address */
2378 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
2380 /* ignore the any errors in broadcast sends */
2381 real_sendmsg(s
, &msg
, flags
);
2384 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2390 ret
= real_sendmsg(s
, &msg
, flags
);
2392 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2397 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2400 struct socket_info
*si
= find_socket_info(s
);
2404 return real_readv(s
, vector
, count
);
2407 if (!si
->connected
) {
2412 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2413 /* cut down to 1500 byte packets for stream sockets,
2414 * which makes it easier to format PCAP capture files
2415 * (as the caller will simply continue from here) */
2418 for (i
=0; i
< count
; i
++) {
2420 nlen
= len
+ vector
[i
].iov_len
;
2428 v
.iov_len
= MIN(v
.iov_len
, 1500);
2434 ret
= real_readv(s
, vector
, count
);
2435 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2436 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2437 } else if (ret
== 0) { /* END OF FILE */
2438 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2439 } else if (ret
> 0) {
2443 size_t remain
= ret
;
2445 /* we capture it as one single packet */
2446 buf
= (uint8_t *)malloc(ret
);
2448 /* we just not capture the packet */
2453 for (i
=0; i
< count
; i
++) {
2454 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2459 remain
-= this_time
;
2462 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2469 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2473 struct sockaddr_un un_addr
;
2475 struct socket_info
*si
= find_socket_info(s
);
2478 return real_writev(s
, vector
, count
);
2481 tmp
.iov_base
= NULL
;
2485 msg
.msg_name
= NULL
; /* optional address */
2486 msg
.msg_namelen
= 0; /* size of address */
2487 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
2488 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
2489 #if 0 /* not available on solaris */
2490 msg
.msg_control
= NULL
; /* ancillary data, see below */
2491 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2492 msg
.msg_flags
= 0; /* flags on received message */
2495 ret
= swrap_sendmsg_before(si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2496 if (ret
== -1) return -1;
2498 ret
= real_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
2500 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2505 _PUBLIC_
int swrap_close(int fd
)
2507 struct socket_info
*si
= find_socket_info(fd
);
2511 return real_close(fd
);
2514 SWRAP_DLIST_REMOVE(sockets
, si
);
2516 if (si
->myname
&& si
->peername
) {
2517 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2520 ret
= real_close(fd
);
2522 if (si
->myname
&& si
->peername
) {
2523 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2524 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2527 if (si
->myname
) free(si
->myname
);
2528 if (si
->peername
) free(si
->peername
);
2530 unlink(si
->tmp_path
);
2538 _PUBLIC_
int swrap_dup(int fd
)
2540 struct socket_info
*si
, *si2
;
2543 si
= find_socket_info(fd
);
2546 return real_dup(fd
);
2550 /* we would need reference counting to handle this */
2560 si2
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2567 /* copy the whole structure, then duplicate pointer elements */
2573 si2
->myname
= sockaddr_dup(si2
->myname
, si2
->myname_len
);
2574 if (si2
->myname
== NULL
) {
2581 if (si2
->peername
) {
2582 si2
->peername
= sockaddr_dup(si2
->peername
, si2
->peername_len
);
2583 if (si2
->peername
== NULL
) {
2590 SWRAP_DLIST_ADD(sockets
, si2
);
2594 _PUBLIC_
int swrap_dup2(int fd
, int newfd
)
2596 struct socket_info
*si
, *si2
;
2599 si
= find_socket_info(fd
);
2602 return real_dup2(fd
, newfd
);
2606 /* we would need reference counting to handle this */
2611 if (find_socket_info(newfd
)) {
2612 /* dup2() does an implicit close of newfd, which we
2613 * need to emulate */
2617 fd2
= real_dup2(fd
, newfd
);
2622 si2
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2629 /* copy the whole structure, then duplicate pointer elements */
2635 si2
->myname
= sockaddr_dup(si2
->myname
, si2
->myname_len
);
2636 if (si2
->myname
== NULL
) {
2643 if (si2
->peername
) {
2644 si2
->peername
= sockaddr_dup(si2
->peername
, si2
->peername_len
);
2645 if (si2
->peername
== NULL
) {
2652 SWRAP_DLIST_ADD(sockets
, si2
);