2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the author nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
44 #define SOCKET_WRAPPER_NOT_REPLACE
45 #include "../replace/replace.h"
46 #include "system/network.h"
47 #include "system/filesys.h"
48 #include "system/time.h"
50 #else /* _SAMBA_BUILD_ */
52 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/ioctl.h>
57 #include <sys/filio.h>
60 #include <netinet/in.h>
61 #include <netinet/tcp.h>
75 #define SWRAP_DLIST_ADD(list,item) do { \
77 (item)->prev = NULL; \
78 (item)->next = NULL; \
81 (item)->prev = NULL; \
82 (item)->next = (list); \
83 (list)->prev = (item); \
88 #define SWRAP_DLIST_REMOVE(list,item) do { \
89 if ((list) == (item)) { \
90 (list) = (item)->next; \
92 (list)->prev = NULL; \
96 (item)->prev->next = (item)->next; \
99 (item)->next->prev = (item)->prev; \
102 (item)->prev = NULL; \
103 (item)->next = NULL; \
106 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
108 #define REWRITE_CALLS
111 #define real_accept accept
112 #define real_connect connect
113 #define real_bind bind
114 #define real_listen listen
115 #define real_getpeername getpeername
116 #define real_getsockname getsockname
117 #define real_getsockopt getsockopt
118 #define real_setsockopt setsockopt
119 #define real_recvfrom recvfrom
120 #define real_sendto sendto
121 #define real_sendmsg sendmsg
122 #define real_ioctl ioctl
123 #define real_recv recv
124 #define real_read read
125 #define real_send send
126 #define real_readv readv
127 #define real_writev writev
128 #define real_socket socket
129 #define real_close close
132 #ifdef HAVE_GETTIMEOFDAY_TZ
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 /* we need to use a very terse format here as IRIX 6.4 silently
139 truncates names to 16 chars, so if we use a longer name then we
140 can't tell which port a packet came from with recvfrom()
142 with this format we have 8 chars left for the directory name
144 #define SOCKET_FORMAT "%c%02X%04X"
145 #define SOCKET_TYPE_CHAR_TCP 'T'
146 #define SOCKET_TYPE_CHAR_UDP 'U'
147 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
148 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
150 #define MAX_WRAPPED_INTERFACES 16
156 static const struct in6_addr
*swrap_ipv6(void)
158 static struct in6_addr v
;
159 static int initialized
;
167 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
176 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
178 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
179 memcpy(ret
, data
, len
);
183 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
187 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
191 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
197 static size_t socket_length(int family
)
201 return sizeof(struct sockaddr_in
);
204 return sizeof(struct sockaddr_in6
);
228 struct sockaddr
*myname
;
229 socklen_t myname_len
;
231 struct sockaddr
*peername
;
232 socklen_t peername_len
;
235 unsigned long pck_snd
;
236 unsigned long pck_rcv
;
239 struct socket_info
*prev
, *next
;
242 static struct socket_info
*sockets
;
244 const char *socket_wrapper_dir(void)
246 const char *s
= getenv("SOCKET_WRAPPER_DIR");
250 if (strncmp(s
, "./", 2) == 0) {
256 unsigned int socket_wrapper_default_iface(void)
258 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
261 if (sscanf(s
, "%u", &iface
) == 1) {
262 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
268 return 1;/* 127.0.0.1 */
271 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
278 p
= strrchr(un
->sun_path
, '/');
279 if (p
) p
++; else p
= un
->sun_path
;
281 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
286 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
297 case SOCKET_TYPE_CHAR_TCP
:
298 case SOCKET_TYPE_CHAR_UDP
: {
299 struct sockaddr_in
*in2
= (struct sockaddr_in
*)in
;
301 if ((*len
) < sizeof(*in2
)) {
306 memset(in2
, 0, sizeof(*in2
));
307 in2
->sin_family
= AF_INET
;
308 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
309 in2
->sin_port
= htons(prt
);
315 case SOCKET_TYPE_CHAR_TCP_V6
:
316 case SOCKET_TYPE_CHAR_UDP_V6
: {
317 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)in
;
319 if ((*len
) < sizeof(*in2
)) {
324 memset(in2
, 0, sizeof(*in2
));
325 in2
->sin6_family
= AF_INET6
;
326 in2
->sin6_addr
= *swrap_ipv6();
327 in2
->sin6_addr
.s6_addr
[15] = iface
;
328 in2
->sin6_port
= htons(prt
);
342 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
350 if (bcast
) *bcast
= 0;
352 switch (inaddr
->sa_family
) {
354 const struct sockaddr_in
*in
=
355 (const struct sockaddr_in
*)inaddr
;
356 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
363 u_type
= SOCKET_TYPE_CHAR_TCP
;
366 u_type
= SOCKET_TYPE_CHAR_UDP
;
367 a_type
= SOCKET_TYPE_CHAR_UDP
;
368 b_type
= SOCKET_TYPE_CHAR_UDP
;
372 prt
= ntohs(in
->sin_port
);
373 if (a_type
&& addr
== 0xFFFFFFFF) {
374 /* 255.255.255.255 only udp */
377 iface
= socket_wrapper_default_iface();
378 } else if (b_type
&& addr
== 0x7FFFFFFF) {
379 /* 127.255.255.255 only udp */
382 iface
= socket_wrapper_default_iface();
383 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
387 iface
= (addr
& 0x000000FF);
392 if (bcast
) *bcast
= is_bcast
;
397 const struct sockaddr_in6
*in
=
398 (const struct sockaddr_in6
*)inaddr
;
403 type
= SOCKET_TYPE_CHAR_TCP_V6
;
406 type
= SOCKET_TYPE_CHAR_UDP_V6
;
410 /* XXX no multicast/broadcast */
412 prt
= ntohs(in
->sin6_port
);
416 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp
)) {
417 iface
= in
->sin6_addr
.s6_addr
[15];
437 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
438 socket_wrapper_dir());
439 /* the caller need to do more processing */
443 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
444 socket_wrapper_dir(), type
, iface
, prt
);
449 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
458 if (bcast
) *bcast
= 0;
460 switch (si
->family
) {
462 const struct sockaddr_in
*in
=
463 (const struct sockaddr_in
*)inaddr
;
464 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
470 prt
= ntohs(in
->sin_port
);
474 u_type
= SOCKET_TYPE_CHAR_TCP
;
475 d_type
= SOCKET_TYPE_CHAR_TCP
;
478 u_type
= SOCKET_TYPE_CHAR_UDP
;
479 d_type
= SOCKET_TYPE_CHAR_UDP
;
480 a_type
= SOCKET_TYPE_CHAR_UDP
;
481 b_type
= SOCKET_TYPE_CHAR_UDP
;
489 iface
= socket_wrapper_default_iface();
490 } else if (a_type
&& addr
== 0xFFFFFFFF) {
491 /* 255.255.255.255 only udp */
494 iface
= socket_wrapper_default_iface();
495 } else if (b_type
&& addr
== 0x7FFFFFFF) {
496 /* 127.255.255.255 only udp */
499 iface
= socket_wrapper_default_iface();
500 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
504 iface
= (addr
& 0x000000FF);
506 errno
= EADDRNOTAVAIL
;
513 const struct sockaddr_in6
*in
=
514 (const struct sockaddr_in6
*)inaddr
;
519 type
= SOCKET_TYPE_CHAR_TCP_V6
;
522 type
= SOCKET_TYPE_CHAR_UDP_V6
;
526 /* XXX no multicast/broadcast */
528 prt
= ntohs(in
->sin6_port
);
532 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
533 iface
= socket_wrapper_default_iface();
534 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp
)) {
535 iface
= in
->sin6_addr
.s6_addr
[15];
537 errno
= EADDRNOTAVAIL
;
545 errno
= EADDRNOTAVAIL
;
550 if (bcast
) *bcast
= is_bcast
;
553 /* handle auto-allocation of ephemeral ports */
554 for (prt
= 5001; prt
< 10000; prt
++) {
555 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
556 socket_wrapper_dir(), type
, iface
, prt
);
557 if (stat(un
->sun_path
, &st
) == 0) continue;
559 set_port(si
->family
, prt
, si
->myname
);
568 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
569 socket_wrapper_dir(), type
, iface
, prt
);
573 static struct socket_info
*find_socket_info(int fd
)
575 struct socket_info
*i
;
576 for (i
= sockets
; i
; i
= i
->next
) {
584 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
585 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
590 out_addr
->sun_family
= AF_UNIX
;
592 switch (in_addr
->sa_family
) {
602 errno
= ESOCKTNOSUPPORT
;
606 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
608 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
614 errno
= EAFNOSUPPORT
;
618 static int sockaddr_convert_from_un(const struct socket_info
*si
,
619 const struct sockaddr_un
*in_addr
,
620 socklen_t un_addrlen
,
622 struct sockaddr
*out_addr
,
623 socklen_t
*out_addrlen
)
625 if (out_addr
== NULL
|| out_addrlen
== NULL
)
628 if (un_addrlen
== 0) {
643 errno
= ESOCKTNOSUPPORT
;
646 return convert_un_in(in_addr
, out_addr
, out_addrlen
);
651 errno
= EAFNOSUPPORT
;
655 enum swrap_packet_type
{
657 SWRAP_CONNECT_UNREACH
,
665 SWRAP_SENDTO_UNREACH
,
676 struct swrap_file_hdr
{
678 uint16_t version_major
;
679 uint16_t version_minor
;
682 uint32_t frame_max_len
;
683 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
686 #define SWRAP_FILE_HDR_SIZE 24
688 struct swrap_packet_frame
{
690 uint32_t micro_seconds
;
691 uint32_t recorded_length
;
692 uint32_t full_length
;
694 #define SWRAP_PACKET_FRAME_SIZE 16
696 union swrap_packet_ip
{
700 uint16_t packet_length
;
701 uint16_t identification
;
706 uint16_t hdr_checksum
;
710 #define SWRAP_PACKET_IP_V4_SIZE 20
713 uint8_t flow_label_high
;
714 uint16_t flow_label_low
;
715 uint16_t payload_length
;
718 uint8_t src_addr
[16];
719 uint8_t dest_addr
[16];
721 #define SWRAP_PACKET_IP_V6_SIZE 40
723 #define SWRAP_PACKET_IP_SIZE 40
725 union swrap_packet_payload
{
727 uint16_t source_port
;
737 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
739 uint16_t source_port
;
744 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
751 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
758 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
760 #define SWRAP_PACKET_PAYLOAD_SIZE 20
762 #define SWRAP_PACKET_MIN_ALLOC \
763 (SWRAP_PACKET_FRAME_SIZE + \
764 SWRAP_PACKET_IP_SIZE + \
765 SWRAP_PACKET_PAYLOAD_SIZE)
767 static const char *socket_wrapper_pcap_file(void)
769 static int initialized
= 0;
770 static const char *s
= NULL
;
771 static const struct swrap_file_hdr h
;
772 static const struct swrap_packet_frame f
;
773 static const union swrap_packet_ip i
;
774 static const union swrap_packet_payload p
;
776 if (initialized
== 1) {
782 * TODO: don't use the structs use plain buffer offsets
783 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
785 * for now make sure we disable PCAP support
786 * if the struct has alignment!
788 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
791 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
794 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
797 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
800 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
803 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
806 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
809 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
812 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
815 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
819 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
823 if (strncmp(s
, "./", 2) == 0) {
829 static uint8_t *swrap_packet_init(struct timeval
*tval
,
830 const struct sockaddr
*src
,
831 const struct sockaddr
*dest
,
833 const uint8_t *payload
,
835 unsigned long tcp_seqno
,
836 unsigned long tcp_ack
,
837 unsigned char tcp_ctl
,
843 struct swrap_packet_frame
*frame
;
844 union swrap_packet_ip
*ip
;
845 union swrap_packet_payload
*pay
;
848 size_t nonwire_len
= sizeof(*frame
);
849 size_t wire_hdr_len
= 0;
851 size_t ip_hdr_len
= 0;
852 size_t icmp_hdr_len
= 0;
853 size_t icmp_truncate_len
= 0;
854 uint8_t protocol
= 0, icmp_protocol
= 0;
855 const struct sockaddr_in
*src_in
= NULL
;
856 const struct sockaddr_in
*dest_in
= NULL
;
858 const struct sockaddr_in6
*src_in6
= NULL
;
859 const struct sockaddr_in6
*dest_in6
= NULL
;
864 switch (src
->sa_family
) {
866 src_in
= (const struct sockaddr_in
*)src
;
867 dest_in
= (const struct sockaddr_in
*)dest
;
868 src_port
= src_in
->sin_port
;
869 dest_port
= dest_in
->sin_port
;
870 ip_hdr_len
= sizeof(ip
->v4
);
874 src_in6
= (const struct sockaddr_in6
*)src
;
875 dest_in6
= (const struct sockaddr_in6
*)dest
;
876 src_port
= src_in6
->sin6_port
;
877 dest_port
= dest_in6
->sin6_port
;
878 ip_hdr_len
= sizeof(ip
->v6
);
885 switch (socket_type
) {
887 protocol
= 0x06; /* TCP */
888 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
889 wire_len
= wire_hdr_len
+ payload_len
;
893 protocol
= 0x11; /* UDP */
894 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
895 wire_len
= wire_hdr_len
+ payload_len
;
903 icmp_protocol
= protocol
;
904 switch (src
->sa_family
) {
906 protocol
= 0x01; /* ICMPv4 */
907 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
911 protocol
= 0x3A; /* ICMPv6 */
912 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
916 if (wire_len
> 64 ) {
917 icmp_truncate_len
= wire_len
- 64;
919 wire_hdr_len
+= icmp_hdr_len
;
920 wire_len
+= icmp_hdr_len
;
923 packet_len
= nonwire_len
+ wire_len
;
924 alloc_len
= packet_len
;
925 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
926 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
929 base
= (uint8_t *)malloc(alloc_len
);
930 if (!base
) return NULL
;
934 frame
= (struct swrap_packet_frame
*)buf
;
935 frame
->seconds
= tval
->tv_sec
;
936 frame
->micro_seconds
= tval
->tv_usec
;
937 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
938 frame
->full_length
= wire_len
- icmp_truncate_len
;
939 buf
+= SWRAP_PACKET_FRAME_SIZE
;
941 ip
= (union swrap_packet_ip
*)buf
;
942 switch (src
->sa_family
) {
944 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
946 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
947 ip
->v4
.identification
= htons(0xFFFF);
948 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
949 ip
->v4
.fragment
= htons(0x0000);
951 ip
->v4
.protocol
= protocol
;
952 ip
->v4
.hdr_checksum
= htons(0x0000);
953 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
954 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
955 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
959 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
960 ip
->v6
.flow_label_high
= 0x00;
961 ip
->v6
.flow_label_low
= 0x0000;
962 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
);//TODO
963 ip
->v6
.next_header
= protocol
;
964 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
965 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
966 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
972 pay
= (union swrap_packet_payload
*)buf
;
973 switch (src
->sa_family
) {
975 pay
->icmp4
.type
= 0x03; /* destination unreachable */
976 pay
->icmp4
.code
= 0x01; /* host unreachable */
977 pay
->icmp4
.checksum
= htons(0x0000);
978 pay
->icmp4
.unused
= htonl(0x00000000);
979 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
981 /* set the ip header in the ICMP payload */
982 ip
= (union swrap_packet_ip
*)buf
;
983 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
985 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
986 ip
->v4
.identification
= htons(0xFFFF);
987 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
988 ip
->v4
.fragment
= htons(0x0000);
990 ip
->v4
.protocol
= icmp_protocol
;
991 ip
->v4
.hdr_checksum
= htons(0x0000);
992 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
993 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
994 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
996 src_port
= dest_in
->sin_port
;
997 dest_port
= src_in
->sin_port
;
1001 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1002 pay
->icmp6
.code
= 0x03; /* address unreachable */
1003 pay
->icmp6
.checksum
= htons(0x0000);
1004 pay
->icmp6
.unused
= htonl(0x00000000);
1005 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1007 /* set the ip header in the ICMP payload */
1008 ip
= (union swrap_packet_ip
*)buf
;
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
, dest_in6
->sin6_addr
.s6_addr
, 16);
1015 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1016 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1018 src_port
= dest_in6
->sin6_port
;
1019 dest_port
= src_in6
->sin6_port
;
1025 pay
= (union swrap_packet_payload
*)buf
;
1027 switch (socket_type
) {
1029 pay
->tcp
.source_port
= src_port
;
1030 pay
->tcp
.dest_port
= dest_port
;
1031 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1032 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1033 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1034 pay
->tcp
.control
= tcp_ctl
;
1035 pay
->tcp
.window
= htons(0x7FFF);
1036 pay
->tcp
.checksum
= htons(0x0000);
1037 pay
->tcp
.urg
= htons(0x0000);
1038 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1043 pay
->udp
.source_port
= src_port
;
1044 pay
->udp
.dest_port
= dest_port
;
1045 pay
->udp
.length
= htons(8 + payload_len
);
1046 pay
->udp
.checksum
= htons(0x0000);
1047 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1052 if (payload
&& payload_len
> 0) {
1053 memcpy(buf
, payload
, payload_len
);
1056 *_packet_len
= packet_len
- icmp_truncate_len
;
1060 static int swrap_get_pcap_fd(const char *fname
)
1064 if (fd
!= -1) return fd
;
1066 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1068 struct swrap_file_hdr file_hdr
;
1069 file_hdr
.magic
= 0xA1B2C3D4;
1070 file_hdr
.version_major
= 0x0002;
1071 file_hdr
.version_minor
= 0x0004;
1072 file_hdr
.timezone
= 0x00000000;
1073 file_hdr
.sigfigs
= 0x00000000;
1074 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1075 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1077 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1084 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
1089 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1090 const struct sockaddr
*addr
,
1091 enum swrap_packet_type type
,
1092 const void *buf
, size_t len
,
1095 const struct sockaddr
*src_addr
;
1096 const struct sockaddr
*dest_addr
;
1097 unsigned long tcp_seqno
= 0;
1098 unsigned long tcp_ack
= 0;
1099 unsigned char tcp_ctl
= 0;
1100 int unreachable
= 0;
1104 switch (si
->family
) {
1116 case SWRAP_CONNECT_SEND
:
1117 if (si
->type
!= SOCK_STREAM
) return NULL
;
1119 src_addr
= si
->myname
;
1122 tcp_seqno
= si
->io
.pck_snd
;
1123 tcp_ack
= si
->io
.pck_rcv
;
1124 tcp_ctl
= 0x02; /* SYN */
1126 si
->io
.pck_snd
+= 1;
1130 case SWRAP_CONNECT_RECV
:
1131 if (si
->type
!= SOCK_STREAM
) return NULL
;
1133 dest_addr
= si
->myname
;
1136 tcp_seqno
= si
->io
.pck_rcv
;
1137 tcp_ack
= si
->io
.pck_snd
;
1138 tcp_ctl
= 0x12; /** SYN,ACK */
1140 si
->io
.pck_rcv
+= 1;
1144 case SWRAP_CONNECT_UNREACH
:
1145 if (si
->type
!= SOCK_STREAM
) return NULL
;
1147 dest_addr
= si
->myname
;
1150 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1151 tcp_seqno
= si
->io
.pck_snd
- 1;
1152 tcp_ack
= si
->io
.pck_rcv
;
1153 tcp_ctl
= 0x02; /* SYN */
1158 case SWRAP_CONNECT_ACK
:
1159 if (si
->type
!= SOCK_STREAM
) return NULL
;
1161 src_addr
= si
->myname
;
1164 tcp_seqno
= si
->io
.pck_snd
;
1165 tcp_ack
= si
->io
.pck_rcv
;
1166 tcp_ctl
= 0x10; /* ACK */
1170 case SWRAP_ACCEPT_SEND
:
1171 if (si
->type
!= SOCK_STREAM
) return NULL
;
1173 dest_addr
= si
->myname
;
1176 tcp_seqno
= si
->io
.pck_rcv
;
1177 tcp_ack
= si
->io
.pck_snd
;
1178 tcp_ctl
= 0x02; /* SYN */
1180 si
->io
.pck_rcv
+= 1;
1184 case SWRAP_ACCEPT_RECV
:
1185 if (si
->type
!= SOCK_STREAM
) return NULL
;
1187 src_addr
= si
->myname
;
1190 tcp_seqno
= si
->io
.pck_snd
;
1191 tcp_ack
= si
->io
.pck_rcv
;
1192 tcp_ctl
= 0x12; /* SYN,ACK */
1194 si
->io
.pck_snd
+= 1;
1198 case SWRAP_ACCEPT_ACK
:
1199 if (si
->type
!= SOCK_STREAM
) return NULL
;
1201 dest_addr
= si
->myname
;
1204 tcp_seqno
= si
->io
.pck_rcv
;
1205 tcp_ack
= si
->io
.pck_snd
;
1206 tcp_ctl
= 0x10; /* ACK */
1211 src_addr
= si
->myname
;
1212 dest_addr
= si
->peername
;
1214 tcp_seqno
= si
->io
.pck_snd
;
1215 tcp_ack
= si
->io
.pck_rcv
;
1216 tcp_ctl
= 0x18; /* PSH,ACK */
1218 si
->io
.pck_snd
+= len
;
1222 case SWRAP_SEND_RST
:
1223 dest_addr
= si
->myname
;
1224 src_addr
= si
->peername
;
1226 if (si
->type
== SOCK_DGRAM
) {
1227 return swrap_marshall_packet(si
, si
->peername
,
1228 SWRAP_SENDTO_UNREACH
,
1229 buf
, len
, packet_len
);
1232 tcp_seqno
= si
->io
.pck_rcv
;
1233 tcp_ack
= si
->io
.pck_snd
;
1234 tcp_ctl
= 0x14; /** RST,ACK */
1238 case SWRAP_PENDING_RST
:
1239 dest_addr
= si
->myname
;
1240 src_addr
= si
->peername
;
1242 if (si
->type
== SOCK_DGRAM
) {
1246 tcp_seqno
= si
->io
.pck_rcv
;
1247 tcp_ack
= si
->io
.pck_snd
;
1248 tcp_ctl
= 0x14; /* RST,ACK */
1253 dest_addr
= si
->myname
;
1254 src_addr
= si
->peername
;
1256 tcp_seqno
= si
->io
.pck_rcv
;
1257 tcp_ack
= si
->io
.pck_snd
;
1258 tcp_ctl
= 0x18; /* PSH,ACK */
1260 si
->io
.pck_rcv
+= len
;
1264 case SWRAP_RECV_RST
:
1265 dest_addr
= si
->myname
;
1266 src_addr
= si
->peername
;
1268 if (si
->type
== SOCK_DGRAM
) {
1272 tcp_seqno
= si
->io
.pck_rcv
;
1273 tcp_ack
= si
->io
.pck_snd
;
1274 tcp_ctl
= 0x14; /* RST,ACK */
1279 src_addr
= si
->myname
;
1282 si
->io
.pck_snd
+= len
;
1286 case SWRAP_SENDTO_UNREACH
:
1287 dest_addr
= si
->myname
;
1294 case SWRAP_RECVFROM
:
1295 dest_addr
= si
->myname
;
1298 si
->io
.pck_rcv
+= len
;
1302 case SWRAP_CLOSE_SEND
:
1303 if (si
->type
!= SOCK_STREAM
) return NULL
;
1305 src_addr
= si
->myname
;
1306 dest_addr
= si
->peername
;
1308 tcp_seqno
= si
->io
.pck_snd
;
1309 tcp_ack
= si
->io
.pck_rcv
;
1310 tcp_ctl
= 0x11; /* FIN, ACK */
1312 si
->io
.pck_snd
+= 1;
1316 case SWRAP_CLOSE_RECV
:
1317 if (si
->type
!= SOCK_STREAM
) return NULL
;
1319 dest_addr
= si
->myname
;
1320 src_addr
= si
->peername
;
1322 tcp_seqno
= si
->io
.pck_rcv
;
1323 tcp_ack
= si
->io
.pck_snd
;
1324 tcp_ctl
= 0x11; /* FIN,ACK */
1326 si
->io
.pck_rcv
+= 1;
1330 case SWRAP_CLOSE_ACK
:
1331 if (si
->type
!= SOCK_STREAM
) return NULL
;
1333 src_addr
= si
->myname
;
1334 dest_addr
= si
->peername
;
1336 tcp_seqno
= si
->io
.pck_snd
;
1337 tcp_ack
= si
->io
.pck_rcv
;
1338 tcp_ctl
= 0x10; /* ACK */
1345 swrapGetTimeOfDay(&tv
);
1347 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1348 (const uint8_t *)buf
, len
,
1349 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
1353 static void swrap_dump_packet(struct socket_info
*si
,
1354 const struct sockaddr
*addr
,
1355 enum swrap_packet_type type
,
1356 const void *buf
, size_t len
)
1358 const char *file_name
;
1360 size_t packet_len
= 0;
1363 file_name
= socket_wrapper_pcap_file();
1368 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
1373 fd
= swrap_get_pcap_fd(file_name
);
1375 if (write(fd
, packet
, packet_len
) != packet_len
) {
1384 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1386 struct socket_info
*si
;
1388 int real_type
= type
;
1390 real_type
&= ~SOCK_CLOEXEC
;
1392 #ifdef SOCK_NONBLOCK
1393 real_type
&= ~SOCK_NONBLOCK
;
1396 if (!socket_wrapper_dir()) {
1397 return real_socket(family
, type
, protocol
);
1407 return real_socket(family
, type
, protocol
);
1409 errno
= EAFNOSUPPORT
;
1413 switch (real_type
) {
1419 errno
= EPROTONOSUPPORT
;
1427 if (real_type
== SOCK_STREAM
) {
1432 if (real_type
== SOCK_DGRAM
) {
1437 errno
= EPROTONOSUPPORT
;
1441 /* We must call real_socket with type, from the caller, not the version we removed
1442 SOCK_CLOEXEC and SOCK_NONBLOCK from */
1443 fd
= real_socket(AF_UNIX
, type
, 0);
1445 if (fd
== -1) return -1;
1447 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1449 si
->family
= family
;
1451 /* however, the rest of the socket_wrapper code expects just
1452 * the type, not the flags */
1453 si
->type
= real_type
;
1454 si
->protocol
= protocol
;
1457 SWRAP_DLIST_ADD(sockets
, si
);
1462 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1464 struct socket_info
*parent_si
, *child_si
;
1466 struct sockaddr_un un_addr
;
1467 socklen_t un_addrlen
= sizeof(un_addr
);
1468 struct sockaddr_un un_my_addr
;
1469 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1470 struct sockaddr
*my_addr
;
1471 socklen_t my_addrlen
, len
;
1474 parent_si
= find_socket_info(s
);
1476 return real_accept(s
, addr
, addrlen
);
1480 * assume out sockaddr have the same size as the in parent
1483 my_addrlen
= socket_length(parent_si
->family
);
1484 if (my_addrlen
<= 0) {
1489 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
1490 if (my_addr
== NULL
) {
1494 memset(&un_addr
, 0, sizeof(un_addr
));
1495 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1497 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1506 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1507 parent_si
->family
, my_addr
, &len
);
1514 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1515 memset(child_si
, 0, sizeof(*child_si
));
1518 child_si
->family
= parent_si
->family
;
1519 child_si
->type
= parent_si
->type
;
1520 child_si
->protocol
= parent_si
->protocol
;
1521 child_si
->bound
= 1;
1522 child_si
->is_server
= 1;
1523 child_si
->connected
= 1;
1525 child_si
->peername_len
= len
;
1526 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1528 if (addr
!= NULL
&& addrlen
!= NULL
) {
1530 if (*addrlen
>= len
)
1531 memcpy(addr
, my_addr
, len
);
1535 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1543 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1544 child_si
->family
, my_addr
, &len
);
1552 child_si
->myname_len
= len
;
1553 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1556 SWRAP_DLIST_ADD(sockets
, child_si
);
1558 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1559 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1560 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1565 static int autobind_start_init
;
1566 static int autobind_start
;
1568 /* using sendto() or connect() on an unbound socket would give the
1569 recipient no way to reply, as unlike UDP and TCP, a unix domain
1570 socket can't auto-assign emphemeral port numbers, so we need to
1572 Note: this might change the family from ipv6 to ipv4
1574 static int swrap_auto_bind(struct socket_info
*si
, int family
)
1576 struct sockaddr_un un_addr
;
1583 if (autobind_start_init
!= 1) {
1584 autobind_start_init
= 1;
1585 autobind_start
= getpid();
1586 autobind_start
%= 50000;
1587 autobind_start
+= 10000;
1590 un_addr
.sun_family
= AF_UNIX
;
1594 struct sockaddr_in in
;
1598 type
= SOCKET_TYPE_CHAR_TCP
;
1601 type
= SOCKET_TYPE_CHAR_UDP
;
1604 errno
= ESOCKTNOSUPPORT
;
1608 memset(&in
, 0, sizeof(in
));
1609 in
.sin_family
= AF_INET
;
1610 in
.sin_addr
.s_addr
= htonl(127<<24 |
1611 socket_wrapper_default_iface());
1613 si
->myname_len
= sizeof(in
);
1614 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1619 struct sockaddr_in6 in6
;
1621 if (si
->family
!= family
) {
1622 errno
= ENETUNREACH
;
1628 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1631 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1634 errno
= ESOCKTNOSUPPORT
;
1638 memset(&in6
, 0, sizeof(in6
));
1639 in6
.sin6_family
= AF_INET6
;
1640 in6
.sin6_addr
= *swrap_ipv6();
1641 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
1642 si
->myname_len
= sizeof(in6
);
1643 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1648 errno
= ESOCKTNOSUPPORT
;
1652 if (autobind_start
> 60000) {
1653 autobind_start
= 10000;
1656 for (i
=0;i
<1000;i
++) {
1657 port
= autobind_start
+ i
;
1658 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1659 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1660 type
, socket_wrapper_default_iface(), port
);
1661 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1663 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1664 if (ret
== -1) return ret
;
1666 si
->tmp_path
= strdup(un_addr
.sun_path
);
1668 autobind_start
= port
+ 1;
1676 si
->family
= family
;
1677 set_port(si
->family
, port
, si
->myname
);
1683 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1686 struct sockaddr_un un_addr
;
1687 struct socket_info
*si
= find_socket_info(s
);
1690 return real_connect(s
, serv_addr
, addrlen
);
1693 if (si
->bound
== 0) {
1694 ret
= swrap_auto_bind(si
, serv_addr
->sa_family
);
1695 if (ret
== -1) return -1;
1698 if (si
->family
!= serv_addr
->sa_family
) {
1703 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1704 if (ret
== -1) return -1;
1706 if (si
->type
== SOCK_DGRAM
) {
1707 si
->defer_connect
= 1;
1710 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1712 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1713 sizeof(struct sockaddr_un
));
1716 /* to give better errors */
1717 if (ret
== -1 && errno
== ENOENT
) {
1718 errno
= EHOSTUNREACH
;
1722 si
->peername_len
= addrlen
;
1723 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1726 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1727 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1729 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1735 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1738 struct sockaddr_un un_addr
;
1739 struct socket_info
*si
= find_socket_info(s
);
1742 return real_bind(s
, myaddr
, addrlen
);
1745 si
->myname_len
= addrlen
;
1746 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1748 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1749 if (ret
== -1) return -1;
1751 unlink(un_addr
.sun_path
);
1753 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1754 sizeof(struct sockaddr_un
));
1763 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1766 struct socket_info
*si
= find_socket_info(s
);
1769 return real_listen(s
, backlog
);
1772 ret
= real_listen(s
, backlog
);
1777 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1779 struct socket_info
*si
= find_socket_info(s
);
1782 return real_getpeername(s
, name
, addrlen
);
1791 memcpy(name
, si
->peername
, si
->peername_len
);
1792 *addrlen
= si
->peername_len
;
1797 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1799 struct socket_info
*si
= find_socket_info(s
);
1802 return real_getsockname(s
, name
, addrlen
);
1805 memcpy(name
, si
->myname
, si
->myname_len
);
1806 *addrlen
= si
->myname_len
;
1811 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1813 struct socket_info
*si
= find_socket_info(s
);
1816 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1819 if (level
== SOL_SOCKET
) {
1820 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1823 errno
= ENOPROTOOPT
;
1827 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1829 struct socket_info
*si
= find_socket_info(s
);
1832 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1835 if (level
== SOL_SOCKET
) {
1836 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1839 switch (si
->family
) {
1843 errno
= ENOPROTOOPT
;
1848 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1850 struct sockaddr_un un_addr
;
1851 socklen_t un_addrlen
= sizeof(un_addr
);
1853 struct socket_info
*si
= find_socket_info(s
);
1854 struct sockaddr_storage ss
;
1855 socklen_t ss_len
= sizeof(ss
);
1858 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1862 from
= (struct sockaddr
*)&ss
;
1866 if (si
->type
== SOCK_STREAM
) {
1867 /* cut down to 1500 byte packets for stream sockets,
1868 * which makes it easier to format PCAP capture files
1869 * (as the caller will simply continue from here) */
1870 len
= MIN(len
, 1500);
1873 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1874 memset(&un_addr
, 0, sizeof(un_addr
));
1875 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1879 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1880 si
->family
, from
, fromlen
) == -1) {
1884 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1890 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1892 struct sockaddr_un un_addr
;
1894 struct socket_info
*si
= find_socket_info(s
);
1898 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1901 if (si
->connected
) {
1908 tolen
= si
->peername_len
;
1913 /* cut down to 1500 byte packets for stream sockets,
1914 * which makes it easier to format PCAP capture files
1915 * (as the caller will simply continue from here) */
1916 len
= MIN(len
, 1500);
1918 ret
= real_send(s
, buf
, len
, flags
);
1921 if (si
->bound
== 0) {
1922 ret
= swrap_auto_bind(si
, si
->family
);
1923 if (ret
== -1) return -1;
1926 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1927 if (ret
== -1) return -1;
1932 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1935 type
= SOCKET_TYPE_CHAR_UDP
;
1937 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1938 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1939 socket_wrapper_dir(), type
, iface
, prt
);
1940 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1942 /* ignore the any errors in broadcast sends */
1943 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1946 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1951 if (si
->defer_connect
) {
1952 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1955 /* to give better errors */
1956 if (ret
== -1 && errno
== ENOENT
) {
1957 errno
= EHOSTUNREACH
;
1963 si
->defer_connect
= 0;
1966 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1970 errno
= EHOSTUNREACH
;
1974 /* to give better errors */
1975 if (ret
== -1 && errno
== ENOENT
) {
1976 errno
= EHOSTUNREACH
;
1980 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1981 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1983 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1989 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1992 struct socket_info
*si
= find_socket_info(s
);
1996 return real_ioctl(s
, r
, p
);
1999 ret
= real_ioctl(s
, r
, p
);
2003 value
= *((int *)p
);
2004 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2005 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2006 } else if (value
== 0) { /* END OF FILE */
2007 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2015 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
2018 struct socket_info
*si
= find_socket_info(s
);
2021 return real_recv(s
, buf
, len
, flags
);
2024 if (si
->type
== SOCK_STREAM
) {
2025 /* cut down to 1500 byte packets for stream sockets,
2026 * which makes it easier to format PCAP capture files
2027 * (as the caller will simply continue from here) */
2028 len
= MIN(len
, 1500);
2031 ret
= real_recv(s
, buf
, len
, flags
);
2032 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2033 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2034 } else if (ret
== 0) { /* END OF FILE */
2035 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2036 } else if (ret
> 0) {
2037 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2043 _PUBLIC_ ssize_t
swrap_read(int s
, void *buf
, size_t len
)
2046 struct socket_info
*si
= find_socket_info(s
);
2049 return real_read(s
, buf
, len
);
2052 if (si
->type
== SOCK_STREAM
) {
2053 /* cut down to 1500 byte packets for stream sockets,
2054 * which makes it easier to format PCAP capture files
2055 * (as the caller will simply continue from here) */
2056 len
= MIN(len
, 1500);
2059 ret
= real_read(s
, buf
, len
);
2060 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2061 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2062 } else if (ret
== 0) { /* END OF FILE */
2063 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2064 } else if (ret
> 0) {
2065 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2072 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
2075 struct socket_info
*si
= find_socket_info(s
);
2078 return real_send(s
, buf
, len
, flags
);
2081 if (si
->type
== SOCK_STREAM
) {
2082 /* cut down to 1500 byte packets for stream sockets,
2083 * which makes it easier to format PCAP capture files
2084 * (as the caller will simply continue from here) */
2085 len
= MIN(len
, 1500);
2088 if (si
->defer_connect
) {
2089 struct sockaddr_un un_addr
;
2092 if (si
->bound
== 0) {
2093 ret
= swrap_auto_bind(si
, si
->family
);
2094 if (ret
== -1) return -1;
2097 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2098 &un_addr
, 0, &bcast
);
2099 if (ret
== -1) return -1;
2101 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
2104 /* to give better errors */
2105 if (ret
== -1 && errno
== ENOENT
) {
2106 errno
= EHOSTUNREACH
;
2112 si
->defer_connect
= 0;
2115 ret
= real_send(s
, buf
, len
, flags
);
2118 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
2119 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2121 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2127 _PUBLIC_ ssize_t
swrap_sendmsg(int s
, const struct msghdr
*msg
, int flags
)
2135 struct socket_info
*si
= find_socket_info(s
);
2138 return real_sendmsg(s
, msg
, flags
);
2141 if (si
->defer_connect
) {
2142 struct sockaddr_un un_addr
;
2145 if (si
->bound
== 0) {
2146 ret
= swrap_auto_bind(si
, si
->family
);
2147 if (ret
== -1) return -1;
2150 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
2151 &un_addr
, 0, &bcast
);
2152 if (ret
== -1) return -1;
2154 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
2157 /* to give better errors */
2158 if (ret
== -1 && errno
== ENOENT
) {
2159 errno
= EHOSTUNREACH
;
2165 si
->defer_connect
= 0;
2168 ret
= real_sendmsg(s
, msg
, flags
);
2171 /* we capture it as one single packet */
2172 buf
= (uint8_t *)malloc(ret
);
2174 /* we just not capture the packet */
2179 for (i
=0; i
< msg
->msg_iovlen
; i
++) {
2180 size_t this_time
= MIN(remain
, msg
->msg_iov
[i
].iov_len
);
2182 msg
->msg_iov
[i
].iov_base
,
2185 remain
-= this_time
;
2188 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2191 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2197 int swrap_readv(int s
, const struct iovec
*vector
, size_t count
)
2200 struct socket_info
*si
= find_socket_info(s
);
2204 return real_readv(s
, vector
, count
);
2207 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2208 /* cut down to 1500 byte packets for stream sockets,
2209 * which makes it easier to format PCAP capture files
2210 * (as the caller will simply continue from here) */
2213 for (i
=0; i
< count
; i
++) {
2215 nlen
= len
+ vector
[i
].iov_len
;
2223 v
.iov_len
= MIN(v
.iov_len
, 1500);
2229 ret
= real_readv(s
, vector
, count
);
2230 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2231 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2232 } else if (ret
== 0) { /* END OF FILE */
2233 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
2234 } else if (ret
> 0) {
2238 size_t remain
= ret
;
2240 /* we capture it as one single packet */
2241 buf
= (uint8_t *)malloc(ret
);
2243 /* we just not capture the packet */
2248 for (i
=0; i
< count
; i
++) {
2249 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2254 remain
-= this_time
;
2257 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
2264 int swrap_writev(int s
, const struct iovec
*vector
, size_t count
)
2267 struct socket_info
*si
= find_socket_info(s
);
2271 return real_writev(s
, vector
, count
);
2274 if (si
->type
== SOCK_STREAM
&& count
> 0) {
2275 /* cut down to 1500 byte packets for stream sockets,
2276 * which makes it easier to format PCAP capture files
2277 * (as the caller will simply continue from here) */
2280 for (i
=0; i
< count
; i
++) {
2282 nlen
= len
+ vector
[i
].iov_len
;
2290 v
.iov_len
= MIN(v
.iov_len
, 1500);
2296 ret
= real_writev(s
, vector
, count
);
2298 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
2303 size_t remain
= ret
;
2305 /* we capture it as one single packet */
2306 buf
= (uint8_t *)malloc(ret
);
2308 /* we just not capture the packet */
2313 for (i
=0; i
< count
; i
++) {
2314 size_t this_time
= MIN(remain
, vector
[i
].iov_len
);
2319 remain
-= this_time
;
2322 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
2329 _PUBLIC_
int swrap_close(int fd
)
2331 struct socket_info
*si
= find_socket_info(fd
);
2335 return real_close(fd
);
2338 SWRAP_DLIST_REMOVE(sockets
, si
);
2340 if (si
->myname
&& si
->peername
) {
2341 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
2344 ret
= real_close(fd
);
2346 if (si
->myname
&& si
->peername
) {
2347 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
2348 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
2351 if (si
->path
) free(si
->path
);
2352 if (si
->myname
) free(si
->myname
);
2353 if (si
->peername
) free(si
->peername
);
2355 unlink(si
->tmp_path
);