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 #ifdef HAVE_LIBREPLACE
46 #define SOCKET_WRAPPER_NOT_REPLACE
48 #include "system/network.h"
49 #include "system/filesys.h"
50 #include "system/time.h"
52 #else /* HAVE_LIBREPLACE */
54 #include <sys/types.h>
57 #include <sys/socket.h>
58 #include <sys/ioctl.h>
59 #ifdef HAVE_SYS_FILIO_H
60 #include <sys/filio.h>
64 #include <netinet/in.h>
65 #include <netinet/tcp.h>
72 #include <arpa/inet.h>
75 #define MIN(a,b) ((a)<(b)?(a):(b))
78 #ifndef discard_const_p
79 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
86 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
89 #endif /* HAVE_LIBREPLACE */
91 #include "socket_wrapper.h"
97 #define SWRAP_DLIST_ADD(list,item) do { \
99 (item)->prev = NULL; \
100 (item)->next = NULL; \
103 (item)->prev = NULL; \
104 (item)->next = (list); \
105 (list)->prev = (item); \
110 #define SWRAP_DLIST_REMOVE(list,item) do { \
111 if ((list) == (item)) { \
112 (list) = (item)->next; \
114 (list)->prev = NULL; \
117 if ((item)->prev) { \
118 (item)->prev->next = (item)->next; \
120 if ((item)->next) { \
121 (item)->next->prev = (item)->prev; \
124 (item)->prev = NULL; \
125 (item)->next = NULL; \
128 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
130 #define REWRITE_CALLS
133 #define real_accept accept
134 #define real_connect connect
135 #define real_bind bind
136 #define real_listen listen
137 #define real_getpeername getpeername
138 #define real_getsockname getsockname
139 #define real_getsockopt getsockopt
140 #define real_setsockopt setsockopt
141 #define real_recvfrom recvfrom
142 #define real_sendto sendto
143 #define real_sendmsg sendmsg
144 #define real_ioctl ioctl
145 #define real_recv recv
146 #define real_read read
147 #define real_send send
148 #define real_readv readv
149 #define real_writev writev
150 #define real_socket socket
151 #define real_close close
153 #define real_dup2 dup2
156 #ifdef HAVE_GETTIMEOFDAY_TZ
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
159 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
162 /* we need to use a very terse format here as IRIX 6.4 silently
163 truncates names to 16 chars, so if we use a longer name then we
164 can't tell which port a packet came from with recvfrom()
166 with this format we have 8 chars left for the directory name
168 #define SOCKET_FORMAT "%c%02X%04X"
169 #define SOCKET_TYPE_CHAR_TCP 'T'
170 #define SOCKET_TYPE_CHAR_UDP 'U'
171 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
172 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
174 /* This limit is to avoid broadcast sendto() needing to stat too many
175 * files. It may be raised (with a performance cost) to up to 254
176 * without changing the format above */
177 #define MAX_WRAPPED_INTERFACES 40
183 static const struct in6_addr
*swrap_ipv6(void)
185 static struct in6_addr v
;
186 static int initialized
;
194 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
203 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
205 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
206 memcpy(ret
, data
, len
);
210 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
214 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
218 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
224 static size_t socket_length(int family
)
228 return sizeof(struct sockaddr_in
);
231 return sizeof(struct sockaddr_in6
);
237 struct socket_info_fd
{
238 struct socket_info_fd
*prev
, *next
;
244 struct socket_info_fd
*fds
;
257 struct sockaddr
*myname
;
258 socklen_t myname_len
;
260 struct sockaddr
*peername
;
261 socklen_t peername_len
;
264 unsigned long pck_snd
;
265 unsigned long pck_rcv
;
268 struct socket_info
*prev
, *next
;
271 static struct socket_info
*sockets
;
273 const char *socket_wrapper_dir(void)
275 const char *s
= getenv("SOCKET_WRAPPER_DIR");
279 if (strncmp(s
, "./", 2) == 0) {
285 unsigned int socket_wrapper_default_iface(void)
287 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
290 if (sscanf(s
, "%u", &iface
) == 1) {
291 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
297 return 1;/* 127.0.0.1 */
300 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
307 p
= strrchr(un
->sun_path
, '/');
308 if (p
) p
++; else p
= un
->sun_path
;
310 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
315 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
326 case SOCKET_TYPE_CHAR_TCP
:
327 case SOCKET_TYPE_CHAR_UDP
: {
328 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
330 if ((*len
) < sizeof(*in2
)) {
335 memset(in2
, 0, sizeof(*in2
));
336 in2
->sin_family
= AF_INET
;
337 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
338 in2
->sin_port
= htons(prt
);
344 case SOCKET_TYPE_CHAR_TCP_V6
:
345 case SOCKET_TYPE_CHAR_UDP_V6
: {
346 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
348 if ((*len
) < sizeof(*in2
)) {
353 memset(in2
, 0, sizeof(*in2
));
354 in2
->sin6_family
= AF_INET6
;
355 in2
->sin6_addr
= *swrap_ipv6();
356 in2
->sin6_addr
.s6_addr
[15] = iface
;
357 in2
->sin6_port
= htons(prt
);
371 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
379 if (bcast
) *bcast
= 0;
381 switch (inaddr
->sa_family
) {
383 const struct sockaddr_in
*in
=
384 (const struct sockaddr_in
*)(const void *)inaddr
;
385 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
392 u_type
= SOCKET_TYPE_CHAR_TCP
;
395 u_type
= SOCKET_TYPE_CHAR_UDP
;
396 a_type
= SOCKET_TYPE_CHAR_UDP
;
397 b_type
= SOCKET_TYPE_CHAR_UDP
;
401 prt
= ntohs(in
->sin_port
);
402 if (a_type
&& addr
== 0xFFFFFFFF) {
403 /* 255.255.255.255 only udp */
406 iface
= socket_wrapper_default_iface();
407 } else if (b_type
&& addr
== 0x7FFFFFFF) {
408 /* 127.255.255.255 only udp */
411 iface
= socket_wrapper_default_iface();
412 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
416 iface
= (addr
& 0x000000FF);
421 if (bcast
) *bcast
= is_bcast
;
426 const struct sockaddr_in6
*in
=
427 (const struct sockaddr_in6
*)(const void *)inaddr
;
428 struct in6_addr cmp1
, cmp2
;
432 type
= SOCKET_TYPE_CHAR_TCP_V6
;
435 type
= SOCKET_TYPE_CHAR_UDP_V6
;
439 /* XXX no multicast/broadcast */
441 prt
= ntohs(in
->sin6_port
);
443 cmp1
= *swrap_ipv6();
444 cmp2
= in
->sin6_addr
;
445 cmp2
.s6_addr
[15] = 0;
446 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
447 iface
= in
->sin6_addr
.s6_addr
[15];
467 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
468 socket_wrapper_dir());
469 /* the caller need to do more processing */
473 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
474 socket_wrapper_dir(), type
, iface
, prt
);
479 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
488 if (bcast
) *bcast
= 0;
490 switch (si
->family
) {
492 const struct sockaddr_in
*in
=
493 (const struct sockaddr_in
*)(const void *)inaddr
;
494 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
500 prt
= ntohs(in
->sin_port
);
504 u_type
= SOCKET_TYPE_CHAR_TCP
;
505 d_type
= SOCKET_TYPE_CHAR_TCP
;
508 u_type
= SOCKET_TYPE_CHAR_UDP
;
509 d_type
= SOCKET_TYPE_CHAR_UDP
;
510 a_type
= SOCKET_TYPE_CHAR_UDP
;
511 b_type
= SOCKET_TYPE_CHAR_UDP
;
519 iface
= socket_wrapper_default_iface();
520 } else if (a_type
&& addr
== 0xFFFFFFFF) {
521 /* 255.255.255.255 only udp */
524 iface
= socket_wrapper_default_iface();
525 } else if (b_type
&& addr
== 0x7FFFFFFF) {
526 /* 127.255.255.255 only udp */
529 iface
= socket_wrapper_default_iface();
530 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
534 iface
= (addr
& 0x000000FF);
536 errno
= EADDRNOTAVAIL
;
543 const struct sockaddr_in6
*in
=
544 (const struct sockaddr_in6
*)(const void *)inaddr
;
545 struct in6_addr cmp1
, cmp2
;
549 type
= SOCKET_TYPE_CHAR_TCP_V6
;
552 type
= SOCKET_TYPE_CHAR_UDP_V6
;
556 /* XXX no multicast/broadcast */
558 prt
= ntohs(in
->sin6_port
);
560 cmp1
= *swrap_ipv6();
561 cmp2
= in
->sin6_addr
;
562 cmp2
.s6_addr
[15] = 0;
563 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
564 iface
= socket_wrapper_default_iface();
565 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
566 iface
= in
->sin6_addr
.s6_addr
[15];
568 errno
= EADDRNOTAVAIL
;
576 errno
= EADDRNOTAVAIL
;
581 if (bcast
) *bcast
= is_bcast
;
583 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
589 /* handle auto-allocation of ephemeral ports */
590 for (prt
= 5001; prt
< 10000; prt
++) {
591 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
592 socket_wrapper_dir(), type
, iface
, prt
);
593 if (stat(un
->sun_path
, &st
) == 0) continue;
595 set_port(si
->family
, prt
, si
->myname
);
604 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
605 socket_wrapper_dir(), type
, iface
, prt
);
609 static struct socket_info
*find_socket_info(int fd
)
611 struct socket_info
*i
;
612 for (i
= sockets
; i
; i
= i
->next
) {
613 struct socket_info_fd
*f
;
614 for (f
= i
->fds
; f
; f
= f
->next
) {
624 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
625 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
627 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
631 out
->sa_family
= AF_UNIX
;
632 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
633 out
->sa_len
= sizeof(*out_addr
);
636 switch (in_addr
->sa_family
) {
646 errno
= ESOCKTNOSUPPORT
;
650 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
652 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
658 errno
= EAFNOSUPPORT
;
662 static int sockaddr_convert_from_un(const struct socket_info
*si
,
663 const struct sockaddr_un
*in_addr
,
664 socklen_t un_addrlen
,
666 struct sockaddr
*out_addr
,
667 socklen_t
*out_addrlen
)
671 if (out_addr
== NULL
|| out_addrlen
== NULL
)
674 if (un_addrlen
== 0) {
689 errno
= ESOCKTNOSUPPORT
;
692 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
693 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
694 out_addr
->sa_len
= *out_addrlen
;
701 errno
= EAFNOSUPPORT
;
705 enum swrap_packet_type
{
707 SWRAP_CONNECT_UNREACH
,
715 SWRAP_SENDTO_UNREACH
,
726 struct swrap_file_hdr
{
728 uint16_t version_major
;
729 uint16_t version_minor
;
732 uint32_t frame_max_len
;
733 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
736 #define SWRAP_FILE_HDR_SIZE 24
738 struct swrap_packet_frame
{
740 uint32_t micro_seconds
;
741 uint32_t recorded_length
;
742 uint32_t full_length
;
744 #define SWRAP_PACKET_FRAME_SIZE 16
746 union swrap_packet_ip
{
750 uint16_t packet_length
;
751 uint16_t identification
;
756 uint16_t hdr_checksum
;
760 #define SWRAP_PACKET_IP_V4_SIZE 20
763 uint8_t flow_label_high
;
764 uint16_t flow_label_low
;
765 uint16_t payload_length
;
768 uint8_t src_addr
[16];
769 uint8_t dest_addr
[16];
771 #define SWRAP_PACKET_IP_V6_SIZE 40
773 #define SWRAP_PACKET_IP_SIZE 40
775 union swrap_packet_payload
{
777 uint16_t source_port
;
787 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
789 uint16_t source_port
;
794 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
801 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
808 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
810 #define SWRAP_PACKET_PAYLOAD_SIZE 20
812 #define SWRAP_PACKET_MIN_ALLOC \
813 (SWRAP_PACKET_FRAME_SIZE + \
814 SWRAP_PACKET_IP_SIZE + \
815 SWRAP_PACKET_PAYLOAD_SIZE)
817 static const char *socket_wrapper_pcap_file(void)
819 static int initialized
= 0;
820 static const char *s
= NULL
;
821 static const struct swrap_file_hdr h
;
822 static const struct swrap_packet_frame f
;
823 static const union swrap_packet_ip i
;
824 static const union swrap_packet_payload p
;
826 if (initialized
== 1) {
832 * TODO: don't use the structs use plain buffer offsets
833 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
835 * for now make sure we disable PCAP support
836 * if the struct has alignment!
838 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
841 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
844 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
847 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
850 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
853 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
856 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
859 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
862 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
865 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
869 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
873 if (strncmp(s
, "./", 2) == 0) {
879 static uint8_t *swrap_packet_init(struct timeval
*tval
,
880 const struct sockaddr
*src
,
881 const struct sockaddr
*dest
,
883 const uint8_t *payload
,
885 unsigned long tcp_seqno
,
886 unsigned long tcp_ack
,
887 unsigned char tcp_ctl
,
893 struct swrap_packet_frame
*frame
;
894 union swrap_packet_ip
*ip
;
895 union swrap_packet_payload
*pay
;
898 size_t nonwire_len
= sizeof(*frame
);
899 size_t wire_hdr_len
= 0;
901 size_t ip_hdr_len
= 0;
902 size_t icmp_hdr_len
= 0;
903 size_t icmp_truncate_len
= 0;
904 uint8_t protocol
= 0, icmp_protocol
= 0;
905 const struct sockaddr_in
*src_in
= NULL
;
906 const struct sockaddr_in
*dest_in
= NULL
;
908 const struct sockaddr_in6
*src_in6
= NULL
;
909 const struct sockaddr_in6
*dest_in6
= NULL
;
914 switch (src
->sa_family
) {
916 src_in
= (const struct sockaddr_in
*)src
;
917 dest_in
= (const struct sockaddr_in
*)dest
;
918 src_port
= src_in
->sin_port
;
919 dest_port
= dest_in
->sin_port
;
920 ip_hdr_len
= sizeof(ip
->v4
);
924 src_in6
= (const struct sockaddr_in6
*)src
;
925 dest_in6
= (const struct sockaddr_in6
*)dest
;
926 src_port
= src_in6
->sin6_port
;
927 dest_port
= dest_in6
->sin6_port
;
928 ip_hdr_len
= sizeof(ip
->v6
);
935 switch (socket_type
) {
937 protocol
= 0x06; /* TCP */
938 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
939 wire_len
= wire_hdr_len
+ payload_len
;
943 protocol
= 0x11; /* UDP */
944 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
945 wire_len
= wire_hdr_len
+ payload_len
;
953 icmp_protocol
= protocol
;
954 switch (src
->sa_family
) {
956 protocol
= 0x01; /* ICMPv4 */
957 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
961 protocol
= 0x3A; /* ICMPv6 */
962 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
966 if (wire_len
> 64 ) {
967 icmp_truncate_len
= wire_len
- 64;
969 wire_hdr_len
+= icmp_hdr_len
;
970 wire_len
+= icmp_hdr_len
;
973 packet_len
= nonwire_len
+ wire_len
;
974 alloc_len
= packet_len
;
975 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
976 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
979 base
= (uint8_t *)malloc(alloc_len
);
980 if (!base
) return NULL
;
984 frame
= (struct swrap_packet_frame
*)buf
;
985 frame
->seconds
= tval
->tv_sec
;
986 frame
->micro_seconds
= tval
->tv_usec
;
987 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
988 frame
->full_length
= wire_len
- icmp_truncate_len
;
989 buf
+= SWRAP_PACKET_FRAME_SIZE
;
991 ip
= (union swrap_packet_ip
*)buf
;
992 switch (src
->sa_family
) {
994 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
996 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
997 ip
->v4
.identification
= htons(0xFFFF);
998 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
999 ip
->v4
.fragment
= htons(0x0000);
1001 ip
->v4
.protocol
= protocol
;
1002 ip
->v4
.hdr_checksum
= htons(0x0000);
1003 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1004 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1005 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1009 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1010 ip
->v6
.flow_label_high
= 0x00;
1011 ip
->v6
.flow_label_low
= 0x0000;
1012 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1013 ip
->v6
.next_header
= protocol
;
1014 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1015 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1016 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1022 pay
= (union swrap_packet_payload
*)buf
;
1023 switch (src
->sa_family
) {
1025 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1026 pay
->icmp4
.code
= 0x01; /* host unreachable */
1027 pay
->icmp4
.checksum
= htons(0x0000);
1028 pay
->icmp4
.unused
= htonl(0x00000000);
1029 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1031 /* set the ip header in the ICMP payload */
1032 ip
= (union swrap_packet_ip
*)buf
;
1033 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1035 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1036 ip
->v4
.identification
= htons(0xFFFF);
1037 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
1038 ip
->v4
.fragment
= htons(0x0000);
1040 ip
->v4
.protocol
= icmp_protocol
;
1041 ip
->v4
.hdr_checksum
= htons(0x0000);
1042 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1043 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1044 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1046 src_port
= dest_in
->sin_port
;
1047 dest_port
= src_in
->sin_port
;
1051 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1052 pay
->icmp6
.code
= 0x03; /* address unreachable */
1053 pay
->icmp6
.checksum
= htons(0x0000);
1054 pay
->icmp6
.unused
= htonl(0x00000000);
1055 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1057 /* set the ip header in the ICMP payload */
1058 ip
= (union swrap_packet_ip
*)buf
;
1059 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1060 ip
->v6
.flow_label_high
= 0x00;
1061 ip
->v6
.flow_label_low
= 0x0000;
1062 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1063 ip
->v6
.next_header
= protocol
;
1064 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1065 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1066 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1068 src_port
= dest_in6
->sin6_port
;
1069 dest_port
= src_in6
->sin6_port
;
1075 pay
= (union swrap_packet_payload
*)buf
;
1077 switch (socket_type
) {
1079 pay
->tcp
.source_port
= src_port
;
1080 pay
->tcp
.dest_port
= dest_port
;
1081 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1082 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1083 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1084 pay
->tcp
.control
= tcp_ctl
;
1085 pay
->tcp
.window
= htons(0x7FFF);
1086 pay
->tcp
.checksum
= htons(0x0000);
1087 pay
->tcp
.urg
= htons(0x0000);
1088 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1093 pay
->udp
.source_port
= src_port
;
1094 pay
->udp
.dest_port
= dest_port
;
1095 pay
->udp
.length
= htons(8 + payload_len
);
1096 pay
->udp
.checksum
= htons(0x0000);
1097 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1102 if (payload
&& payload_len
> 0) {
1103 memcpy(buf
, payload
, payload_len
);
1106 *_packet_len
= packet_len
- icmp_truncate_len
;
1110 static int swrap_get_pcap_fd(const char *fname
)
1114 if (fd
!= -1) return fd
;
1116 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1118 struct swrap_file_hdr file_hdr
;
1119 file_hdr
.magic
= 0xA1B2C3D4;
1120 file_hdr
.version_major
= 0x0002;
1121 file_hdr
.version_minor
= 0x0004;
1122 file_hdr
.timezone
= 0x00000000;
1123 file_hdr
.sigfigs
= 0x00000000;
1124 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1125 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1127 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1134 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1139 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1140 const struct sockaddr
*addr
,
1141 enum swrap_packet_type type
,
1142 const void *buf
, size_t len
,
1145 const struct sockaddr
*src_addr
;
1146 const struct sockaddr
*dest_addr
;
1147 unsigned long tcp_seqno
= 0;
1148 unsigned long tcp_ack
= 0;
1149 unsigned char tcp_ctl
= 0;
1150 int unreachable
= 0;
1154 switch (si
->family
) {
1166 case SWRAP_CONNECT_SEND
:
1167 if (si
->type
!= SOCK_STREAM
) return NULL
;
1169 src_addr
= si
->myname
;
1172 tcp_seqno
= si
->io
.pck_snd
;
1173 tcp_ack
= si
->io
.pck_rcv
;
1174 tcp_ctl
= 0x02; /* SYN */
1176 si
->io
.pck_snd
+= 1;
1180 case SWRAP_CONNECT_RECV
:
1181 if (si
->type
!= SOCK_STREAM
) return NULL
;
1183 dest_addr
= si
->myname
;
1186 tcp_seqno
= si
->io
.pck_rcv
;
1187 tcp_ack
= si
->io
.pck_snd
;
1188 tcp_ctl
= 0x12; /** SYN,ACK */
1190 si
->io
.pck_rcv
+= 1;
1194 case SWRAP_CONNECT_UNREACH
:
1195 if (si
->type
!= SOCK_STREAM
) return NULL
;
1197 dest_addr
= si
->myname
;
1200 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1201 tcp_seqno
= si
->io
.pck_snd
- 1;
1202 tcp_ack
= si
->io
.pck_rcv
;
1203 tcp_ctl
= 0x02; /* SYN */
1208 case SWRAP_CONNECT_ACK
:
1209 if (si
->type
!= SOCK_STREAM
) return NULL
;
1211 src_addr
= si
->myname
;
1214 tcp_seqno
= si
->io
.pck_snd
;
1215 tcp_ack
= si
->io
.pck_rcv
;
1216 tcp_ctl
= 0x10; /* ACK */
1220 case SWRAP_ACCEPT_SEND
:
1221 if (si
->type
!= SOCK_STREAM
) return NULL
;
1223 dest_addr
= si
->myname
;
1226 tcp_seqno
= si
->io
.pck_rcv
;
1227 tcp_ack
= si
->io
.pck_snd
;
1228 tcp_ctl
= 0x02; /* SYN */
1230 si
->io
.pck_rcv
+= 1;
1234 case SWRAP_ACCEPT_RECV
:
1235 if (si
->type
!= SOCK_STREAM
) return NULL
;
1237 src_addr
= si
->myname
;
1240 tcp_seqno
= si
->io
.pck_snd
;
1241 tcp_ack
= si
->io
.pck_rcv
;
1242 tcp_ctl
= 0x12; /* SYN,ACK */
1244 si
->io
.pck_snd
+= 1;
1248 case SWRAP_ACCEPT_ACK
:
1249 if (si
->type
!= SOCK_STREAM
) return NULL
;
1251 dest_addr
= si
->myname
;
1254 tcp_seqno
= si
->io
.pck_rcv
;
1255 tcp_ack
= si
->io
.pck_snd
;
1256 tcp_ctl
= 0x10; /* ACK */
1261 src_addr
= si
->myname
;
1262 dest_addr
= si
->peername
;
1264 tcp_seqno
= si
->io
.pck_snd
;
1265 tcp_ack
= si
->io
.pck_rcv
;
1266 tcp_ctl
= 0x18; /* PSH,ACK */
1268 si
->io
.pck_snd
+= len
;
1272 case SWRAP_SEND_RST
:
1273 dest_addr
= si
->myname
;
1274 src_addr
= si
->peername
;
1276 if (si
->type
== SOCK_DGRAM
) {
1277 return swrap_marshall_packet(si
, si
->peername
,
1278 SWRAP_SENDTO_UNREACH
,
1279 buf
, len
, packet_len
);
1282 tcp_seqno
= si
->io
.pck_rcv
;
1283 tcp_ack
= si
->io
.pck_snd
;
1284 tcp_ctl
= 0x14; /** RST,ACK */
1288 case SWRAP_PENDING_RST
:
1289 dest_addr
= si
->myname
;
1290 src_addr
= si
->peername
;
1292 if (si
->type
== SOCK_DGRAM
) {
1296 tcp_seqno
= si
->io
.pck_rcv
;
1297 tcp_ack
= si
->io
.pck_snd
;
1298 tcp_ctl
= 0x14; /* RST,ACK */
1303 dest_addr
= si
->myname
;
1304 src_addr
= si
->peername
;
1306 tcp_seqno
= si
->io
.pck_rcv
;
1307 tcp_ack
= si
->io
.pck_snd
;
1308 tcp_ctl
= 0x18; /* PSH,ACK */
1310 si
->io
.pck_rcv
+= len
;
1314 case SWRAP_RECV_RST
:
1315 dest_addr
= si
->myname
;
1316 src_addr
= si
->peername
;
1318 if (si
->type
== SOCK_DGRAM
) {
1322 tcp_seqno
= si
->io
.pck_rcv
;
1323 tcp_ack
= si
->io
.pck_snd
;
1324 tcp_ctl
= 0x14; /* RST,ACK */
1329 src_addr
= si
->myname
;
1332 si
->io
.pck_snd
+= len
;
1336 case SWRAP_SENDTO_UNREACH
:
1337 dest_addr
= si
->myname
;
1344 case SWRAP_RECVFROM
:
1345 dest_addr
= si
->myname
;
1348 si
->io
.pck_rcv
+= len
;
1352 case SWRAP_CLOSE_SEND
:
1353 if (si
->type
!= SOCK_STREAM
) return NULL
;
1355 src_addr
= si
->myname
;
1356 dest_addr
= si
->peername
;
1358 tcp_seqno
= si
->io
.pck_snd
;
1359 tcp_ack
= si
->io
.pck_rcv
;
1360 tcp_ctl
= 0x11; /* FIN, ACK */
1362 si
->io
.pck_snd
+= 1;
1366 case SWRAP_CLOSE_RECV
:
1367 if (si
->type
!= SOCK_STREAM
) return NULL
;
1369 dest_addr
= si
->myname
;
1370 src_addr
= si
->peername
;
1372 tcp_seqno
= si
->io
.pck_rcv
;
1373 tcp_ack
= si
->io
.pck_snd
;
1374 tcp_ctl
= 0x11; /* FIN,ACK */
1376 si
->io
.pck_rcv
+= 1;
1380 case SWRAP_CLOSE_ACK
:
1381 if (si
->type
!= SOCK_STREAM
) return NULL
;
1383 src_addr
= si
->myname
;
1384 dest_addr
= si
->peername
;
1386 tcp_seqno
= si
->io
.pck_snd
;
1387 tcp_ack
= si
->io
.pck_rcv
;
1388 tcp_ctl
= 0x10; /* ACK */
1395 swrapGetTimeOfDay(&tv
);
1397 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1398 (const uint8_t *)buf
, len
,
1399 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1403 static void swrap_dump_packet(struct socket_info
*si
,
1404 const struct sockaddr
*addr
,
1405 enum swrap_packet_type type
,
1406 const void *buf
, size_t len
)
1408 const char *file_name
;
1410 size_t packet_len
= 0;
1413 file_name
= socket_wrapper_pcap_file();
1418 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1423 fd
= swrap_get_pcap_fd(file_name
);
1425 if (write(fd
, packet
, packet_len
) != packet_len
) {
1434 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1436 struct socket_info
*si
;
1437 struct socket_info_fd
*fi
;
1439 int real_type
= type
;
1441 real_type
&= ~SOCK_CLOEXEC
;
1443 #ifdef SOCK_NONBLOCK
1444 real_type
&= ~SOCK_NONBLOCK
;
1447 if (!socket_wrapper_dir()) {
1448 return real_socket(family
, type
, protocol
);
1458 return real_socket(family
, type
, protocol
);
1460 errno
= EAFNOSUPPORT
;
1464 switch (real_type
) {
1470 errno
= EPROTONOSUPPORT
;
1478 if (real_type
== SOCK_STREAM
) {
1483 if (real_type
== SOCK_DGRAM
) {
1488 errno
= EPROTONOSUPPORT
;
1492 /* We must call real_socket with type, from the caller, not the version we removed
1493 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1494 fd
= real_socket(AF_UNIX
, type
, 0);
1496 if (fd
== -1) return -1;
1498 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1504 si
->family
= family
;
1506 /* however, the rest of the socket_wrapper code expects just
1507 * the type, not the flags */
1508 si
->type
= real_type
;
1509 si
->protocol
= protocol
;
1511 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
1520 SWRAP_DLIST_ADD(si
->fds
, fi
);
1521 SWRAP_DLIST_ADD(sockets
, si
);
1526 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1528 struct socket_info
*parent_si
, *child_si
;
1529 struct socket_info_fd
*child_fi
;
1531 struct sockaddr_un un_addr
;
1532 socklen_t un_addrlen
= sizeof(un_addr
);
1533 struct sockaddr_un un_my_addr
;
1534 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1535 struct sockaddr
*my_addr
;
1536 socklen_t my_addrlen
, len
;
1539 parent_si
= find_socket_info(s
);
1541 return real_accept(s
, addr
, addrlen
);
1545 * assume out sockaddr have the same size as the in parent
1548 my_addrlen
= socket_length(parent_si
->family
);
1549 if (my_addrlen
<= 0) {
1554 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1555 if (my_addr
== NULL
) {
1559 memset(&un_addr
, 0, sizeof(un_addr
));
1560 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1562 ret
= real_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
1571 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1572 parent_si
->family
, my_addr
, &len
);
1579 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1580 memset(child_si
, 0, sizeof(*child_si
));
1582 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
1583 if (child_fi
== NULL
) {
1593 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
1595 child_si
->family
= parent_si
->family
;
1596 child_si
->type
= parent_si
->type
;
1597 child_si
->protocol
= parent_si
->protocol
;
1598 child_si
->bound
= 1;
1599 child_si
->is_server
= 1;
1600 child_si
->connected
= 1;
1602 child_si
->peername_len
= len
;
1603 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1605 if (addr
!= NULL
&& addrlen
!= NULL
) {
1606 size_t copy_len
= MIN(*addrlen
, len
);
1608 memcpy(addr
, my_addr
, copy_len
);
1613 ret
= real_getsockname(fd
, (struct sockaddr
*)(void *)&un_my_addr
,
1623 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1624 child_si
->family
, my_addr
, &len
);
1633 child_si
->myname_len
= len
;
1634 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1637 SWRAP_DLIST_ADD(sockets
, child_si
);
1639 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1640 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1641 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1646 static int autobind_start_init
;
1647 static int autobind_start
;
1649 /* using sendto() or connect() on an unbound socket would give the
1650 recipient no way to reply, as unlike UDP and TCP, a unix domain
1651 socket can't auto-assign emphemeral port numbers, so we need to
1653 Note: this might change the family from ipv6 to ipv4
1655 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
1657 struct sockaddr_un un_addr
;
1664 if (autobind_start_init
!= 1) {
1665 autobind_start_init
= 1;
1666 autobind_start
= getpid();
1667 autobind_start
%= 50000;
1668 autobind_start
+= 10000;
1671 un_addr
.sun_family
= AF_UNIX
;
1675 struct sockaddr_in in
;
1679 type
= SOCKET_TYPE_CHAR_TCP
;
1682 type
= SOCKET_TYPE_CHAR_UDP
;
1685 errno
= ESOCKTNOSUPPORT
;
1689 memset(&in
, 0, sizeof(in
));
1690 in
.sin_family
= AF_INET
;
1691 in
.sin_addr
.s_addr
= htonl(127<<24 |
1692 socket_wrapper_default_iface());
1694 si
->myname_len
= sizeof(in
);
1695 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1700 struct sockaddr_in6 in6
;
1702 if (si
->family
!= family
) {
1703 errno
= ENETUNREACH
;
1709 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1712 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1715 errno
= ESOCKTNOSUPPORT
;
1719 memset(&in6
, 0, sizeof(in6
));
1720 in6
.sin6_family
= AF_INET6
;
1721 in6
.sin6_addr
= *swrap_ipv6();
1722 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1723 si
->myname_len
= sizeof(in6
);
1724 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1729 errno
= ESOCKTNOSUPPORT
;
1733 if (autobind_start
> 60000) {
1734 autobind_start
= 10000;
1737 for (i
=0;i
<1000;i
++) {
1738 port
= autobind_start
+ i
;
1739 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1740 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1741 type
, socket_wrapper_default_iface(), port
);
1742 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1744 ret
= real_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
1746 if (ret
== -1) return ret
;
1748 si
->tmp_path
= strdup(un_addr
.sun_path
);
1750 autobind_start
= port
+ 1;
1758 si
->family
= family
;
1759 set_port(si
->family
, port
, si
->myname
);
1765 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1768 struct sockaddr_un un_addr
;
1769 struct socket_info
*si
= find_socket_info(s
);
1773 return real_connect(s
, serv_addr
, addrlen
);
1776 if (si
->bound
== 0) {
1777 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
1778 if (ret
== -1) return -1;
1781 if (si
->family
!= serv_addr
->sa_family
) {
1786 ret
= sockaddr_convert_to_un(si
, serv_addr
,
1787 addrlen
, &un_addr
, 0, &bcast
);
1788 if (ret
== -1) return -1;
1791 errno
= ENETUNREACH
;
1795 if (si
->type
== SOCK_DGRAM
) {
1796 si
->defer_connect
= 1;
1799 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1801 ret
= real_connect(s
, (struct sockaddr
*)(void *)&un_addr
,
1802 sizeof(struct sockaddr_un
));
1805 /* to give better errors */
1806 if (ret
== -1 && errno
== ENOENT
) {
1807 errno
= EHOSTUNREACH
;
1811 si
->peername_len
= addrlen
;
1812 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1815 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1816 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1818 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1824 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1827 struct sockaddr_un un_addr
;
1828 struct socket_info
*si
= find_socket_info(s
);
1831 return real_bind(s
, myaddr
, addrlen
);
1834 si
->myname_len
= addrlen
;
1835 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1837 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1838 if (ret
== -1) return -1;
1840 unlink(un_addr
.sun_path
);
1842 ret
= real_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
1843 sizeof(struct sockaddr_un
));
1852 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1855 struct socket_info
*si
= find_socket_info(s
);
1858 return real_listen(s
, backlog
);
1861 ret
= real_listen(s
, backlog
);
1866 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1868 struct socket_info
*si
= find_socket_info(s
);
1871 return real_getpeername(s
, name
, addrlen
);
1880 memcpy(name
, si
->peername
, si
->peername_len
);
1881 *addrlen
= si
->peername_len
;
1886 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1888 struct socket_info
*si
= find_socket_info(s
);
1891 return real_getsockname(s
, name
, addrlen
);
1894 memcpy(name
, si
->myname
, si
->myname_len
);
1895 *addrlen
= si
->myname_len
;
1900 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1902 struct socket_info
*si
= find_socket_info(s
);
1905 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1908 if (level
== SOL_SOCKET
) {
1909 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1912 errno
= ENOPROTOOPT
;
1916 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1918 struct socket_info
*si
= find_socket_info(s
);
1921 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1924 if (level
== SOL_SOCKET
) {
1925 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1928 switch (si
->family
) {
1936 errno
= ENOPROTOOPT
;
1941 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1944 struct socket_info
*si
= find_socket_info(s
);
1948 return real_ioctl(s
, r
, p
);
1951 ret
= real_ioctl(s
, r
, p
);
1955 value
= *((int *)p
);
1956 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1957 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1958 } else if (value
== 0) { /* END OF FILE */
1959 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1967 static ssize_t
swrap_sendmsg_before(int fd
,
1968 struct socket_info
*si
,
1970 struct iovec
*tmp_iov
,
1971 struct sockaddr_un
*tmp_un
,
1972 const struct sockaddr_un
**to_un
,
1973 const struct sockaddr
**to
,
1991 if (!si
->connected
) {
1996 if (msg
->msg_iovlen
== 0) {
2001 * cut down to 1500 byte packets for stream sockets,
2002 * which makes it easier to format PCAP capture files
2003 * (as the caller will simply continue from here)
2006 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2008 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
2013 msg
->msg_iovlen
= i
;
2014 if (msg
->msg_iovlen
== 0) {
2015 *tmp_iov
= msg
->msg_iov
[0];
2016 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, 1500);
2017 msg
->msg_iov
= tmp_iov
;
2018 msg
->msg_iovlen
= 1;
2023 if (si
->connected
) {
2024 if (msg
->msg_name
) {
2029 const struct sockaddr
*msg_name
;
2030 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
2032 if (msg_name
== NULL
) {
2038 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
2040 if (ret
== -1) return -1;
2048 msg
->msg_name
= tmp_un
;
2049 msg
->msg_namelen
= sizeof(*tmp_un
);
2052 if (si
->bound
== 0) {
2053 ret
= swrap_auto_bind(fd
, si
, si
->family
);
2054 if (ret
== -1) return -1;
2057 if (!si
->defer_connect
) {
2061 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2063 if (ret
== -1) return -1;
2065 ret
= real_connect(fd
, (struct sockaddr
*)(void *)tmp_un
,
2068 /* to give better errors */
2069 if (ret
== -1 && errno
== ENOENT
) {
2070 errno
= EHOSTUNREACH
;
2077 si
->defer_connect
= 0;
2080 errno
= EHOSTUNREACH
;
2087 static void swrap_sendmsg_after(struct socket_info
*si
,
2089 const struct sockaddr
*to
,
2092 int saved_errno
= errno
;
2099 /* to give better errors */
2100 if (ret
== -1 && saved_errno
== ENOENT
) {
2101 saved_errno
= EHOSTUNREACH
;
2104 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2105 avail
+= msg
->msg_iov
[i
].iov_len
;
2109 remain
= MIN(80, avail
);
2114 /* we capture it as one single packet */
2115 buf
= (uint8_t *)malloc(remain
);
2117 /* we just not capture the packet */
2118 errno
= saved_errno
;
2122 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2123 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2125 msg
->msg_iov
[i
].iov_base
,
2128 remain
-= this_time
;
2135 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2136 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2138 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2143 if (si
->connected
) {
2147 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2148 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
2150 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2156 errno
= saved_errno
;
2159 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
2161 struct sockaddr_un un_addr
;
2162 socklen_t un_addrlen
= sizeof(un_addr
);
2164 struct socket_info
*si
= find_socket_info(s
);
2165 struct sockaddr_storage ss
;
2166 socklen_t ss_len
= sizeof(ss
);
2169 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
2173 from
= (struct sockaddr
*)(void *)&ss
;
2177 if (si
->type
== SOCK_STREAM
) {
2178 /* cut down to 1500 byte packets for stream sockets,
2179 * which makes it easier to format PCAP capture files
2180 * (as the caller will simply continue from here) */
2181 len
= MIN(len
, 1500);
2184 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2185 memset(&un_addr
, 0, sizeof(un_addr
));
2186 ret
= real_recvfrom(s
, buf
, len
, flags
,
2187 (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2191 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
2192 si
->family
, from
, fromlen
) == -1) {
2196 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
2202 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
2206 struct sockaddr_un un_addr
;
2207 const struct sockaddr_un
*to_un
= NULL
;
2209 struct socket_info
*si
= find_socket_info(s
);
2213 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
2216 tmp
.iov_base
= discard_const_p(char, buf
);
2220 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
2221 msg
.msg_namelen
= tolen
; /* size of address */
2222 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2223 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2224 #if 0 /* not available on solaris */
2225 msg
.msg_control
= NULL
; /* ancillary data, see below */
2226 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2227 msg
.msg_flags
= 0; /* flags on received message */
2230 ret
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2231 if (ret
== -1) return -1;
2233 buf
= msg
.msg_iov
[0].iov_base
;
2234 len
= msg
.msg_iov
[0].iov_len
;
2239 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2242 type
= SOCKET_TYPE_CHAR_UDP
;
2244 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2245 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2246 socket_wrapper_dir(), type
, iface
, prt
);
2247 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2249 /* ignore the any errors in broadcast sends */
2250 real_sendto(s
, buf
, len
, flags
,
2251 (struct sockaddr
*)(void *)&un_addr
,
2255 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2260 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)msg
.msg_name
,
2263 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2268 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2271 struct socket_info
*si
= find_socket_info(s
);
2274 return real_recv(s
, buf
, len
, flags
);
2277 if (si
->type
== SOCK_STREAM
) {
2278 /* cut down to 1500 byte packets for stream sockets,
2279 * which makes it easier to format PCAP capture files
2280 * (as the caller will simply continue from here) */
2281 len
= MIN(len
, 1500);
2284 ret
= real_recv(s
, buf
, len
, flags
);
2285 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2286 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2287 } else if (ret
== 0) { /* END OF FILE */
2288 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2289 } else if (ret
> 0) {
2290 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2296 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2299 struct socket_info
*si
= find_socket_info(s
);
2302 return real_read(s
, buf
, len
);
2305 if (si
->type
== SOCK_STREAM
) {
2306 /* cut down to 1500 byte packets for stream sockets,
2307 * which makes it easier to format PCAP capture files
2308 * (as the caller will simply continue from here) */
2309 len
= MIN(len
, 1500);
2312 ret
= real_read(s
, buf
, len
);
2313 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2314 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2315 } else if (ret
== 0) { /* END OF FILE */
2316 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2317 } else if (ret
> 0) {
2318 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2325 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2329 struct sockaddr_un un_addr
;
2331 struct socket_info
*si
= find_socket_info(s
);
2334 return real_send(s
, buf
, len
, flags
);
2337 tmp
.iov_base
= discard_const_p(char, buf
);
2341 msg
.msg_name
= NULL
; /* optional address */
2342 msg
.msg_namelen
= 0; /* size of address */
2343 msg
.msg_iov
= &tmp
; /* scatter/gather array */
2344 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
2345 #if 0 /* not available on solaris */
2346 msg
.msg_control
= NULL
; /* ancillary data, see below */
2347 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2348 msg
.msg_flags
= 0; /* flags on received message */
2351 ret
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2352 if (ret
== -1) return -1;
2354 buf
= msg
.msg_iov
[0].iov_base
;
2355 len
= msg
.msg_iov
[0].iov_len
;
2357 ret
= real_send(s
, buf
, len
, flags
);
2359 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2364 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
2368 struct sockaddr_un un_addr
;
2369 const struct sockaddr_un
*to_un
= NULL
;
2370 const struct sockaddr
*to
= NULL
;
2372 struct socket_info
*si
= find_socket_info(s
);
2376 return real_sendmsg(s
, omsg
, flags
);
2379 tmp
.iov_base
= NULL
;
2384 msg
.msg_name
= omsg
->msg_name
; /* optional address */
2385 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
2386 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
2387 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
2388 /* the following is not available on solaris */
2389 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
2390 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
2391 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
2394 ret
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
2395 if (ret
== -1) return -1;
2400 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
2408 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2409 avail
+= msg
.msg_iov
[i
].iov_len
;
2415 /* we capture it as one single packet */
2416 buf
= (uint8_t *)malloc(remain
);
2421 for (i
=0; i
< msg
.msg_iovlen
; i
++) {
2422 size_t this_time
= MIN(remain
, msg
.msg_iov
[i
].iov_len
);
2424 msg
.msg_iov
[i
].iov_base
,
2427 remain
-= this_time
;
2430 type
= SOCKET_TYPE_CHAR_UDP
;
2432 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
2433 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
2434 socket_wrapper_dir(), type
, iface
, prt
);
2435 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
2437 msg
.msg_name
= &un_addr
; /* optional address */
2438 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
2440 /* ignore the any errors in broadcast sends */
2441 real_sendmsg(s
, &msg
, flags
);
2444 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
2450 ret
= real_sendmsg(s
, &msg
, flags
);
2452 swrap_sendmsg_after(si
, &msg
, to
, ret
);
2457 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2460 struct socket_info
*si
= find_socket_info(s
);
2464 return real_readv(s
, vector
, count
);
2467 if (!si
->connected
) {
2472 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2473 /* cut down to 1500 byte packets for stream sockets,
2474 * which makes it easier to format PCAP capture files
2475 * (as the caller will simply continue from here) */
2478 for (i
=0; i
< count
; i
++) {
2480 nlen
= len
+ vector
[i
].iov_len
;
2488 v
.iov_len
= MIN(v
.iov_len
, 1500);
2494 ret
= real_readv(s
, vector
, count
);
2495 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2496 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2497 } else if (ret
== 0) { /* END OF FILE */
2498 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2499 } else if (ret
> 0) {
2503 size_t remain
= ret
;
2505 /* we capture it as one single packet */
2506 buf
= (uint8_t *)malloc(ret
);
2508 /* we just not capture the packet */
2513 for (i
=0; i
< count
; i
++) {
2514 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2519 remain
-= this_time
;
2522 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2529 ssize_t
swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2533 struct sockaddr_un un_addr
;
2535 struct socket_info
*si
= find_socket_info(s
);
2538 return real_writev(s
, vector
, count
);
2541 tmp
.iov_base
= NULL
;
2545 msg
.msg_name
= NULL
; /* optional address */
2546 msg
.msg_namelen
= 0; /* size of address */
2547 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
2548 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
2549 #if 0 /* not available on solaris */
2550 msg
.msg_control
= NULL
; /* ancillary data, see below */
2551 msg
.msg_controllen
= 0; /* ancillary data buffer len */
2552 msg
.msg_flags
= 0; /* flags on received message */
2555 ret
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
2556 if (ret
== -1) return -1;
2558 ret
= real_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
2560 swrap_sendmsg_after(si
, &msg
, NULL
, ret
);
2565 _PUBLIC_
int swrap_close(int fd
)
2567 struct socket_info
*si
= find_socket_info(fd
);
2568 struct socket_info_fd
*fi
;
2572 return real_close(fd
);
2575 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
2577 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
2584 /* there are still references left */
2585 return real_close(fd
);
2588 SWRAP_DLIST_REMOVE(sockets
, si
);
2590 if (si
->myname
&& si
->peername
) {
2591 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2594 ret
= real_close(fd
);
2596 if (si
->myname
&& si
->peername
) {
2597 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2598 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2601 if (si
->myname
) free(si
->myname
);
2602 if (si
->peername
) free(si
->peername
);
2604 unlink(si
->tmp_path
);
2612 _PUBLIC_
int swrap_dup(int fd
)
2614 struct socket_info
*si
;
2615 struct socket_info_fd
*fi
;
2617 si
= find_socket_info(fd
);
2620 return real_dup(fd
);
2623 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2629 fi
->fd
= real_dup(fd
);
2631 int saved_errno
= errno
;
2633 errno
= saved_errno
;
2637 SWRAP_DLIST_ADD(si
->fds
, fi
);
2641 _PUBLIC_
int swrap_dup2(int fd
, int newfd
)
2643 struct socket_info
*si
;
2644 struct socket_info_fd
*fi
;
2646 si
= find_socket_info(fd
);
2649 return real_dup2(fd
, newfd
);
2652 if (find_socket_info(newfd
)) {
2653 /* dup2() does an implicit close of newfd, which we
2654 * need to emulate */
2658 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2664 fi
->fd
= real_dup2(fd
, newfd
);
2666 int saved_errno
= errno
;
2668 errno
= saved_errno
;
2672 SWRAP_DLIST_ADD(si
->fds
, fi
);