2 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <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
46 #include "system/network.h"
47 #include "system/filesys.h"
59 #else /* _SAMBA_BUILD_ */
61 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <sys/ioctl.h>
66 #include <sys/filio.h>
69 #include <netinet/in.h>
70 #include <netinet/tcp.h>
81 #define SWRAP_DLIST_ADD(list,item) do { \
83 (item)->prev = NULL; \
84 (item)->next = NULL; \
87 (item)->prev = NULL; \
88 (item)->next = (list); \
89 (list)->prev = (item); \
94 #define SWRAP_DLIST_REMOVE(list,item) do { \
95 if ((list) == (item)) { \
96 (list) = (item)->next; \
98 (list)->prev = NULL; \
101 if ((item)->prev) { \
102 (item)->prev->next = (item)->next; \
104 if ((item)->next) { \
105 (item)->next->prev = (item)->prev; \
108 (item)->prev = NULL; \
109 (item)->next = NULL; \
112 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
114 #define REWRITE_CALLS
117 #define real_accept accept
118 #define real_connect connect
119 #define real_bind bind
120 #define real_listen listen
121 #define real_getpeername getpeername
122 #define real_getsockname getsockname
123 #define real_getsockopt getsockopt
124 #define real_setsockopt setsockopt
125 #define real_recvfrom recvfrom
126 #define real_sendto sendto
127 #define real_ioctl ioctl
128 #define real_recv recv
129 #define real_send send
130 #define real_socket socket
131 #define real_close close
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'
150 #define MAX_WRAPPED_INTERFACES 16
152 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
154 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
155 memcpy(ret
, data
, len
);
173 struct sockaddr
*myname
;
174 socklen_t myname_len
;
176 struct sockaddr
*peername
;
177 socklen_t peername_len
;
180 unsigned long pck_snd
;
181 unsigned long pck_rcv
;
184 struct socket_info
*prev
, *next
;
187 static struct socket_info
*sockets
;
190 const char *socket_wrapper_dir(void)
192 const char *s
= getenv("SOCKET_WRAPPER_DIR");
196 if (strncmp(s
, "./", 2) == 0) {
202 unsigned int socket_wrapper_default_iface(void)
204 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
208 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
213 return 1;/* 127.0.0.1 */
216 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr_in
*in
, socklen_t
*len
)
223 if ((*len
) < sizeof(struct sockaddr_in
)) {
227 p
= strrchr(un
->sun_path
, '/');
228 if (p
) p
++; else p
= un
->sun_path
;
230 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
235 if (type
!= SOCKET_TYPE_CHAR_TCP
&& type
!= SOCKET_TYPE_CHAR_UDP
) {
240 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
250 in
->sin_family
= AF_INET
;
251 in
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
252 in
->sin_port
= htons(prt
);
254 *len
= sizeof(struct sockaddr_in
);
258 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr_in
*in
, struct sockaddr_un
*un
,
265 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
266 unsigned int prt
= ntohs(in
->sin_port
);
270 if (bcast
) *bcast
= 0;
279 u_type
= SOCKET_TYPE_CHAR_TCP
;
282 u_type
= SOCKET_TYPE_CHAR_UDP
;
283 a_type
= SOCKET_TYPE_CHAR_UDP
;
284 b_type
= SOCKET_TYPE_CHAR_UDP
;
288 if (a_type
&& addr
== 0xFFFFFFFF) {
289 /* 255.255.255.255 only udp */
292 iface
= socket_wrapper_default_iface();
293 } else if (b_type
&& addr
== 0x7FFFFFFF) {
294 /* 127.255.255.255 only udp */
297 iface
= socket_wrapper_default_iface();
298 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
302 iface
= (addr
& 0x000000FF);
308 if (bcast
) *bcast
= is_bcast
;
311 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
312 socket_wrapper_dir());
313 /* the caller need to do more processing */
317 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
318 socket_wrapper_dir(), type
, iface
, prt
);
323 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr_in
*in
, struct sockaddr_un
*un
,
331 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
332 unsigned int prt
= ntohs(in
->sin_port
);
337 if (bcast
) *bcast
= 0;
341 u_type
= SOCKET_TYPE_CHAR_TCP
;
342 d_type
= SOCKET_TYPE_CHAR_TCP
;
345 u_type
= SOCKET_TYPE_CHAR_UDP
;
346 d_type
= SOCKET_TYPE_CHAR_UDP
;
347 a_type
= SOCKET_TYPE_CHAR_UDP
;
348 b_type
= SOCKET_TYPE_CHAR_UDP
;
356 iface
= socket_wrapper_default_iface();
357 } else if (a_type
&& addr
== 0xFFFFFFFF) {
358 /* 255.255.255.255 only udp */
361 iface
= socket_wrapper_default_iface();
362 } else if (b_type
&& addr
== 0x7FFFFFFF) {
363 /* 127.255.255.255 only udp */
366 iface
= socket_wrapper_default_iface();
367 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
371 iface
= (addr
& 0x000000FF);
373 errno
= EADDRNOTAVAIL
;
377 if (bcast
) *bcast
= is_bcast
;
380 /* handle auto-allocation of ephemeral ports */
381 for (prt
= 5001; prt
< 10000; prt
++) {
382 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
383 socket_wrapper_dir(), type
, iface
, prt
);
384 if (stat(un
->sun_path
, &st
) == 0) continue;
386 ((struct sockaddr_in
*)si
->myname
)->sin_port
= htons(prt
);
393 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
394 socket_wrapper_dir(), type
, iface
, prt
);
398 static struct socket_info
*find_socket_info(int fd
)
400 struct socket_info
*i
;
401 for (i
= sockets
; i
; i
= i
->next
) {
409 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
410 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
415 out_addr
->sun_family
= AF_UNIX
;
417 switch (in_addr
->sa_family
) {
424 errno
= ESOCKTNOSUPPORT
;
428 return convert_in_un_alloc(si
, (const struct sockaddr_in
*)in_addr
, out_addr
, bcast
);
430 return convert_in_un_remote(si
, (const struct sockaddr_in
*)in_addr
, out_addr
, bcast
);
436 errno
= EAFNOSUPPORT
;
440 static int sockaddr_convert_from_un(const struct socket_info
*si
,
441 const struct sockaddr_un
*in_addr
,
442 socklen_t un_addrlen
,
444 struct sockaddr
*out_addr
,
445 socklen_t
*_out_addrlen
)
447 socklen_t out_addrlen
;
449 if (out_addr
== NULL
|| _out_addrlen
== NULL
)
452 if (un_addrlen
== 0) {
457 out_addrlen
= *_out_addrlen
;
458 if (out_addrlen
> un_addrlen
) {
459 out_addrlen
= un_addrlen
;
469 errno
= ESOCKTNOSUPPORT
;
472 return convert_un_in(in_addr
, (struct sockaddr_in
*)out_addr
, _out_addrlen
);
477 errno
= EAFNOSUPPORT
;
481 enum swrap_packet_type
{
483 SWRAP_CONNECT_UNREACH
,
491 SWRAP_SENDTO_UNREACH
,
502 struct swrap_file_hdr
{
504 unsigned short version_major
;
505 unsigned short version_minor
;
507 unsigned long sigfigs
;
508 unsigned long frame_max_len
;
509 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
510 unsigned long link_type
;
512 #define SWRAP_FILE_HDR_SIZE 24
514 struct swrap_packet
{
516 unsigned long seconds
;
517 unsigned long micro_seconds
;
518 unsigned long recorded_length
;
519 unsigned long full_length
;
521 #define SWRAP_PACKET__FRAME_SIZE 16
525 unsigned char ver_hdrlen
;
527 unsigned short packet_length
;
528 unsigned short identification
;
530 unsigned char fragment
;
532 unsigned char protocol
;
533 unsigned short hdr_checksum
;
534 unsigned long src_addr
;
535 unsigned long dest_addr
;
537 #define SWRAP_PACKET__IP_HDR_SIZE 20
541 unsigned short source_port
;
542 unsigned short dest_port
;
543 unsigned long seq_num
;
544 unsigned long ack_num
;
545 unsigned char hdr_length
;
546 unsigned char control
;
547 unsigned short window
;
548 unsigned short checksum
;
551 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
553 unsigned short source_port
;
554 unsigned short dest_port
;
555 unsigned short length
;
556 unsigned short checksum
;
558 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
562 unsigned short checksum
;
563 unsigned long unused
;
565 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
569 #define SWRAP_PACKET_SIZE 56
571 static const char *socket_wrapper_pcap_file(void)
573 static int initialized
= 0;
574 static const char *s
= NULL
;
575 static const struct swrap_file_hdr h
;
576 static const struct swrap_packet p
;
578 if (initialized
== 1) {
584 * TODO: don't use the structs use plain buffer offsets
585 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
587 * for now make sure we disable PCAP support
588 * if the struct has alignment!
590 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
593 if (sizeof(p
) != SWRAP_PACKET_SIZE
) {
596 if (sizeof(p
.frame
) != SWRAP_PACKET__FRAME_SIZE
) {
599 if (sizeof(p
.ip
.hdr
) != SWRAP_PACKET__IP_HDR_SIZE
) {
602 if (sizeof(p
.ip
.p
.tcp
) != SWRAP_PACKET__IP_P_TCP_SIZE
) {
605 if (sizeof(p
.ip
.p
.udp
) != SWRAP_PACKET__IP_P_UDP_SIZE
) {
608 if (sizeof(p
.ip
.p
.icmp
) != SWRAP_PACKET__IP_P_ICMP_SIZE
) {
612 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
616 if (strncmp(s
, "./", 2) == 0) {
622 static struct swrap_packet
*swrap_packet_init(struct timeval
*tval
,
623 const struct sockaddr_in
*src_addr
,
624 const struct sockaddr_in
*dest_addr
,
626 const unsigned char *payload
,
628 unsigned long tcp_seq
,
629 unsigned long tcp_ack
,
630 unsigned char tcp_ctl
,
634 struct swrap_packet
*ret
;
635 struct swrap_packet
*packet
;
638 size_t nonwire_len
= sizeof(packet
->frame
);
639 size_t wire_hdr_len
= 0;
641 size_t icmp_hdr_len
= 0;
642 size_t icmp_truncate_len
= 0;
643 unsigned char protocol
= 0, icmp_protocol
= 0;
644 unsigned short src_port
= src_addr
->sin_port
;
645 unsigned short dest_port
= dest_addr
->sin_port
;
647 switch (socket_type
) {
649 protocol
= 0x06; /* TCP */
650 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.tcp
);
651 wire_len
= wire_hdr_len
+ payload_len
;
655 protocol
= 0x11; /* UDP */
656 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.udp
);
657 wire_len
= wire_hdr_len
+ payload_len
;
662 icmp_protocol
= protocol
;
663 protocol
= 0x01; /* ICMP */
664 if (wire_len
> 64 ) {
665 icmp_truncate_len
= wire_len
- 64;
667 icmp_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.icmp
);
668 wire_hdr_len
+= icmp_hdr_len
;
669 wire_len
+= icmp_hdr_len
;
672 packet_len
= nonwire_len
+ wire_len
;
673 alloc_len
= packet_len
;
674 if (alloc_len
< sizeof(struct swrap_packet
)) {
675 alloc_len
= sizeof(struct swrap_packet
);
677 ret
= (struct swrap_packet
*)malloc(alloc_len
);
678 if (!ret
) return NULL
;
682 packet
->frame
.seconds
= tval
->tv_sec
;
683 packet
->frame
.micro_seconds
= tval
->tv_usec
;
684 packet
->frame
.recorded_length
= wire_len
- icmp_truncate_len
;
685 packet
->frame
.full_length
= wire_len
- icmp_truncate_len
;
687 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
688 packet
->ip
.hdr
.tos
= 0x00;
689 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_truncate_len
);
690 packet
->ip
.hdr
.identification
= htons(0xFFFF);
691 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
692 packet
->ip
.hdr
.fragment
= htons(0x0000);
693 packet
->ip
.hdr
.ttl
= 0xFF;
694 packet
->ip
.hdr
.protocol
= protocol
;
695 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
696 packet
->ip
.hdr
.src_addr
= src_addr
->sin_addr
.s_addr
;
697 packet
->ip
.hdr
.dest_addr
= dest_addr
->sin_addr
.s_addr
;
700 packet
->ip
.p
.icmp
.type
= 0x03; /* destination unreachable */
701 packet
->ip
.p
.icmp
.code
= 0x01; /* host unreachable */
702 packet
->ip
.p
.icmp
.checksum
= htons(0x0000);
703 packet
->ip
.p
.icmp
.unused
= htonl(0x00000000);
705 /* set the ip header in the ICMP payload */
706 packet
= (struct swrap_packet
*)(((unsigned char *)ret
) + icmp_hdr_len
);
707 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
708 packet
->ip
.hdr
.tos
= 0x00;
709 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_hdr_len
);
710 packet
->ip
.hdr
.identification
= htons(0xFFFF);
711 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
712 packet
->ip
.hdr
.fragment
= htons(0x0000);
713 packet
->ip
.hdr
.ttl
= 0xFF;
714 packet
->ip
.hdr
.protocol
= icmp_protocol
;
715 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
716 packet
->ip
.hdr
.src_addr
= dest_addr
->sin_addr
.s_addr
;
717 packet
->ip
.hdr
.dest_addr
= src_addr
->sin_addr
.s_addr
;
719 src_port
= dest_addr
->sin_port
;
720 dest_port
= src_addr
->sin_port
;
723 switch (socket_type
) {
725 packet
->ip
.p
.tcp
.source_port
= src_port
;
726 packet
->ip
.p
.tcp
.dest_port
= dest_port
;
727 packet
->ip
.p
.tcp
.seq_num
= htonl(tcp_seq
);
728 packet
->ip
.p
.tcp
.ack_num
= htonl(tcp_ack
);
729 packet
->ip
.p
.tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
730 packet
->ip
.p
.tcp
.control
= tcp_ctl
;
731 packet
->ip
.p
.tcp
.window
= htons(0x7FFF);
732 packet
->ip
.p
.tcp
.checksum
= htons(0x0000);
733 packet
->ip
.p
.tcp
.urg
= htons(0x0000);
738 packet
->ip
.p
.udp
.source_port
= src_addr
->sin_port
;
739 packet
->ip
.p
.udp
.dest_port
= dest_addr
->sin_port
;
740 packet
->ip
.p
.udp
.length
= htons(8 + payload_len
);
741 packet
->ip
.p
.udp
.checksum
= htons(0x0000);
746 if (payload
&& payload_len
> 0) {
747 unsigned char *p
= (unsigned char *)ret
;
750 memcpy(p
, payload
, payload_len
);
753 *_packet_len
= packet_len
- icmp_truncate_len
;
757 static int swrap_get_pcap_fd(const char *fname
)
761 if (fd
!= -1) return fd
;
763 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
765 struct swrap_file_hdr file_hdr
;
766 file_hdr
.magic
= 0xA1B2C3D4;
767 file_hdr
.version_major
= 0x0002;
768 file_hdr
.version_minor
= 0x0004;
769 file_hdr
.timezone
= 0x00000000;
770 file_hdr
.sigfigs
= 0x00000000;
771 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
772 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
774 write(fd
, &file_hdr
, sizeof(file_hdr
));
778 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
783 static void swrap_dump_packet(struct socket_info
*si
, const struct sockaddr
*addr
,
784 enum swrap_packet_type type
,
785 const void *buf
, size_t len
)
787 const struct sockaddr_in
*src_addr
;
788 const struct sockaddr_in
*dest_addr
;
789 const char *file_name
;
790 unsigned long tcp_seq
= 0;
791 unsigned long tcp_ack
= 0;
792 unsigned char tcp_ctl
= 0;
795 struct swrap_packet
*packet
;
796 size_t packet_len
= 0;
799 file_name
= socket_wrapper_pcap_file();
804 if (si
->family
!= AF_INET
) {
809 case SWRAP_CONNECT_SEND
:
810 if (si
->type
!= SOCK_STREAM
) return;
812 src_addr
= (const struct sockaddr_in
*)si
->myname
;
813 dest_addr
= (const struct sockaddr_in
*)addr
;
815 tcp_seq
= si
->io
.pck_snd
;
816 tcp_ack
= si
->io
.pck_rcv
;
817 tcp_ctl
= 0x02; /* SYN */
823 case SWRAP_CONNECT_RECV
:
824 if (si
->type
!= SOCK_STREAM
) return;
826 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
827 src_addr
= (const struct sockaddr_in
*)addr
;
829 tcp_seq
= si
->io
.pck_rcv
;
830 tcp_ack
= si
->io
.pck_snd
;
831 tcp_ctl
= 0x12; /** SYN,ACK */
837 case SWRAP_CONNECT_UNREACH
:
838 if (si
->type
!= SOCK_STREAM
) return;
840 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
841 src_addr
= (const struct sockaddr_in
*)addr
;
843 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
844 tcp_seq
= si
->io
.pck_snd
- 1;
845 tcp_ack
= si
->io
.pck_rcv
;
846 tcp_ctl
= 0x02; /* SYN */
851 case SWRAP_CONNECT_ACK
:
852 if (si
->type
!= SOCK_STREAM
) return;
854 src_addr
= (const struct sockaddr_in
*)si
->myname
;
855 dest_addr
= (const struct sockaddr_in
*)addr
;
857 tcp_seq
= si
->io
.pck_snd
;
858 tcp_ack
= si
->io
.pck_rcv
;
859 tcp_ctl
= 0x10; /* ACK */
863 case SWRAP_ACCEPT_SEND
:
864 if (si
->type
!= SOCK_STREAM
) return;
866 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
867 src_addr
= (const struct sockaddr_in
*)addr
;
869 tcp_seq
= si
->io
.pck_rcv
;
870 tcp_ack
= si
->io
.pck_snd
;
871 tcp_ctl
= 0x02; /* SYN */
877 case SWRAP_ACCEPT_RECV
:
878 if (si
->type
!= SOCK_STREAM
) return;
880 src_addr
= (const struct sockaddr_in
*)si
->myname
;
881 dest_addr
= (const struct sockaddr_in
*)addr
;
883 tcp_seq
= si
->io
.pck_snd
;
884 tcp_ack
= si
->io
.pck_rcv
;
885 tcp_ctl
= 0x12; /* SYN,ACK */
891 case SWRAP_ACCEPT_ACK
:
892 if (si
->type
!= SOCK_STREAM
) return;
894 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
895 src_addr
= (const struct sockaddr_in
*)addr
;
897 tcp_seq
= si
->io
.pck_rcv
;
898 tcp_ack
= si
->io
.pck_snd
;
899 tcp_ctl
= 0x10; /* ACK */
904 src_addr
= (const struct sockaddr_in
*)si
->myname
;
905 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
907 tcp_seq
= si
->io
.pck_snd
;
908 tcp_ack
= si
->io
.pck_rcv
;
909 tcp_ctl
= 0x18; /* PSH,ACK */
911 si
->io
.pck_snd
+= len
;
916 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
917 src_addr
= (const struct sockaddr_in
*)si
->peername
;
919 if (si
->type
== SOCK_DGRAM
) {
920 swrap_dump_packet(si
, si
->peername
,
921 SWRAP_SENDTO_UNREACH
,
926 tcp_seq
= si
->io
.pck_rcv
;
927 tcp_ack
= si
->io
.pck_snd
;
928 tcp_ctl
= 0x14; /** RST,ACK */
932 case SWRAP_PENDING_RST
:
933 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
934 src_addr
= (const struct sockaddr_in
*)si
->peername
;
936 if (si
->type
== SOCK_DGRAM
) {
940 tcp_seq
= si
->io
.pck_rcv
;
941 tcp_ack
= si
->io
.pck_snd
;
942 tcp_ctl
= 0x14; /* RST,ACK */
947 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
948 src_addr
= (const struct sockaddr_in
*)si
->peername
;
950 tcp_seq
= si
->io
.pck_rcv
;
951 tcp_ack
= si
->io
.pck_snd
;
952 tcp_ctl
= 0x18; /* PSH,ACK */
954 si
->io
.pck_rcv
+= len
;
959 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
960 src_addr
= (const struct sockaddr_in
*)si
->peername
;
962 if (si
->type
== SOCK_DGRAM
) {
966 tcp_seq
= si
->io
.pck_rcv
;
967 tcp_ack
= si
->io
.pck_snd
;
968 tcp_ctl
= 0x14; /* RST,ACK */
973 src_addr
= (const struct sockaddr_in
*)si
->myname
;
974 dest_addr
= (const struct sockaddr_in
*)addr
;
976 si
->io
.pck_snd
+= len
;
980 case SWRAP_SENDTO_UNREACH
:
981 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
982 src_addr
= (const struct sockaddr_in
*)addr
;
989 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
990 src_addr
= (const struct sockaddr_in
*)addr
;
992 si
->io
.pck_rcv
+= len
;
996 case SWRAP_CLOSE_SEND
:
997 if (si
->type
!= SOCK_STREAM
) return;
999 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1000 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
1002 tcp_seq
= si
->io
.pck_snd
;
1003 tcp_ack
= si
->io
.pck_rcv
;
1004 tcp_ctl
= 0x11; /* FIN, ACK */
1006 si
->io
.pck_snd
+= 1;
1010 case SWRAP_CLOSE_RECV
:
1011 if (si
->type
!= SOCK_STREAM
) return;
1013 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1014 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1016 tcp_seq
= si
->io
.pck_rcv
;
1017 tcp_ack
= si
->io
.pck_snd
;
1018 tcp_ctl
= 0x11; /* FIN,ACK */
1020 si
->io
.pck_rcv
+= 1;
1024 case SWRAP_CLOSE_ACK
:
1025 if (si
->type
!= SOCK_STREAM
) return;
1027 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1028 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
1030 tcp_seq
= si
->io
.pck_snd
;
1031 tcp_ack
= si
->io
.pck_rcv
;
1032 tcp_ctl
= 0x10; /* ACK */
1039 swrapGetTimeOfDay(&tv
);
1041 packet
= swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1042 (const unsigned char *)buf
, len
,
1043 tcp_seq
, tcp_ack
, tcp_ctl
, unreachable
,
1049 fd
= swrap_get_pcap_fd(file_name
);
1051 write(fd
, packet
, packet_len
);
1057 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1059 struct socket_info
*si
;
1062 if (!socket_wrapper_dir()) {
1063 return real_socket(family
, type
, protocol
);
1070 return real_socket(family
, type
, protocol
);
1072 errno
= EAFNOSUPPORT
;
1082 errno
= EPROTONOSUPPORT
;
1090 errno
= EPROTONOSUPPORT
;
1094 fd
= real_socket(AF_UNIX
, type
, 0);
1096 if (fd
== -1) return -1;
1098 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1100 si
->family
= family
;
1102 si
->protocol
= protocol
;
1105 SWRAP_DLIST_ADD(sockets
, si
);
1110 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1112 struct socket_info
*parent_si
, *child_si
;
1114 struct sockaddr_un un_addr
;
1115 socklen_t un_addrlen
= sizeof(un_addr
);
1116 struct sockaddr_un un_my_addr
;
1117 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1118 struct sockaddr my_addr
;
1119 socklen_t my_addrlen
= sizeof(my_addr
);
1122 parent_si
= find_socket_info(s
);
1124 return real_accept(s
, addr
, addrlen
);
1127 memset(&un_addr
, 0, sizeof(un_addr
));
1128 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1129 memset(&my_addr
, 0, sizeof(my_addr
));
1131 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1132 if (ret
== -1) return ret
;
1136 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1137 parent_si
->family
, addr
, addrlen
);
1143 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1144 memset(child_si
, 0, sizeof(*child_si
));
1147 child_si
->family
= parent_si
->family
;
1148 child_si
->type
= parent_si
->type
;
1149 child_si
->protocol
= parent_si
->protocol
;
1150 child_si
->bound
= 1;
1151 child_si
->is_server
= 1;
1153 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1160 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1161 child_si
->family
, &my_addr
, &my_addrlen
);
1168 child_si
->myname_len
= my_addrlen
;
1169 child_si
->myname
= sockaddr_dup(&my_addr
, my_addrlen
);
1171 child_si
->peername_len
= *addrlen
;
1172 child_si
->peername
= sockaddr_dup(addr
, *addrlen
);
1174 SWRAP_DLIST_ADD(sockets
, child_si
);
1176 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1177 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1178 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1183 static int autobind_start_init
;
1184 static int autobind_start
;
1186 /* using sendto() or connect() on an unbound socket would give the
1187 recipient no way to reply, as unlike UDP and TCP, a unix domain
1188 socket can't auto-assign emphemeral port numbers, so we need to
1190 static int swrap_auto_bind(struct socket_info
*si
)
1192 struct sockaddr_un un_addr
;
1193 struct sockaddr_in in
;
1200 if (autobind_start_init
!= 1) {
1201 autobind_start_init
= 1;
1202 autobind_start
= getpid();
1203 autobind_start
%= 50000;
1204 autobind_start
+= 10000;
1207 un_addr
.sun_family
= AF_UNIX
;
1211 type
= SOCKET_TYPE_CHAR_TCP
;
1214 type
= SOCKET_TYPE_CHAR_UDP
;
1217 errno
= ESOCKTNOSUPPORT
;
1221 if (autobind_start
> 60000) {
1222 autobind_start
= 10000;
1225 for (i
=0;i
<1000;i
++) {
1226 port
= autobind_start
+ i
;
1227 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1228 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1229 type
, socket_wrapper_default_iface(), port
);
1230 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1232 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1233 if (ret
== -1) return ret
;
1235 si
->tmp_path
= strdup(un_addr
.sun_path
);
1237 autobind_start
= port
+ 1;
1245 memset(&in
, 0, sizeof(in
));
1246 in
.sin_family
= AF_INET
;
1247 in
.sin_port
= htons(port
);
1248 in
.sin_addr
.s_addr
= htonl(127<<24 | socket_wrapper_default_iface());
1250 si
->myname_len
= sizeof(in
);
1251 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1256 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1259 struct sockaddr_un un_addr
;
1260 struct socket_info
*si
= find_socket_info(s
);
1263 return real_connect(s
, serv_addr
, addrlen
);
1266 if (si
->bound
== 0) {
1267 ret
= swrap_auto_bind(si
);
1268 if (ret
== -1) return -1;
1271 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1272 if (ret
== -1) return -1;
1274 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1276 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1277 sizeof(struct sockaddr_un
));
1279 /* to give better errors */
1280 if (ret
== -1 && errno
== ENOENT
) {
1281 errno
= EHOSTUNREACH
;
1285 si
->peername_len
= addrlen
;
1286 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1288 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1289 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1291 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1297 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1300 struct sockaddr_un un_addr
;
1301 struct socket_info
*si
= find_socket_info(s
);
1304 return real_bind(s
, myaddr
, addrlen
);
1307 si
->myname_len
= addrlen
;
1308 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1310 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1311 if (ret
== -1) return -1;
1313 unlink(un_addr
.sun_path
);
1315 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1316 sizeof(struct sockaddr_un
));
1325 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1328 struct socket_info
*si
= find_socket_info(s
);
1331 return real_listen(s
, backlog
);
1334 ret
= real_listen(s
, backlog
);
1339 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1341 struct socket_info
*si
= find_socket_info(s
);
1344 return real_getpeername(s
, name
, addrlen
);
1353 memcpy(name
, si
->peername
, si
->peername_len
);
1354 *addrlen
= si
->peername_len
;
1359 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1361 struct socket_info
*si
= find_socket_info(s
);
1364 return real_getsockname(s
, name
, addrlen
);
1367 memcpy(name
, si
->myname
, si
->myname_len
);
1368 *addrlen
= si
->myname_len
;
1373 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1375 struct socket_info
*si
= find_socket_info(s
);
1378 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1381 if (level
== SOL_SOCKET
) {
1382 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1385 errno
= ENOPROTOOPT
;
1389 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1391 struct socket_info
*si
= find_socket_info(s
);
1394 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1397 if (level
== SOL_SOCKET
) {
1398 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1401 switch (si
->family
) {
1405 errno
= ENOPROTOOPT
;
1410 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1412 struct sockaddr_un un_addr
;
1413 socklen_t un_addrlen
= sizeof(un_addr
);
1415 struct socket_info
*si
= find_socket_info(s
);
1418 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1421 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1422 memset(&un_addr
, 0, sizeof(un_addr
));
1423 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1427 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1428 si
->family
, from
, fromlen
) == -1) {
1432 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1438 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1440 struct sockaddr_un un_addr
;
1442 struct socket_info
*si
= find_socket_info(s
);
1446 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1449 if (si
->bound
== 0) {
1450 ret
= swrap_auto_bind(si
);
1451 if (ret
== -1) return -1;
1454 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1455 if (ret
== -1) return -1;
1460 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1463 type
= SOCKET_TYPE_CHAR_UDP
;
1465 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1466 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1467 socket_wrapper_dir(), type
, iface
, prt
);
1468 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1470 /* ignore the any errors in broadcast sends */
1471 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1474 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1479 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1481 /* to give better errors */
1482 if (ret
== -1 && errno
== ENOENT
) {
1483 errno
= EHOSTUNREACH
;
1487 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1488 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1490 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1496 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1499 struct socket_info
*si
= find_socket_info(s
);
1503 return real_ioctl(s
, r
, p
);
1506 ret
= real_ioctl(s
, r
, p
);
1510 value
= *((int *)p
);
1511 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1512 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1513 } else if (value
== 0) { /* END OF FILE */
1514 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1522 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1525 struct socket_info
*si
= find_socket_info(s
);
1528 return real_recv(s
, buf
, len
, flags
);
1531 ret
= real_recv(s
, buf
, len
, flags
);
1532 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1533 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1534 } else if (ret
== 0) { /* END OF FILE */
1535 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1537 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1544 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1547 struct socket_info
*si
= find_socket_info(s
);
1550 return real_send(s
, buf
, len
, flags
);
1553 ret
= real_send(s
, buf
, len
, flags
);
1556 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
1557 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
1559 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
1565 _PUBLIC_
int swrap_close(int fd
)
1567 struct socket_info
*si
= find_socket_info(fd
);
1571 return real_close(fd
);
1574 SWRAP_DLIST_REMOVE(sockets
, si
);
1576 if (si
->myname
&& si
->peername
) {
1577 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
1580 ret
= real_close(fd
);
1582 if (si
->myname
&& si
->peername
) {
1583 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
1584 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
1587 if (si
->path
) free(si
->path
);
1588 if (si
->myname
) free(si
->myname
);
1589 if (si
->peername
) free(si
->peername
);
1591 unlink(si
->tmp_path
);