2 Socket wrapper library. Passes all socket communication over
3 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
5 Copyright (C) Jelmer Vernooij 2005
6 Copyright (C) Stefan Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define SOCKET_WRAPPER_NOT_REPLACE
27 #include "system/network.h"
28 #include "system/filesys.h"
31 #include "lib/util/dlinklist.h"
44 #else /* _SAMBA_BUILD_ */
46 #include <sys/types.h>
48 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <netinet/tcp.h>
58 #error "dlinklist.h missing"
62 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
67 #define real_accept accept
68 #define real_connect connect
69 #define real_bind bind
70 #define real_listen listen
71 #define real_getpeername getpeername
72 #define real_getsockname getsockname
73 #define real_getsockopt getsockopt
74 #define real_setsockopt setsockopt
75 #define real_recvfrom recvfrom
76 #define real_sendto sendto
77 #define real_ioctl ioctl
78 #define real_recv recv
79 #define real_send send
80 #define real_socket socket
81 #define real_close close
84 #ifdef HAVE_GETTIMEOFDAY_TZ
85 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
87 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
90 /* we need to use a very terse format here as IRIX 6.4 silently
91 truncates names to 16 chars, so if we use a longer name then we
92 can't tell which port a packet came from with recvfrom()
94 with this format we have 8 chars left for the directory name
96 #define SOCKET_FORMAT "%c%02X%04X"
97 #define SOCKET_TYPE_CHAR_TCP 'T'
98 #define SOCKET_TYPE_CHAR_UDP 'U'
100 #define MAX_WRAPPED_INTERFACES 16
102 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
104 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
105 memcpy(ret
, data
, len
);
123 struct sockaddr
*myname
;
124 socklen_t myname_len
;
126 struct sockaddr
*peername
;
127 socklen_t peername_len
;
130 unsigned long pck_snd
;
131 unsigned long pck_rcv
;
134 struct socket_info
*prev
, *next
;
137 static struct socket_info
*sockets
;
140 static const char *socket_wrapper_dir(void)
142 const char *s
= getenv("SOCKET_WRAPPER_DIR");
146 if (strncmp(s
, "./", 2) == 0) {
152 static unsigned int socket_wrapper_default_iface(void)
154 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
157 if (sscanf(s
, "%u", &iface
) == 1) {
158 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
164 return 1;/* 127.0.0.1 */
167 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr_in
*in
, socklen_t
*len
)
174 if ((*len
) < sizeof(struct sockaddr_in
)) {
178 p
= strrchr(un
->sun_path
, '/');
179 if (p
) p
++; else p
= un
->sun_path
;
181 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
186 if (type
!= SOCKET_TYPE_CHAR_TCP
&& type
!= SOCKET_TYPE_CHAR_UDP
) {
191 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
201 in
->sin_family
= AF_INET
;
202 in
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
203 in
->sin_port
= htons(prt
);
205 *len
= sizeof(struct sockaddr_in
);
209 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr_in
*in
, struct sockaddr_un
*un
,
216 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
217 unsigned int prt
= ntohs(in
->sin_port
);
221 if (bcast
) *bcast
= 0;
230 u_type
= SOCKET_TYPE_CHAR_TCP
;
233 u_type
= SOCKET_TYPE_CHAR_UDP
;
234 a_type
= SOCKET_TYPE_CHAR_UDP
;
235 b_type
= SOCKET_TYPE_CHAR_UDP
;
239 if (a_type
&& addr
== 0xFFFFFFFF) {
240 /* 255.255.255.255 only udp */
243 iface
= socket_wrapper_default_iface();
244 } else if (b_type
&& addr
== 0x7FFFFFFF) {
245 /* 127.255.255.255 only udp */
248 iface
= socket_wrapper_default_iface();
249 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
253 iface
= (addr
& 0x000000FF);
259 if (bcast
) *bcast
= is_bcast
;
262 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
263 socket_wrapper_dir());
264 /* the caller need to do more processing */
268 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
269 socket_wrapper_dir(), type
, iface
, prt
);
274 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr_in
*in
, struct sockaddr_un
*un
,
282 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
283 unsigned int prt
= ntohs(in
->sin_port
);
288 if (bcast
) *bcast
= 0;
292 u_type
= SOCKET_TYPE_CHAR_TCP
;
293 d_type
= SOCKET_TYPE_CHAR_TCP
;
296 u_type
= SOCKET_TYPE_CHAR_UDP
;
297 d_type
= SOCKET_TYPE_CHAR_UDP
;
298 a_type
= SOCKET_TYPE_CHAR_UDP
;
299 b_type
= SOCKET_TYPE_CHAR_UDP
;
307 iface
= socket_wrapper_default_iface();
308 } else if (a_type
&& addr
== 0xFFFFFFFF) {
309 /* 255.255.255.255 only udp */
312 iface
= socket_wrapper_default_iface();
313 } else if (b_type
&& addr
== 0x7FFFFFFF) {
314 /* 127.255.255.255 only udp */
317 iface
= socket_wrapper_default_iface();
318 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
322 iface
= (addr
& 0x000000FF);
324 errno
= EADDRNOTAVAIL
;
328 if (bcast
) *bcast
= is_bcast
;
331 /* handle auto-allocation of ephemeral ports */
332 for (prt
= 5001; prt
< 10000; prt
++) {
333 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
334 socket_wrapper_dir(), type
, iface
, prt
);
335 if (stat(un
->sun_path
, &st
) == 0) continue;
337 ((struct sockaddr_in
*)si
->myname
)->sin_port
= htons(prt
);
344 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
345 socket_wrapper_dir(), type
, iface
, prt
);
349 static struct socket_info
*find_socket_info(int fd
)
351 struct socket_info
*i
;
352 for (i
= sockets
; i
; i
= i
->next
) {
360 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
361 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
366 out_addr
->sun_family
= AF_UNIX
;
368 switch (in_addr
->sa_family
) {
375 errno
= ESOCKTNOSUPPORT
;
379 return convert_in_un_alloc(si
, (const struct sockaddr_in
*)in_addr
, out_addr
, bcast
);
381 return convert_in_un_remote(si
, (const struct sockaddr_in
*)in_addr
, out_addr
, bcast
);
387 errno
= EAFNOSUPPORT
;
391 static int sockaddr_convert_from_un(const struct socket_info
*si
,
392 const struct sockaddr_un
*in_addr
,
393 socklen_t un_addrlen
,
395 struct sockaddr
*out_addr
,
396 socklen_t
*_out_addrlen
)
398 socklen_t out_addrlen
;
400 if (out_addr
== NULL
|| _out_addrlen
== NULL
)
403 if (un_addrlen
== 0) {
408 out_addrlen
= *_out_addrlen
;
409 if (out_addrlen
> un_addrlen
) {
410 out_addrlen
= un_addrlen
;
420 errno
= ESOCKTNOSUPPORT
;
423 return convert_un_in(in_addr
, (struct sockaddr_in
*)out_addr
, _out_addrlen
);
428 errno
= EAFNOSUPPORT
;
432 enum swrap_packet_type
{
434 SWRAP_CONNECT_UNREACH
,
442 SWRAP_SENDTO_UNREACH
,
453 struct swrap_file_hdr
{
455 unsigned short version_major
;
456 unsigned short version_minor
;
458 unsigned long sigfigs
;
459 unsigned long frame_max_len
;
460 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
461 unsigned long link_type
;
463 #define SWRAP_FILE_HDR_SIZE 24
465 struct swrap_packet
{
467 unsigned long seconds
;
468 unsigned long micro_seconds
;
469 unsigned long recorded_length
;
470 unsigned long full_length
;
472 #define SWRAP_PACKET__FRAME_SIZE 16
476 unsigned char ver_hdrlen
;
478 unsigned short packet_length
;
479 unsigned short identification
;
481 unsigned char fragment
;
483 unsigned char protocol
;
484 unsigned short hdr_checksum
;
485 unsigned long src_addr
;
486 unsigned long dest_addr
;
488 #define SWRAP_PACKET__IP_HDR_SIZE 20
492 unsigned short source_port
;
493 unsigned short dest_port
;
494 unsigned long seq_num
;
495 unsigned long ack_num
;
496 unsigned char hdr_length
;
497 unsigned char control
;
498 unsigned short window
;
499 unsigned short checksum
;
502 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
504 unsigned short source_port
;
505 unsigned short dest_port
;
506 unsigned short length
;
507 unsigned short checksum
;
509 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
513 unsigned short checksum
;
514 unsigned long unused
;
516 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
520 #define SWRAP_PACKET_SIZE 56
522 static const char *socket_wrapper_pcap_file(void)
524 static int initialized
= 0;
525 static const char *s
= NULL
;
526 static const struct swrap_file_hdr h
;
527 static const struct swrap_packet p
;
529 if (initialized
== 1) {
535 * TODO: don't use the structs use plain buffer offsets
536 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
538 * for now make sure we disable PCAP support
539 * if the struct has alignment!
541 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
544 if (sizeof(p
) != SWRAP_PACKET_SIZE
) {
547 if (sizeof(p
.frame
) != SWRAP_PACKET__FRAME_SIZE
) {
550 if (sizeof(p
.ip
.hdr
) != SWRAP_PACKET__IP_HDR_SIZE
) {
553 if (sizeof(p
.ip
.p
.tcp
) != SWRAP_PACKET__IP_P_TCP_SIZE
) {
556 if (sizeof(p
.ip
.p
.udp
) != SWRAP_PACKET__IP_P_UDP_SIZE
) {
559 if (sizeof(p
.ip
.p
.icmp
) != SWRAP_PACKET__IP_P_ICMP_SIZE
) {
563 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
567 if (strncmp(s
, "./", 2) == 0) {
573 static struct swrap_packet
*swrap_packet_init(struct timeval
*tval
,
574 const struct sockaddr_in
*src_addr
,
575 const struct sockaddr_in
*dest_addr
,
577 const unsigned char *payload
,
579 unsigned long tcp_seq
,
580 unsigned long tcp_ack
,
581 unsigned char tcp_ctl
,
585 struct swrap_packet
*ret
;
586 struct swrap_packet
*packet
;
589 size_t nonwire_len
= sizeof(packet
->frame
);
590 size_t wire_hdr_len
= 0;
592 size_t icmp_hdr_len
= 0;
593 size_t icmp_truncate_len
= 0;
594 unsigned char protocol
= 0, icmp_protocol
= 0;
595 unsigned short src_port
= src_addr
->sin_port
;
596 unsigned short dest_port
= dest_addr
->sin_port
;
598 switch (socket_type
) {
600 protocol
= 0x06; /* TCP */
601 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.tcp
);
602 wire_len
= wire_hdr_len
+ payload_len
;
606 protocol
= 0x11; /* UDP */
607 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.udp
);
608 wire_len
= wire_hdr_len
+ payload_len
;
613 icmp_protocol
= protocol
;
614 protocol
= 0x01; /* ICMP */
615 if (wire_len
> 64 ) {
616 icmp_truncate_len
= wire_len
- 64;
618 icmp_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.icmp
);
619 wire_hdr_len
+= icmp_hdr_len
;
620 wire_len
+= icmp_hdr_len
;
623 packet_len
= nonwire_len
+ wire_len
;
624 alloc_len
= packet_len
;
625 if (alloc_len
< sizeof(struct swrap_packet
)) {
626 alloc_len
= sizeof(struct swrap_packet
);
628 ret
= (struct swrap_packet
*)malloc(alloc_len
);
629 if (!ret
) return NULL
;
633 packet
->frame
.seconds
= tval
->tv_sec
;
634 packet
->frame
.micro_seconds
= tval
->tv_usec
;
635 packet
->frame
.recorded_length
= wire_len
- icmp_truncate_len
;
636 packet
->frame
.full_length
= wire_len
- icmp_truncate_len
;
638 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
639 packet
->ip
.hdr
.tos
= 0x00;
640 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_truncate_len
);
641 packet
->ip
.hdr
.identification
= htons(0xFFFF);
642 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
643 packet
->ip
.hdr
.fragment
= htons(0x0000);
644 packet
->ip
.hdr
.ttl
= 0xFF;
645 packet
->ip
.hdr
.protocol
= protocol
;
646 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
647 packet
->ip
.hdr
.src_addr
= src_addr
->sin_addr
.s_addr
;
648 packet
->ip
.hdr
.dest_addr
= dest_addr
->sin_addr
.s_addr
;
651 packet
->ip
.p
.icmp
.type
= 0x03; /* destination unreachable */
652 packet
->ip
.p
.icmp
.code
= 0x01; /* host unreachable */
653 packet
->ip
.p
.icmp
.checksum
= htons(0x0000);
654 packet
->ip
.p
.icmp
.unused
= htonl(0x00000000);
656 /* set the ip header in the ICMP payload */
657 packet
= (struct swrap_packet
*)(((unsigned char *)ret
) + icmp_hdr_len
);
658 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
659 packet
->ip
.hdr
.tos
= 0x00;
660 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_hdr_len
);
661 packet
->ip
.hdr
.identification
= htons(0xFFFF);
662 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
663 packet
->ip
.hdr
.fragment
= htons(0x0000);
664 packet
->ip
.hdr
.ttl
= 0xFF;
665 packet
->ip
.hdr
.protocol
= icmp_protocol
;
666 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
667 packet
->ip
.hdr
.src_addr
= dest_addr
->sin_addr
.s_addr
;
668 packet
->ip
.hdr
.dest_addr
= src_addr
->sin_addr
.s_addr
;
670 src_port
= dest_addr
->sin_port
;
671 dest_port
= src_addr
->sin_port
;
674 switch (socket_type
) {
676 packet
->ip
.p
.tcp
.source_port
= src_port
;
677 packet
->ip
.p
.tcp
.dest_port
= dest_port
;
678 packet
->ip
.p
.tcp
.seq_num
= htonl(tcp_seq
);
679 packet
->ip
.p
.tcp
.ack_num
= htonl(tcp_ack
);
680 packet
->ip
.p
.tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
681 packet
->ip
.p
.tcp
.control
= tcp_ctl
;
682 packet
->ip
.p
.tcp
.window
= htons(0x7FFF);
683 packet
->ip
.p
.tcp
.checksum
= htons(0x0000);
684 packet
->ip
.p
.tcp
.urg
= htons(0x0000);
689 packet
->ip
.p
.udp
.source_port
= src_addr
->sin_port
;
690 packet
->ip
.p
.udp
.dest_port
= dest_addr
->sin_port
;
691 packet
->ip
.p
.udp
.length
= htons(8 + payload_len
);
692 packet
->ip
.p
.udp
.checksum
= htons(0x0000);
697 if (payload
&& payload_len
> 0) {
698 unsigned char *p
= (unsigned char *)ret
;
701 memcpy(p
, payload
, payload_len
);
704 *_packet_len
= packet_len
- icmp_truncate_len
;
708 static int swrap_get_pcap_fd(const char *fname
)
712 if (fd
!= -1) return fd
;
714 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
716 struct swrap_file_hdr file_hdr
;
717 file_hdr
.magic
= 0xA1B2C3D4;
718 file_hdr
.version_major
= 0x0002;
719 file_hdr
.version_minor
= 0x0004;
720 file_hdr
.timezone
= 0x00000000;
721 file_hdr
.sigfigs
= 0x00000000;
722 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
723 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
725 write(fd
, &file_hdr
, sizeof(file_hdr
));
729 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
734 static void swrap_dump_packet(struct socket_info
*si
, const struct sockaddr
*addr
,
735 enum swrap_packet_type type
,
736 const void *buf
, size_t len
)
738 const struct sockaddr_in
*src_addr
;
739 const struct sockaddr_in
*dest_addr
;
740 const char *file_name
;
741 unsigned long tcp_seq
= 0;
742 unsigned long tcp_ack
= 0;
743 unsigned char tcp_ctl
= 0;
746 struct swrap_packet
*packet
;
747 size_t packet_len
= 0;
750 file_name
= socket_wrapper_pcap_file();
755 if (si
->family
!= AF_INET
) {
760 case SWRAP_CONNECT_SEND
:
761 if (si
->type
!= SOCK_STREAM
) return;
763 src_addr
= (const struct sockaddr_in
*)si
->myname
;
764 dest_addr
= (const struct sockaddr_in
*)addr
;
766 tcp_seq
= si
->io
.pck_snd
;
767 tcp_ack
= si
->io
.pck_rcv
;
768 tcp_ctl
= 0x02; /* SYN */
774 case SWRAP_CONNECT_RECV
:
775 if (si
->type
!= SOCK_STREAM
) return;
777 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
778 src_addr
= (const struct sockaddr_in
*)addr
;
780 tcp_seq
= si
->io
.pck_rcv
;
781 tcp_ack
= si
->io
.pck_snd
;
782 tcp_ctl
= 0x12; /** SYN,ACK */
788 case SWRAP_CONNECT_UNREACH
:
789 if (si
->type
!= SOCK_STREAM
) return;
791 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
792 src_addr
= (const struct sockaddr_in
*)addr
;
794 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
795 tcp_seq
= si
->io
.pck_snd
- 1;
796 tcp_ack
= si
->io
.pck_rcv
;
797 tcp_ctl
= 0x02; /* SYN */
802 case SWRAP_CONNECT_ACK
:
803 if (si
->type
!= SOCK_STREAM
) return;
805 src_addr
= (const struct sockaddr_in
*)si
->myname
;
806 dest_addr
= (const struct sockaddr_in
*)addr
;
808 tcp_seq
= si
->io
.pck_snd
;
809 tcp_ack
= si
->io
.pck_rcv
;
810 tcp_ctl
= 0x10; /* ACK */
814 case SWRAP_ACCEPT_SEND
:
815 if (si
->type
!= SOCK_STREAM
) return;
817 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
818 src_addr
= (const struct sockaddr_in
*)addr
;
820 tcp_seq
= si
->io
.pck_rcv
;
821 tcp_ack
= si
->io
.pck_snd
;
822 tcp_ctl
= 0x02; /* SYN */
828 case SWRAP_ACCEPT_RECV
:
829 if (si
->type
!= SOCK_STREAM
) return;
831 src_addr
= (const struct sockaddr_in
*)si
->myname
;
832 dest_addr
= (const struct sockaddr_in
*)addr
;
834 tcp_seq
= si
->io
.pck_snd
;
835 tcp_ack
= si
->io
.pck_rcv
;
836 tcp_ctl
= 0x12; /* SYN,ACK */
842 case SWRAP_ACCEPT_ACK
:
843 if (si
->type
!= SOCK_STREAM
) return;
845 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
846 src_addr
= (const struct sockaddr_in
*)addr
;
848 tcp_seq
= si
->io
.pck_rcv
;
849 tcp_ack
= si
->io
.pck_snd
;
850 tcp_ctl
= 0x10; /* ACK */
855 src_addr
= (const struct sockaddr_in
*)si
->myname
;
856 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
858 tcp_seq
= si
->io
.pck_snd
;
859 tcp_ack
= si
->io
.pck_rcv
;
860 tcp_ctl
= 0x18; /* PSH,ACK */
862 si
->io
.pck_snd
+= len
;
867 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
868 src_addr
= (const struct sockaddr_in
*)si
->peername
;
870 if (si
->type
== SOCK_DGRAM
) {
871 swrap_dump_packet(si
, si
->peername
,
872 SWRAP_SENDTO_UNREACH
,
877 tcp_seq
= si
->io
.pck_rcv
;
878 tcp_ack
= si
->io
.pck_snd
;
879 tcp_ctl
= 0x14; /** RST,ACK */
883 case SWRAP_PENDING_RST
:
884 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
885 src_addr
= (const struct sockaddr_in
*)si
->peername
;
887 if (si
->type
== SOCK_DGRAM
) {
891 tcp_seq
= si
->io
.pck_rcv
;
892 tcp_ack
= si
->io
.pck_snd
;
893 tcp_ctl
= 0x14; /* RST,ACK */
898 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
899 src_addr
= (const struct sockaddr_in
*)si
->peername
;
901 tcp_seq
= si
->io
.pck_rcv
;
902 tcp_ack
= si
->io
.pck_snd
;
903 tcp_ctl
= 0x18; /* PSH,ACK */
905 si
->io
.pck_rcv
+= len
;
910 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
911 src_addr
= (const struct sockaddr_in
*)si
->peername
;
913 if (si
->type
== SOCK_DGRAM
) {
917 tcp_seq
= si
->io
.pck_rcv
;
918 tcp_ack
= si
->io
.pck_snd
;
919 tcp_ctl
= 0x14; /* RST,ACK */
924 src_addr
= (const struct sockaddr_in
*)si
->myname
;
925 dest_addr
= (const struct sockaddr_in
*)addr
;
927 si
->io
.pck_snd
+= len
;
931 case SWRAP_SENDTO_UNREACH
:
932 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
933 src_addr
= (const struct sockaddr_in
*)addr
;
940 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
941 src_addr
= (const struct sockaddr_in
*)addr
;
943 si
->io
.pck_rcv
+= len
;
947 case SWRAP_CLOSE_SEND
:
948 if (si
->type
!= SOCK_STREAM
) return;
950 src_addr
= (const struct sockaddr_in
*)si
->myname
;
951 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
953 tcp_seq
= si
->io
.pck_snd
;
954 tcp_ack
= si
->io
.pck_rcv
;
955 tcp_ctl
= 0x11; /* FIN, ACK */
961 case SWRAP_CLOSE_RECV
:
962 if (si
->type
!= SOCK_STREAM
) return;
964 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
965 src_addr
= (const struct sockaddr_in
*)si
->peername
;
967 tcp_seq
= si
->io
.pck_rcv
;
968 tcp_ack
= si
->io
.pck_snd
;
969 tcp_ctl
= 0x11; /* FIN,ACK */
975 case SWRAP_CLOSE_ACK
:
976 if (si
->type
!= SOCK_STREAM
) return;
978 src_addr
= (const struct sockaddr_in
*)si
->myname
;
979 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
981 tcp_seq
= si
->io
.pck_snd
;
982 tcp_ack
= si
->io
.pck_rcv
;
983 tcp_ctl
= 0x10; /* ACK */
990 swrapGetTimeOfDay(&tv
);
992 packet
= swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
993 (const unsigned char *)buf
, len
,
994 tcp_seq
, tcp_ack
, tcp_ctl
, unreachable
,
1000 fd
= swrap_get_pcap_fd(file_name
);
1002 write(fd
, packet
, packet_len
);
1008 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1010 struct socket_info
*si
;
1013 if (!socket_wrapper_dir()) {
1014 return real_socket(family
, type
, protocol
);
1021 return real_socket(family
, type
, protocol
);
1023 errno
= EAFNOSUPPORT
;
1033 errno
= EPROTONOSUPPORT
;
1041 errno
= EPROTONOSUPPORT
;
1045 fd
= real_socket(AF_UNIX
, type
, 0);
1047 if (fd
== -1) return -1;
1049 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1051 si
->family
= family
;
1053 si
->protocol
= protocol
;
1056 DLIST_ADD(sockets
, si
);
1061 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1063 struct socket_info
*parent_si
, *child_si
;
1065 struct sockaddr_un un_addr
;
1066 socklen_t un_addrlen
= sizeof(un_addr
);
1067 struct sockaddr_un un_my_addr
;
1068 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1069 struct sockaddr my_addr
;
1070 socklen_t my_addrlen
= sizeof(my_addr
);
1073 parent_si
= find_socket_info(s
);
1075 return real_accept(s
, addr
, addrlen
);
1078 memset(&un_addr
, 0, sizeof(un_addr
));
1079 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1080 memset(&my_addr
, 0, sizeof(my_addr
));
1082 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1083 if (ret
== -1) return ret
;
1087 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1088 parent_si
->family
, addr
, addrlen
);
1094 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1095 memset(child_si
, 0, sizeof(*child_si
));
1098 child_si
->family
= parent_si
->family
;
1099 child_si
->type
= parent_si
->type
;
1100 child_si
->protocol
= parent_si
->protocol
;
1101 child_si
->bound
= 1;
1102 child_si
->is_server
= 1;
1104 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1111 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1112 child_si
->family
, &my_addr
, &my_addrlen
);
1119 child_si
->myname_len
= my_addrlen
;
1120 child_si
->myname
= sockaddr_dup(&my_addr
, my_addrlen
);
1122 child_si
->peername_len
= *addrlen
;
1123 child_si
->peername
= sockaddr_dup(addr
, *addrlen
);
1125 DLIST_ADD(sockets
, child_si
);
1127 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1128 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1129 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1134 static int autobind_start_init
;
1135 static int autobind_start
;
1137 /* using sendto() or connect() on an unbound socket would give the
1138 recipient no way to reply, as unlike UDP and TCP, a unix domain
1139 socket can't auto-assign emphemeral port numbers, so we need to
1141 static int swrap_auto_bind(struct socket_info
*si
)
1143 struct sockaddr_un un_addr
;
1144 struct sockaddr_in in
;
1151 if (autobind_start_init
!= 1) {
1152 autobind_start_init
= 1;
1153 autobind_start
= getpid();
1154 autobind_start
%= 50000;
1155 autobind_start
+= 10000;
1158 un_addr
.sun_family
= AF_UNIX
;
1162 type
= SOCKET_TYPE_CHAR_TCP
;
1165 type
= SOCKET_TYPE_CHAR_UDP
;
1168 errno
= ESOCKTNOSUPPORT
;
1172 if (autobind_start
> 60000) {
1173 autobind_start
= 10000;
1176 for (i
=0;i
<1000;i
++) {
1177 port
= autobind_start
+ i
;
1178 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1179 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1180 type
, socket_wrapper_default_iface(), port
);
1181 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1183 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1184 if (ret
== -1) return ret
;
1186 si
->tmp_path
= strdup(un_addr
.sun_path
);
1188 autobind_start
= port
+ 1;
1196 memset(&in
, 0, sizeof(in
));
1197 in
.sin_family
= AF_INET
;
1198 in
.sin_port
= htons(port
);
1199 in
.sin_addr
.s_addr
= htonl(127<<24 | socket_wrapper_default_iface());
1201 si
->myname_len
= sizeof(in
);
1202 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1207 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1210 struct sockaddr_un un_addr
;
1211 struct socket_info
*si
= find_socket_info(s
);
1214 return real_connect(s
, serv_addr
, addrlen
);
1217 if (si
->bound
== 0) {
1218 ret
= swrap_auto_bind(si
);
1219 if (ret
== -1) return -1;
1222 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1223 if (ret
== -1) return -1;
1225 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1227 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1228 sizeof(struct sockaddr_un
));
1230 /* to give better errors */
1231 if (ret
== -1 && errno
== ENOENT
) {
1232 errno
= EHOSTUNREACH
;
1236 si
->peername_len
= addrlen
;
1237 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1239 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1240 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1242 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1248 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1251 struct sockaddr_un un_addr
;
1252 struct socket_info
*si
= find_socket_info(s
);
1255 return real_bind(s
, myaddr
, addrlen
);
1258 si
->myname_len
= addrlen
;
1259 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1261 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1262 if (ret
== -1) return -1;
1264 unlink(un_addr
.sun_path
);
1266 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1267 sizeof(struct sockaddr_un
));
1276 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1279 struct socket_info
*si
= find_socket_info(s
);
1282 return real_listen(s
, backlog
);
1285 ret
= real_listen(s
, backlog
);
1290 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1292 struct socket_info
*si
= find_socket_info(s
);
1295 return real_getpeername(s
, name
, addrlen
);
1304 memcpy(name
, si
->peername
, si
->peername_len
);
1305 *addrlen
= si
->peername_len
;
1310 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1312 struct socket_info
*si
= find_socket_info(s
);
1315 return real_getsockname(s
, name
, addrlen
);
1318 memcpy(name
, si
->myname
, si
->myname_len
);
1319 *addrlen
= si
->myname_len
;
1324 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1326 struct socket_info
*si
= find_socket_info(s
);
1329 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1332 if (level
== SOL_SOCKET
) {
1333 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1336 errno
= ENOPROTOOPT
;
1340 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1342 struct socket_info
*si
= find_socket_info(s
);
1345 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1348 if (level
== SOL_SOCKET
) {
1349 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1352 switch (si
->family
) {
1356 errno
= ENOPROTOOPT
;
1361 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1363 struct sockaddr_un un_addr
;
1364 socklen_t un_addrlen
= sizeof(un_addr
);
1366 struct socket_info
*si
= find_socket_info(s
);
1369 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1372 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1373 memset(&un_addr
, 0, sizeof(un_addr
));
1374 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1378 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1379 si
->family
, from
, fromlen
) == -1) {
1383 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1389 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1391 struct sockaddr_un un_addr
;
1393 struct socket_info
*si
= find_socket_info(s
);
1397 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1400 if (si
->bound
== 0) {
1401 ret
= swrap_auto_bind(si
);
1402 if (ret
== -1) return -1;
1405 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1406 if (ret
== -1) return -1;
1411 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1414 type
= SOCKET_TYPE_CHAR_UDP
;
1416 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1417 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1418 socket_wrapper_dir(), type
, iface
, prt
);
1419 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1421 /* ignore the any errors in broadcast sends */
1422 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1425 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1430 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1432 /* to give better errors */
1433 if (ret
== -1 && errno
== ENOENT
) {
1434 errno
= EHOSTUNREACH
;
1438 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1439 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1441 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1447 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1450 struct socket_info
*si
= find_socket_info(s
);
1454 return real_ioctl(s
, r
, p
);
1457 ret
= real_ioctl(s
, r
, p
);
1461 value
= *((int *)p
);
1462 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1463 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1464 } else if (value
== 0) { /* END OF FILE */
1465 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1473 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1476 struct socket_info
*si
= find_socket_info(s
);
1479 return real_recv(s
, buf
, len
, flags
);
1482 ret
= real_recv(s
, buf
, len
, flags
);
1483 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1484 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1485 } else if (ret
== 0) { /* END OF FILE */
1486 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1488 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1495 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1498 struct socket_info
*si
= find_socket_info(s
);
1501 return real_send(s
, buf
, len
, flags
);
1504 ret
= real_send(s
, buf
, len
, flags
);
1507 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
1508 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
1510 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
1516 _PUBLIC_
int swrap_close(int fd
)
1518 struct socket_info
*si
= find_socket_info(fd
);
1522 return real_close(fd
);
1525 DLIST_REMOVE(sockets
, si
);
1527 if (si
->myname
&& si
->peername
) {
1528 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
1531 ret
= real_close(fd
);
1533 if (si
->myname
&& si
->peername
) {
1534 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
1535 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
1538 if (si
->path
) free(si
->path
);
1539 if (si
->myname
) free(si
->myname
);
1540 if (si
->peername
) free(si
->peername
);
1542 unlink(si
->tmp_path
);