1 /* $NetBSD: socket_wrapper.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
4 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
5 * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 Socket wrapper library. Passes all socket communication over
40 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
44 #define SOCKET_WRAPPER_NOT_REPLACE
49 #include "system/network.h"
50 #include "system/filesys.h"
62 #else /* _SAMBA_BUILD_ */
65 #undef SOCKET_WRAPPER_REPLACE
67 #include <sys/types.h>
68 #ifdef TIME_WITH_SYS_TIME
71 #elif defined(HAVE_SYS_TIME_H)
77 #include <sys/socket.h>
78 #include <sys/ioctl.h>
79 #ifdef HAVE_SYS_FILIO_H
80 #include <sys/filio.h>
84 #include <netinet/in.h>
85 #include <netinet/tcp.h>
91 #include <krb5/roken.h>
93 #include "socket_wrapper.h"
95 #define HAVE_GETTIMEOFDAY_TZ 1
101 #define SWRAP_DLIST_ADD(list,item) do { \
103 (item)->prev = NULL; \
104 (item)->next = NULL; \
107 (item)->prev = NULL; \
108 (item)->next = (list); \
109 (list)->prev = (item); \
114 #define SWRAP_DLIST_REMOVE(list,item) do { \
115 if ((list) == (item)) { \
116 (list) = (item)->next; \
118 (list)->prev = NULL; \
121 if ((item)->prev) { \
122 (item)->prev->next = (item)->next; \
124 if ((item)->next) { \
125 (item)->next->prev = (item)->prev; \
128 (item)->prev = NULL; \
129 (item)->next = NULL; \
132 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
134 #define REWRITE_CALLS
137 #define real_accept accept
138 #define real_connect connect
139 #define real_bind bind
140 #define real_listen listen
141 #define real_getpeername getpeername
142 #define real_getsockname getsockname
143 #define real_getsockopt getsockopt
144 #define real_setsockopt setsockopt
145 #define real_recvfrom recvfrom
146 #define real_sendto sendto
147 #define real_ioctl ioctl
148 #define real_recv recv
149 #define real_send send
150 #define real_socket socket
151 #define real_close close
153 #define real_dup2 dup2
156 #ifdef HAVE_GETTIMEOFDAY_TZ
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
159 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
162 /* we need to use a very terse format here as IRIX 6.4 silently
163 truncates names to 16 chars, so if we use a longer name then we
164 can't tell which port a packet came from with recvfrom()
166 with this format we have 8 chars left for the directory name
168 #define SOCKET_FORMAT "%c%02X%04X"
169 #define SOCKET_TYPE_CHAR_TCP 'T'
170 #define SOCKET_TYPE_CHAR_UDP 'U'
171 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
172 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
174 #define MAX_WRAPPED_INTERFACES 16
176 #define SW_IPV6_ADDRESS 1
178 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
180 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
181 memcpy(ret
, data
, len
);
185 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
189 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
193 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
199 static int socket_length(int family
)
203 return sizeof(struct sockaddr_in
);
206 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
;
245 static const char *socket_wrapper_dir(void)
247 const char *s
= getenv("SOCKET_WRAPPER_DIR");
251 if (strncmp(s
, "./", 2) == 0) {
257 static unsigned int socket_wrapper_default_iface(void)
259 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
262 if (sscanf(s
, "%u", &iface
) == 1) {
263 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
269 return 1;/* 127.0.0.1 */
272 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
279 p
= strrchr(un
->sun_path
, '/');
280 if (p
) p
++; else p
= un
->sun_path
;
282 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
287 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
298 case SOCKET_TYPE_CHAR_TCP
:
299 case SOCKET_TYPE_CHAR_UDP
: {
300 struct sockaddr_in
*in2
= (struct sockaddr_in
*)in
;
302 if ((*len
) < sizeof(*in2
)) {
307 memset(in2
, 0, sizeof(*in2
));
308 in2
->sin_family
= AF_INET
;
309 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
310 in2
->sin_port
= htons(prt
);
316 case SOCKET_TYPE_CHAR_TCP_V6
:
317 case SOCKET_TYPE_CHAR_UDP_V6
: {
318 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)in
;
320 if ((*len
) < sizeof(*in2
)) {
325 memset(in2
, 0, sizeof(*in2
));
326 in2
->sin6_family
= AF_INET6
;
327 in2
->sin6_addr
.s6_addr
[0] = SW_IPV6_ADDRESS
;
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 (si
->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
;
402 type
= SOCKET_TYPE_CHAR_TCP_V6
;
405 type
= SOCKET_TYPE_CHAR_UDP_V6
;
409 /* XXX no multicast/broadcast */
411 prt
= ntohs(in
->sin6_port
);
412 iface
= SW_IPV6_ADDRESS
;
428 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
429 socket_wrapper_dir());
430 /* the caller need to do more processing */
434 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
435 socket_wrapper_dir(), type
, iface
, prt
);
440 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
449 if (bcast
) *bcast
= 0;
451 switch (si
->family
) {
453 const struct sockaddr_in
*in
=
454 (const struct sockaddr_in
*)inaddr
;
455 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
461 prt
= ntohs(in
->sin_port
);
465 u_type
= SOCKET_TYPE_CHAR_TCP
;
466 d_type
= SOCKET_TYPE_CHAR_TCP
;
469 u_type
= SOCKET_TYPE_CHAR_UDP
;
470 d_type
= SOCKET_TYPE_CHAR_UDP
;
471 a_type
= SOCKET_TYPE_CHAR_UDP
;
472 b_type
= SOCKET_TYPE_CHAR_UDP
;
480 iface
= socket_wrapper_default_iface();
481 } else if (a_type
&& addr
== 0xFFFFFFFF) {
482 /* 255.255.255.255 only udp */
485 iface
= socket_wrapper_default_iface();
486 } else if (b_type
&& addr
== 0x7FFFFFFF) {
487 /* 127.255.255.255 only udp */
490 iface
= socket_wrapper_default_iface();
491 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
495 iface
= (addr
& 0x000000FF);
497 errno
= EADDRNOTAVAIL
;
504 const struct sockaddr_in6
*in
=
505 (const struct sockaddr_in6
*)inaddr
;
509 type
= SOCKET_TYPE_CHAR_TCP_V6
;
512 type
= SOCKET_TYPE_CHAR_UDP_V6
;
516 /* XXX no multicast/broadcast */
518 prt
= ntohs(in
->sin6_port
);
519 iface
= SW_IPV6_ADDRESS
;
530 if (bcast
) *bcast
= is_bcast
;
533 /* handle auto-allocation of ephemeral ports */
534 for (prt
= 5001; prt
< 10000; prt
++) {
535 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
536 socket_wrapper_dir(), type
, iface
, prt
);
537 if (stat(un
->sun_path
, &st
) == 0) continue;
539 set_port(si
->family
, prt
, si
->myname
);
543 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
544 socket_wrapper_dir(), type
, iface
, prt
);
548 static struct socket_info
*find_socket_info(int fd
)
550 struct socket_info
*i
;
551 for (i
= sockets
; i
; i
= i
->next
) {
559 static int sockaddr_convert_to_un(struct socket_info
*si
, const struct sockaddr
*in_addr
, socklen_t in_len
,
560 struct sockaddr_un
*out_addr
, int alloc_sock
, int *bcast
)
565 out_addr
->sun_family
= AF_UNIX
;
567 switch (in_addr
->sa_family
) {
577 errno
= ESOCKTNOSUPPORT
;
581 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
583 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
589 errno
= EAFNOSUPPORT
;
593 static int sockaddr_convert_from_un(const struct socket_info
*si
,
594 const struct sockaddr_un
*in_addr
,
595 socklen_t un_addrlen
,
597 struct sockaddr
*out_addr
,
598 socklen_t
*out_addrlen
)
600 if (out_addr
== NULL
|| out_addrlen
== NULL
)
603 if (un_addrlen
== 0) {
618 errno
= ESOCKTNOSUPPORT
;
621 return convert_un_in(in_addr
, out_addr
, out_addrlen
);
626 errno
= EAFNOSUPPORT
;
630 enum swrap_packet_type
{
632 SWRAP_CONNECT_UNREACH
,
640 SWRAP_SENDTO_UNREACH
,
651 struct swrap_file_hdr
{
653 unsigned short version_major
;
654 unsigned short version_minor
;
656 unsigned long sigfigs
;
657 unsigned long frame_max_len
;
658 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
659 unsigned long link_type
;
661 #define SWRAP_FILE_HDR_SIZE 24
663 struct swrap_packet
{
665 unsigned long seconds
;
666 unsigned long micro_seconds
;
667 unsigned long recorded_length
;
668 unsigned long full_length
;
670 #define SWRAP_PACKET__FRAME_SIZE 16
674 unsigned char ver_hdrlen
;
676 unsigned short packet_length
;
677 unsigned short identification
;
679 unsigned char fragment
;
681 unsigned char protocol
;
682 unsigned short hdr_checksum
;
683 unsigned long src_addr
;
684 unsigned long dest_addr
;
686 #define SWRAP_PACKET__IP_HDR_SIZE 20
690 unsigned short source_port
;
691 unsigned short dest_port
;
692 unsigned long seq_num
;
693 unsigned long ack_num
;
694 unsigned char hdr_length
;
695 unsigned char control
;
696 unsigned short window
;
697 unsigned short checksum
;
700 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
702 unsigned short source_port
;
703 unsigned short dest_port
;
704 unsigned short length
;
705 unsigned short checksum
;
707 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
711 unsigned short checksum
;
712 unsigned long unused
;
714 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
718 #define SWRAP_PACKET_SIZE 56
720 static const char *socket_wrapper_pcap_file(void)
722 static int initialized
= 0;
723 static const char *s
= NULL
;
724 static const struct swrap_file_hdr h
;
725 static const struct swrap_packet p
;
727 if (initialized
== 1) {
733 * TODO: don't use the structs use plain buffer offsets
734 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
736 * for now make sure we disable PCAP support
737 * if the struct has alignment!
739 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
742 if (sizeof(p
) != SWRAP_PACKET_SIZE
) {
745 if (sizeof(p
.frame
) != SWRAP_PACKET__FRAME_SIZE
) {
748 if (sizeof(p
.ip
.hdr
) != SWRAP_PACKET__IP_HDR_SIZE
) {
751 if (sizeof(p
.ip
.p
.tcp
) != SWRAP_PACKET__IP_P_TCP_SIZE
) {
754 if (sizeof(p
.ip
.p
.udp
) != SWRAP_PACKET__IP_P_UDP_SIZE
) {
757 if (sizeof(p
.ip
.p
.icmp
) != SWRAP_PACKET__IP_P_ICMP_SIZE
) {
761 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
765 if (strncmp(s
, "./", 2) == 0) {
771 static struct swrap_packet
*swrap_packet_init(struct timeval
*tval
,
772 const struct sockaddr_in
*src_addr
,
773 const struct sockaddr_in
*dest_addr
,
775 const unsigned char *payload
,
777 unsigned long tcp_seq
,
778 unsigned long tcp_ack
,
779 unsigned char tcp_ctl
,
783 struct swrap_packet
*ret
;
784 struct swrap_packet
*packet
;
787 size_t nonwire_len
= sizeof(packet
->frame
);
788 size_t wire_hdr_len
= 0;
790 size_t icmp_hdr_len
= 0;
791 size_t icmp_truncate_len
= 0;
792 unsigned char protocol
= 0, icmp_protocol
= 0;
793 unsigned short src_port
= src_addr
->sin_port
;
794 unsigned short dest_port
= dest_addr
->sin_port
;
796 switch (socket_type
) {
798 protocol
= 0x06; /* TCP */
799 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.tcp
);
800 wire_len
= wire_hdr_len
+ payload_len
;
804 protocol
= 0x11; /* UDP */
805 wire_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.udp
);
806 wire_len
= wire_hdr_len
+ payload_len
;
811 icmp_protocol
= protocol
;
812 protocol
= 0x01; /* ICMP */
813 if (wire_len
> 64 ) {
814 icmp_truncate_len
= wire_len
- 64;
816 icmp_hdr_len
= sizeof(packet
->ip
.hdr
) + sizeof(packet
->ip
.p
.icmp
);
817 wire_hdr_len
+= icmp_hdr_len
;
818 wire_len
+= icmp_hdr_len
;
821 packet_len
= nonwire_len
+ wire_len
;
822 alloc_len
= packet_len
;
823 if (alloc_len
< sizeof(struct swrap_packet
)) {
824 alloc_len
= sizeof(struct swrap_packet
);
826 ret
= (struct swrap_packet
*)malloc(alloc_len
);
827 if (!ret
) return NULL
;
831 packet
->frame
.seconds
= tval
->tv_sec
;
832 packet
->frame
.micro_seconds
= tval
->tv_usec
;
833 packet
->frame
.recorded_length
= wire_len
- icmp_truncate_len
;
834 packet
->frame
.full_length
= wire_len
- icmp_truncate_len
;
836 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
837 packet
->ip
.hdr
.tos
= 0x00;
838 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_truncate_len
);
839 packet
->ip
.hdr
.identification
= htons(0xFFFF);
840 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
841 packet
->ip
.hdr
.fragment
= htons(0x0000);
842 packet
->ip
.hdr
.ttl
= 0xFF;
843 packet
->ip
.hdr
.protocol
= protocol
;
844 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
845 packet
->ip
.hdr
.src_addr
= src_addr
->sin_addr
.s_addr
;
846 packet
->ip
.hdr
.dest_addr
= dest_addr
->sin_addr
.s_addr
;
849 packet
->ip
.p
.icmp
.type
= 0x03; /* destination unreachable */
850 packet
->ip
.p
.icmp
.code
= 0x01; /* host unreachable */
851 packet
->ip
.p
.icmp
.checksum
= htons(0x0000);
852 packet
->ip
.p
.icmp
.unused
= htonl(0x00000000);
854 /* set the ip header in the ICMP payload */
855 packet
= (struct swrap_packet
*)(((unsigned char *)ret
) + icmp_hdr_len
);
856 packet
->ip
.hdr
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
857 packet
->ip
.hdr
.tos
= 0x00;
858 packet
->ip
.hdr
.packet_length
= htons(wire_len
- icmp_hdr_len
);
859 packet
->ip
.hdr
.identification
= htons(0xFFFF);
860 packet
->ip
.hdr
.flags
= 0x40; /* BIT 1 set - means don't fraqment */
861 packet
->ip
.hdr
.fragment
= htons(0x0000);
862 packet
->ip
.hdr
.ttl
= 0xFF;
863 packet
->ip
.hdr
.protocol
= icmp_protocol
;
864 packet
->ip
.hdr
.hdr_checksum
= htons(0x0000);
865 packet
->ip
.hdr
.src_addr
= dest_addr
->sin_addr
.s_addr
;
866 packet
->ip
.hdr
.dest_addr
= src_addr
->sin_addr
.s_addr
;
868 src_port
= dest_addr
->sin_port
;
869 dest_port
= src_addr
->sin_port
;
872 switch (socket_type
) {
874 packet
->ip
.p
.tcp
.source_port
= src_port
;
875 packet
->ip
.p
.tcp
.dest_port
= dest_port
;
876 packet
->ip
.p
.tcp
.seq_num
= htonl(tcp_seq
);
877 packet
->ip
.p
.tcp
.ack_num
= htonl(tcp_ack
);
878 packet
->ip
.p
.tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
879 packet
->ip
.p
.tcp
.control
= tcp_ctl
;
880 packet
->ip
.p
.tcp
.window
= htons(0x7FFF);
881 packet
->ip
.p
.tcp
.checksum
= htons(0x0000);
882 packet
->ip
.p
.tcp
.urg
= htons(0x0000);
887 packet
->ip
.p
.udp
.source_port
= src_addr
->sin_port
;
888 packet
->ip
.p
.udp
.dest_port
= dest_addr
->sin_port
;
889 packet
->ip
.p
.udp
.length
= htons(8 + payload_len
);
890 packet
->ip
.p
.udp
.checksum
= htons(0x0000);
895 if (payload
&& payload_len
> 0) {
896 unsigned char *p
= (unsigned char *)ret
;
899 memcpy(p
, payload
, payload_len
);
902 *_packet_len
= packet_len
- icmp_truncate_len
;
906 static int swrap_get_pcap_fd(const char *fname
)
910 if (fd
!= -1) return fd
;
912 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
914 struct swrap_file_hdr file_hdr
;
915 file_hdr
.magic
= 0xA1B2C3D4;
916 file_hdr
.version_major
= 0x0002;
917 file_hdr
.version_minor
= 0x0004;
918 file_hdr
.timezone
= 0x00000000;
919 file_hdr
.sigfigs
= 0x00000000;
920 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
921 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
923 write(fd
, &file_hdr
, sizeof(file_hdr
));
927 fd
= open(fname
, O_WRONLY
|O_APPEND
, 0644);
932 static void swrap_dump_packet(struct socket_info
*si
, const struct sockaddr
*addr
,
933 enum swrap_packet_type type
,
934 const void *buf
, size_t len
)
936 const struct sockaddr_in
*src_addr
;
937 const struct sockaddr_in
*dest_addr
;
938 const char *file_name
;
939 unsigned long tcp_seq
= 0;
940 unsigned long tcp_ack
= 0;
941 unsigned char tcp_ctl
= 0;
944 struct swrap_packet
*packet
;
945 size_t packet_len
= 0;
948 file_name
= socket_wrapper_pcap_file();
953 switch (si
->family
) {
964 case SWRAP_CONNECT_SEND
:
965 if (si
->type
!= SOCK_STREAM
) return;
967 src_addr
= (const struct sockaddr_in
*)si
->myname
;
968 dest_addr
= (const struct sockaddr_in
*)addr
;
970 tcp_seq
= si
->io
.pck_snd
;
971 tcp_ack
= si
->io
.pck_rcv
;
972 tcp_ctl
= 0x02; /* SYN */
978 case SWRAP_CONNECT_RECV
:
979 if (si
->type
!= SOCK_STREAM
) return;
981 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
982 src_addr
= (const struct sockaddr_in
*)addr
;
984 tcp_seq
= si
->io
.pck_rcv
;
985 tcp_ack
= si
->io
.pck_snd
;
986 tcp_ctl
= 0x12; /** SYN,ACK */
992 case SWRAP_CONNECT_UNREACH
:
993 if (si
->type
!= SOCK_STREAM
) return;
995 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
996 src_addr
= (const struct sockaddr_in
*)addr
;
998 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
999 tcp_seq
= si
->io
.pck_snd
- 1;
1000 tcp_ack
= si
->io
.pck_rcv
;
1001 tcp_ctl
= 0x02; /* SYN */
1006 case SWRAP_CONNECT_ACK
:
1007 if (si
->type
!= SOCK_STREAM
) return;
1009 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1010 dest_addr
= (const struct sockaddr_in
*)addr
;
1012 tcp_seq
= si
->io
.pck_snd
;
1013 tcp_ack
= si
->io
.pck_rcv
;
1014 tcp_ctl
= 0x10; /* ACK */
1018 case SWRAP_ACCEPT_SEND
:
1019 if (si
->type
!= SOCK_STREAM
) return;
1021 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1022 src_addr
= (const struct sockaddr_in
*)addr
;
1024 tcp_seq
= si
->io
.pck_rcv
;
1025 tcp_ack
= si
->io
.pck_snd
;
1026 tcp_ctl
= 0x02; /* SYN */
1028 si
->io
.pck_rcv
+= 1;
1032 case SWRAP_ACCEPT_RECV
:
1033 if (si
->type
!= SOCK_STREAM
) return;
1035 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1036 dest_addr
= (const struct sockaddr_in
*)addr
;
1038 tcp_seq
= si
->io
.pck_snd
;
1039 tcp_ack
= si
->io
.pck_rcv
;
1040 tcp_ctl
= 0x12; /* SYN,ACK */
1042 si
->io
.pck_snd
+= 1;
1046 case SWRAP_ACCEPT_ACK
:
1047 if (si
->type
!= SOCK_STREAM
) return;
1049 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1050 src_addr
= (const struct sockaddr_in
*)addr
;
1052 tcp_seq
= si
->io
.pck_rcv
;
1053 tcp_ack
= si
->io
.pck_snd
;
1054 tcp_ctl
= 0x10; /* ACK */
1059 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1060 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
1062 tcp_seq
= si
->io
.pck_snd
;
1063 tcp_ack
= si
->io
.pck_rcv
;
1064 tcp_ctl
= 0x18; /* PSH,ACK */
1066 si
->io
.pck_snd
+= len
;
1070 case SWRAP_SEND_RST
:
1071 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1072 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1074 if (si
->type
== SOCK_DGRAM
) {
1075 swrap_dump_packet(si
, si
->peername
,
1076 SWRAP_SENDTO_UNREACH
,
1081 tcp_seq
= si
->io
.pck_rcv
;
1082 tcp_ack
= si
->io
.pck_snd
;
1083 tcp_ctl
= 0x14; /** RST,ACK */
1087 case SWRAP_PENDING_RST
:
1088 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1089 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1091 if (si
->type
== SOCK_DGRAM
) {
1095 tcp_seq
= si
->io
.pck_rcv
;
1096 tcp_ack
= si
->io
.pck_snd
;
1097 tcp_ctl
= 0x14; /* RST,ACK */
1102 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1103 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1105 tcp_seq
= si
->io
.pck_rcv
;
1106 tcp_ack
= si
->io
.pck_snd
;
1107 tcp_ctl
= 0x18; /* PSH,ACK */
1109 si
->io
.pck_rcv
+= len
;
1113 case SWRAP_RECV_RST
:
1114 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1115 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1117 if (si
->type
== SOCK_DGRAM
) {
1121 tcp_seq
= si
->io
.pck_rcv
;
1122 tcp_ack
= si
->io
.pck_snd
;
1123 tcp_ctl
= 0x14; /* RST,ACK */
1128 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1129 dest_addr
= (const struct sockaddr_in
*)addr
;
1131 si
->io
.pck_snd
+= len
;
1135 case SWRAP_SENDTO_UNREACH
:
1136 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1137 src_addr
= (const struct sockaddr_in
*)addr
;
1143 case SWRAP_RECVFROM
:
1144 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1145 src_addr
= (const struct sockaddr_in
*)addr
;
1147 si
->io
.pck_rcv
+= len
;
1151 case SWRAP_CLOSE_SEND
:
1152 if (si
->type
!= SOCK_STREAM
) return;
1154 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1155 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
1157 tcp_seq
= si
->io
.pck_snd
;
1158 tcp_ack
= si
->io
.pck_rcv
;
1159 tcp_ctl
= 0x11; /* FIN, ACK */
1161 si
->io
.pck_snd
+= 1;
1165 case SWRAP_CLOSE_RECV
:
1166 if (si
->type
!= SOCK_STREAM
) return;
1168 dest_addr
= (const struct sockaddr_in
*)si
->myname
;
1169 src_addr
= (const struct sockaddr_in
*)si
->peername
;
1171 tcp_seq
= si
->io
.pck_rcv
;
1172 tcp_ack
= si
->io
.pck_snd
;
1173 tcp_ctl
= 0x11; /* FIN,ACK */
1175 si
->io
.pck_rcv
+= 1;
1179 case SWRAP_CLOSE_ACK
:
1180 if (si
->type
!= SOCK_STREAM
) return;
1182 src_addr
= (const struct sockaddr_in
*)si
->myname
;
1183 dest_addr
= (const struct sockaddr_in
*)si
->peername
;
1185 tcp_seq
= si
->io
.pck_snd
;
1186 tcp_ack
= si
->io
.pck_rcv
;
1187 tcp_ctl
= 0x10; /* ACK */
1194 swrapGetTimeOfDay(&tv
);
1196 packet
= swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
1197 (const unsigned char *)buf
, len
,
1198 tcp_seq
, tcp_ack
, tcp_ctl
, unreachable
,
1204 fd
= swrap_get_pcap_fd(file_name
);
1206 write(fd
, packet
, packet_len
);
1212 _PUBLIC_
int swrap_socket(int family
, int type
, int protocol
)
1214 struct socket_info
*si
;
1217 if (!socket_wrapper_dir()) {
1218 return real_socket(family
, type
, protocol
);
1228 return real_socket(family
, type
, protocol
);
1230 errno
= EAFNOSUPPORT
;
1240 errno
= EPROTONOSUPPORT
;
1249 errno
= EPROTONOSUPPORT
;
1254 fd
= real_socket(AF_UNIX
, type
, 0);
1256 if (fd
== -1) return -1;
1258 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1260 si
->family
= family
;
1262 si
->protocol
= protocol
;
1265 SWRAP_DLIST_ADD(sockets
, si
);
1270 _PUBLIC_
int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
1272 struct socket_info
*parent_si
, *child_si
;
1274 struct sockaddr_un un_addr
;
1275 socklen_t un_addrlen
= sizeof(un_addr
);
1276 struct sockaddr_un un_my_addr
;
1277 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
1278 struct sockaddr
*my_addr
;
1279 socklen_t my_addrlen
, len
;
1282 parent_si
= find_socket_info(s
);
1284 return real_accept(s
, addr
, addrlen
);
1288 * assume out sockaddr have the same size as the in parent
1291 my_addrlen
= socket_length(parent_si
->family
);
1292 if (my_addrlen
< 0) {
1297 my_addr
= malloc(my_addrlen
);
1298 if (my_addr
== NULL
) {
1302 memset(&un_addr
, 0, sizeof(un_addr
));
1303 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
1305 ret
= real_accept(s
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1314 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
1315 parent_si
->family
, my_addr
, &len
);
1322 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
1323 memset(child_si
, 0, sizeof(*child_si
));
1326 child_si
->family
= parent_si
->family
;
1327 child_si
->type
= parent_si
->type
;
1328 child_si
->protocol
= parent_si
->protocol
;
1329 child_si
->bound
= 1;
1330 child_si
->is_server
= 1;
1332 child_si
->peername_len
= len
;
1333 child_si
->peername
= sockaddr_dup(my_addr
, len
);
1335 if (addr
!= NULL
&& addrlen
!= NULL
) {
1337 if (*addrlen
>= len
)
1338 memcpy(addr
, my_addr
, len
);
1342 ret
= real_getsockname(fd
, (struct sockaddr
*)&un_my_addr
, &un_my_addrlen
);
1350 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
1351 child_si
->family
, my_addr
, &len
);
1359 child_si
->myname_len
= len
;
1360 child_si
->myname
= sockaddr_dup(my_addr
, len
);
1363 SWRAP_DLIST_ADD(sockets
, child_si
);
1365 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
1366 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
1367 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
1372 static int autobind_start_init
;
1373 static int autobind_start
;
1375 /* using sendto() or connect() on an unbound socket would give the
1376 recipient no way to reply, as unlike UDP and TCP, a unix domain
1377 socket can't auto-assign emphemeral port numbers, so we need to
1379 static int swrap_auto_bind(struct socket_info
*si
)
1381 struct sockaddr_un un_addr
;
1388 if (autobind_start_init
!= 1) {
1389 autobind_start_init
= 1;
1390 autobind_start
= getpid();
1391 autobind_start
%= 50000;
1392 autobind_start
+= 10000;
1395 un_addr
.sun_family
= AF_UNIX
;
1397 switch (si
->family
) {
1399 struct sockaddr_in in
;
1403 type
= SOCKET_TYPE_CHAR_TCP
;
1406 type
= SOCKET_TYPE_CHAR_UDP
;
1409 errno
= ESOCKTNOSUPPORT
;
1413 memset(&in
, 0, sizeof(in
));
1414 in
.sin_family
= AF_INET
;
1415 in
.sin_addr
.s_addr
= htonl(127<<24 |
1416 socket_wrapper_default_iface());
1418 si
->myname_len
= sizeof(in
);
1419 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
1424 struct sockaddr_in6 in6
;
1428 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1431 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1434 errno
= ESOCKTNOSUPPORT
;
1438 memset(&in6
, 0, sizeof(in6
));
1439 in6
.sin6_family
= AF_INET6
;
1440 in6
.sin6_addr
.s6_addr
[0] = SW_IPV6_ADDRESS
;
1441 si
->myname_len
= sizeof(in6
);
1442 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
1447 errno
= ESOCKTNOSUPPORT
;
1451 if (autobind_start
> 60000) {
1452 autobind_start
= 10000;
1455 for (i
=0;i
<1000;i
++) {
1456 port
= autobind_start
+ i
;
1457 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
1458 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
1459 type
, socket_wrapper_default_iface(), port
);
1460 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
1462 ret
= real_bind(si
->fd
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1463 if (ret
== -1) return ret
;
1465 si
->tmp_path
= strdup(un_addr
.sun_path
);
1467 autobind_start
= port
+ 1;
1475 set_port(si
->family
, port
, si
->myname
);
1481 _PUBLIC_
int swrap_connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
1484 struct sockaddr_un un_addr
;
1485 struct socket_info
*si
= find_socket_info(s
);
1488 return real_connect(s
, serv_addr
, addrlen
);
1491 if (si
->bound
== 0) {
1492 ret
= swrap_auto_bind(si
);
1493 if (ret
== -1) return -1;
1496 if (si
->family
!= serv_addr
->sa_family
) {
1501 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)serv_addr
, addrlen
, &un_addr
, 0, NULL
);
1502 if (ret
== -1) return -1;
1504 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
1506 ret
= real_connect(s
, (struct sockaddr
*)&un_addr
,
1507 sizeof(struct sockaddr_un
));
1509 /* to give better errors */
1510 if (ret
== -1 && errno
== ENOENT
) {
1511 errno
= EHOSTUNREACH
;
1515 si
->peername_len
= addrlen
;
1516 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
1518 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
1519 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
1521 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
1527 _PUBLIC_
int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
1530 struct sockaddr_un un_addr
;
1531 struct socket_info
*si
= find_socket_info(s
);
1534 return real_bind(s
, myaddr
, addrlen
);
1537 si
->myname_len
= addrlen
;
1538 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
1540 ret
= sockaddr_convert_to_un(si
, (const struct sockaddr
*)myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
1541 if (ret
== -1) return -1;
1543 unlink(un_addr
.sun_path
);
1545 ret
= real_bind(s
, (struct sockaddr
*)&un_addr
,
1546 sizeof(struct sockaddr_un
));
1555 _PUBLIC_
int swrap_listen(int s
, int backlog
)
1558 struct socket_info
*si
= find_socket_info(s
);
1561 return real_listen(s
, backlog
);
1564 ret
= real_listen(s
, backlog
);
1569 _PUBLIC_
int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1571 struct socket_info
*si
= find_socket_info(s
);
1574 return real_getpeername(s
, name
, addrlen
);
1583 memcpy(name
, si
->peername
, si
->peername_len
);
1584 *addrlen
= si
->peername_len
;
1589 _PUBLIC_
int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
1591 struct socket_info
*si
= find_socket_info(s
);
1594 return real_getsockname(s
, name
, addrlen
);
1597 memcpy(name
, si
->myname
, si
->myname_len
);
1598 *addrlen
= si
->myname_len
;
1603 _PUBLIC_
int swrap_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1605 struct socket_info
*si
= find_socket_info(s
);
1608 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1611 if (level
== SOL_SOCKET
) {
1612 return real_getsockopt(s
, level
, optname
, optval
, optlen
);
1615 errno
= ENOPROTOOPT
;
1619 _PUBLIC_
int swrap_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1621 struct socket_info
*si
= find_socket_info(s
);
1624 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1627 if (level
== SOL_SOCKET
) {
1628 return real_setsockopt(s
, level
, optname
, optval
, optlen
);
1631 switch (si
->family
) {
1635 errno
= ENOPROTOOPT
;
1640 _PUBLIC_ ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
1642 struct sockaddr_un un_addr
;
1643 socklen_t un_addrlen
= sizeof(un_addr
);
1645 struct socket_info
*si
= find_socket_info(s
);
1648 return real_recvfrom(s
, buf
, len
, flags
, from
, fromlen
);
1651 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1652 memset(&un_addr
, 0, sizeof(un_addr
));
1653 ret
= real_recvfrom(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, &un_addrlen
);
1657 if (sockaddr_convert_from_un(si
, &un_addr
, un_addrlen
,
1658 si
->family
, from
, fromlen
) == -1) {
1662 swrap_dump_packet(si
, from
, SWRAP_RECVFROM
, buf
, ret
);
1668 _PUBLIC_ ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
, const struct sockaddr
*to
, socklen_t tolen
)
1670 struct sockaddr_un un_addr
;
1672 struct socket_info
*si
= find_socket_info(s
);
1676 return real_sendto(s
, buf
, len
, flags
, to
, tolen
);
1681 ret
= real_send(s
, buf
, len
, flags
);
1684 if (si
->bound
== 0) {
1685 ret
= swrap_auto_bind(si
);
1686 if (ret
== -1) return -1;
1689 ret
= sockaddr_convert_to_un(si
, to
, tolen
, &un_addr
, 0, &bcast
);
1690 if (ret
== -1) return -1;
1695 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
1698 type
= SOCKET_TYPE_CHAR_UDP
;
1700 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
1701 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
1702 socket_wrapper_dir(), type
, iface
, prt
);
1703 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
1705 /* ignore the any errors in broadcast sends */
1706 real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1709 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1714 ret
= real_sendto(s
, buf
, len
, flags
, (struct sockaddr
*)&un_addr
, sizeof(un_addr
));
1718 errno
= EHOSTUNREACH
;
1722 /* to give better errors */
1723 if (ret
== -1 && errno
== ENOENT
) {
1724 errno
= EHOSTUNREACH
;
1728 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
1729 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
1731 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, ret
);
1737 _PUBLIC_
int swrap_ioctl(int s
, int r
, void *p
)
1740 struct socket_info
*si
= find_socket_info(s
);
1744 return real_ioctl(s
, r
, p
);
1747 ret
= real_ioctl(s
, r
, p
);
1751 value
= *((int *)p
);
1752 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1753 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1754 } else if (value
== 0) { /* END OF FILE */
1755 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
1763 _PUBLIC_ ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
1766 struct socket_info
*si
= find_socket_info(s
);
1769 return real_recv(s
, buf
, len
, flags
);
1772 ret
= real_recv(s
, buf
, len
, flags
);
1773 if (ret
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
1774 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1775 } else if (ret
== 0) { /* END OF FILE */
1776 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
1778 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
1785 _PUBLIC_ ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
1788 struct socket_info
*si
= find_socket_info(s
);
1791 return real_send(s
, buf
, len
, flags
);
1794 ret
= real_send(s
, buf
, len
, flags
);
1797 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
1798 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
1800 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, ret
);
1806 _PUBLIC_
int swrap_close(int fd
)
1808 struct socket_info
*si
= find_socket_info(fd
);
1812 return real_close(fd
);
1815 SWRAP_DLIST_REMOVE(sockets
, si
);
1817 if (si
->myname
&& si
->peername
) {
1818 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
1821 ret
= real_close(fd
);
1823 if (si
->myname
&& si
->peername
) {
1824 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
1825 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
1828 if (si
->path
) free(si
->path
);
1829 if (si
->myname
) free(si
->myname
);
1830 if (si
->peername
) free(si
->peername
);
1832 unlink(si
->tmp_path
);
1841 dup_internal(const struct socket_info
*si_oldd
, int fd
)
1843 struct socket_info
*si_newd
;
1845 si_newd
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
1849 si_newd
->family
= si_oldd
->family
;
1850 si_newd
->type
= si_oldd
->type
;
1851 si_newd
->protocol
= si_oldd
->protocol
;
1852 si_newd
->bound
= si_oldd
->bound
;
1853 si_newd
->bcast
= si_oldd
->bcast
;
1855 si_newd
->path
= strdup(si_oldd
->path
);
1856 if (si_oldd
->tmp_path
)
1857 si_newd
->tmp_path
= strdup(si_oldd
->tmp_path
);
1859 sockaddr_dup(si_oldd
->myname
, si_oldd
->myname_len
);
1860 si_newd
->myname_len
= si_oldd
->myname_len
;
1862 sockaddr_dup(si_oldd
->peername
, si_oldd
->peername_len
);
1863 si_newd
->peername_len
= si_oldd
->peername_len
;
1865 si_newd
->io
= si_oldd
->io
;
1867 SWRAP_DLIST_ADD(sockets
, si_newd
);
1873 _PUBLIC_
int swrap_dup(int oldd
)
1875 struct socket_info
*si
;
1878 si
= find_socket_info(oldd
);
1880 return real_dup(oldd
);
1882 fd
= real_dup(si
->fd
);
1886 return dup_internal(si
, fd
);
1890 _PUBLIC_
int swrap_dup2(int oldd
, int newd
)
1892 struct socket_info
*si_newd
, *si_oldd
;
1898 si_oldd
= find_socket_info(oldd
);
1899 si_newd
= find_socket_info(newd
);
1901 if (si_oldd
== NULL
&& si_newd
== NULL
)
1902 return real_dup2(oldd
, newd
);
1904 fd
= real_dup2(si_oldd
->fd
, newd
);
1908 /* close new socket first */
1912 return dup_internal(si_oldd
, fd
);