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>
63 #include <sys/socket.h>
64 #include <sys/ioctl.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
79 #define SWRAP_DLIST_ADD(list,item) do { \
81 (item)->prev = NULL; \
82 (item)->next = NULL; \
85 (item)->prev = NULL; \
86 (item)->next = (list); \
87 (list)->prev = (item); \
92 #define SWRAP_DLIST_REMOVE(list,item) do { \
93 if ((list) == (item)) { \
94 (list) = (item)->next; \
96 (list)->prev = NULL; \
100 (item)->prev->next = (item)->next; \
102 if ((item)->next) { \
103 (item)->next->prev = (item)->prev; \
106 (item)->prev = NULL; \
107 (item)->next = NULL; \
110 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
112 #define REWRITE_CALLS
115 #define real_accept accept
116 #define real_connect connect
117 #define real_bind bind
118 #define real_listen listen
119 #define real_getpeername getpeername
120 #define real_getsockname getsockname
121 #define real_getsockopt getsockopt
122 #define real_setsockopt setsockopt
123 #define real_recvfrom recvfrom
124 #define real_sendto sendto
125 #define real_ioctl ioctl
126 #define real_recv recv
127 #define real_send send
128 #define real_socket socket
129 #define real_close close
132 #ifdef HAVE_GETTIMEOFDAY_TZ
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 /* we need to use a very terse format here as IRIX 6.4 silently
139 truncates names to 16 chars, so if we use a longer name then we
140 can't tell which port a packet came from with recvfrom()
142 with this format we have 8 chars left for the directory name
144 #define SOCKET_FORMAT "%c%02X%04X"
145 #define SOCKET_TYPE_CHAR_TCP 'T'
146 #define SOCKET_TYPE_CHAR_UDP 'U'
148 #define MAX_WRAPPED_INTERFACES 16
150 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
152 struct sockaddr *ret = (struct sockaddr *)malloc(len);
153 memcpy(ret, data, len);
171 struct sockaddr *myname;
172 socklen_t myname_len;
174 struct sockaddr *peername;
175 socklen_t peername_len;
178 unsigned long pck_snd;
179 unsigned long pck_rcv;
182 struct socket_info *prev, *next;
185 static struct socket_info *sockets;
188 static const char *socket_wrapper_dir(void)
190 const char *s = getenv("SOCKET_WRAPPER_DIR");
194 if (strncmp(s, "./", 2) == 0) {
200 static unsigned int socket_wrapper_default_iface(void)
202 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
205 if (sscanf(s, "%u", &iface) == 1) {
206 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
212 return 1;/* 127.0.0.1 */
215 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
222 if ((*len) < sizeof(struct sockaddr_in)) {
226 p = strrchr(un->sun_path, '/');
227 if (p) p++; else p = un->sun_path;
229 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
234 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
239 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
249 in->sin_family = AF_INET;
250 in->sin_addr.s_addr = htonl((127<<24) | iface);
251 in->sin_port = htons(prt);
253 *len = sizeof(struct sockaddr_in);
257 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
264 unsigned int addr= ntohl(in->sin_addr.s_addr);
265 unsigned int prt = ntohs(in->sin_port);
269 if (bcast) *bcast = 0;
278 u_type = SOCKET_TYPE_CHAR_TCP;
281 u_type = SOCKET_TYPE_CHAR_UDP;
282 a_type = SOCKET_TYPE_CHAR_UDP;
283 b_type = SOCKET_TYPE_CHAR_UDP;
287 if (a_type && addr == 0xFFFFFFFF) {
288 /* 255.255.255.255 only udp */
291 iface = socket_wrapper_default_iface();
292 } else if (b_type && addr == 0x7FFFFFFF) {
293 /* 127.255.255.255 only udp */
296 iface = socket_wrapper_default_iface();
297 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
301 iface = (addr & 0x000000FF);
307 if (bcast) *bcast = is_bcast;
310 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
311 socket_wrapper_dir());
312 /* the caller need to do more processing */
316 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
317 socket_wrapper_dir(), type, iface, prt);
322 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
330 unsigned int addr= ntohl(in->sin_addr.s_addr);
331 unsigned int prt = ntohs(in->sin_port);
336 if (bcast) *bcast = 0;
340 u_type = SOCKET_TYPE_CHAR_TCP;
341 d_type = SOCKET_TYPE_CHAR_TCP;
344 u_type = SOCKET_TYPE_CHAR_UDP;
345 d_type = SOCKET_TYPE_CHAR_UDP;
346 a_type = SOCKET_TYPE_CHAR_UDP;
347 b_type = SOCKET_TYPE_CHAR_UDP;
355 iface = socket_wrapper_default_iface();
356 } else if (a_type && addr == 0xFFFFFFFF) {
357 /* 255.255.255.255 only udp */
360 iface = socket_wrapper_default_iface();
361 } else if (b_type && addr == 0x7FFFFFFF) {
362 /* 127.255.255.255 only udp */
365 iface = socket_wrapper_default_iface();
366 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
370 iface = (addr & 0x000000FF);
372 errno = EADDRNOTAVAIL;
376 if (bcast) *bcast = is_bcast;
379 /* handle auto-allocation of ephemeral ports */
380 for (prt = 5001; prt < 10000; prt++) {
381 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
382 socket_wrapper_dir(), type, iface, prt);
383 if (stat(un->sun_path, &st) == 0) continue;
385 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
392 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
393 socket_wrapper_dir(), type, iface, prt);
397 static struct socket_info *find_socket_info(int fd)
399 struct socket_info *i;
400 for (i = sockets; i; i = i->next) {
408 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
409 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
414 out_addr->sun_family = AF_UNIX;
416 switch (in_addr->sa_family) {
423 errno = ESOCKTNOSUPPORT;
427 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
429 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
435 errno = EAFNOSUPPORT;
439 static int sockaddr_convert_from_un(const struct socket_info *si,
440 const struct sockaddr_un *in_addr,
441 socklen_t un_addrlen,
443 struct sockaddr *out_addr,
444 socklen_t *_out_addrlen)
446 socklen_t out_addrlen;
448 if (out_addr == NULL || _out_addrlen == NULL)
451 if (un_addrlen == 0) {
456 out_addrlen = *_out_addrlen;
457 if (out_addrlen > un_addrlen) {
458 out_addrlen = un_addrlen;
468 errno = ESOCKTNOSUPPORT;
471 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
476 errno = EAFNOSUPPORT;
480 enum swrap_packet_type {
482 SWRAP_CONNECT_UNREACH,
490 SWRAP_SENDTO_UNREACH,
501 struct swrap_file_hdr {
503 unsigned short version_major;
504 unsigned short version_minor;
506 unsigned long sigfigs;
507 unsigned long frame_max_len;
508 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
509 unsigned long link_type;
511 #define SWRAP_FILE_HDR_SIZE 24
513 struct swrap_packet {
515 unsigned long seconds;
516 unsigned long micro_seconds;
517 unsigned long recorded_length;
518 unsigned long full_length;
520 #define SWRAP_PACKET__FRAME_SIZE 16
524 unsigned char ver_hdrlen;
526 unsigned short packet_length;
527 unsigned short identification;
529 unsigned char fragment;
531 unsigned char protocol;
532 unsigned short hdr_checksum;
533 unsigned long src_addr;
534 unsigned long dest_addr;
536 #define SWRAP_PACKET__IP_HDR_SIZE 20
540 unsigned short source_port;
541 unsigned short dest_port;
542 unsigned long seq_num;
543 unsigned long ack_num;
544 unsigned char hdr_length;
545 unsigned char control;
546 unsigned short window;
547 unsigned short checksum;
550 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
552 unsigned short source_port;
553 unsigned short dest_port;
554 unsigned short length;
555 unsigned short checksum;
557 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
561 unsigned short checksum;
562 unsigned long unused;
564 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
568 #define SWRAP_PACKET_SIZE 56
570 static const char *socket_wrapper_pcap_file(void)
572 static int initialized = 0;
573 static const char *s = NULL;
574 static const struct swrap_file_hdr h = { 0, };
575 static const struct swrap_packet p = { { 0, }, { { 0, }, { { 0, } } } };
577 if (initialized == 1) {
583 * TODO: don't use the structs use plain buffer offsets
584 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
586 * for now make sure we disable PCAP support
587 * if the struct has alignment!
589 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
592 if (sizeof(p) != SWRAP_PACKET_SIZE) {
595 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
598 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
601 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
604 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
607 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
611 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
615 if (strncmp(s, "./", 2) == 0) {
621 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
622 const struct sockaddr_in *src_addr,
623 const struct sockaddr_in *dest_addr,
625 const unsigned char *payload,
627 unsigned long tcp_seq,
628 unsigned long tcp_ack,
629 unsigned char tcp_ctl,
633 struct swrap_packet *ret;
634 struct swrap_packet *packet;
637 size_t nonwire_len = sizeof(packet->frame);
638 size_t wire_hdr_len = 0;
640 size_t icmp_hdr_len = 0;
641 size_t icmp_truncate_len = 0;
642 unsigned char protocol = 0, icmp_protocol = 0;
643 unsigned short src_port = src_addr->sin_port;
644 unsigned short dest_port = dest_addr->sin_port;
646 switch (socket_type) {
648 protocol = 0x06; /* TCP */
649 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
650 wire_len = wire_hdr_len + payload_len;
654 protocol = 0x11; /* UDP */
655 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
656 wire_len = wire_hdr_len + payload_len;
661 icmp_protocol = protocol;
662 protocol = 0x01; /* ICMP */
663 if (wire_len > 64 ) {
664 icmp_truncate_len = wire_len - 64;
666 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
667 wire_hdr_len += icmp_hdr_len;
668 wire_len += icmp_hdr_len;
671 packet_len = nonwire_len + wire_len;
672 alloc_len = packet_len;
673 if (alloc_len < sizeof(struct swrap_packet)) {
674 alloc_len = sizeof(struct swrap_packet);
676 ret = (struct swrap_packet *)malloc(alloc_len);
677 if (!ret) return NULL;
681 packet->frame.seconds = tval->tv_sec;
682 packet->frame.micro_seconds = tval->tv_usec;
683 packet->frame.recorded_length = wire_len - icmp_truncate_len;
684 packet->frame.full_length = wire_len - icmp_truncate_len;
686 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
687 packet->ip.hdr.tos = 0x00;
688 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
689 packet->ip.hdr.identification = htons(0xFFFF);
690 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
691 packet->ip.hdr.fragment = htons(0x0000);
692 packet->ip.hdr.ttl = 0xFF;
693 packet->ip.hdr.protocol = protocol;
694 packet->ip.hdr.hdr_checksum = htons(0x0000);
695 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
696 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
699 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
700 packet->ip.p.icmp.code = 0x01; /* host unreachable */
701 packet->ip.p.icmp.checksum = htons(0x0000);
702 packet->ip.p.icmp.unused = htonl(0x00000000);
704 /* set the ip header in the ICMP payload */
705 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
706 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
707 packet->ip.hdr.tos = 0x00;
708 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
709 packet->ip.hdr.identification = htons(0xFFFF);
710 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
711 packet->ip.hdr.fragment = htons(0x0000);
712 packet->ip.hdr.ttl = 0xFF;
713 packet->ip.hdr.protocol = icmp_protocol;
714 packet->ip.hdr.hdr_checksum = htons(0x0000);
715 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
716 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
718 src_port = dest_addr->sin_port;
719 dest_port = src_addr->sin_port;
722 switch (socket_type) {
724 packet->ip.p.tcp.source_port = src_port;
725 packet->ip.p.tcp.dest_port = dest_port;
726 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
727 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
728 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
729 packet->ip.p.tcp.control = tcp_ctl;
730 packet->ip.p.tcp.window = htons(0x7FFF);
731 packet->ip.p.tcp.checksum = htons(0x0000);
732 packet->ip.p.tcp.urg = htons(0x0000);
737 packet->ip.p.udp.source_port = src_addr->sin_port;
738 packet->ip.p.udp.dest_port = dest_addr->sin_port;
739 packet->ip.p.udp.length = htons(8 + payload_len);
740 packet->ip.p.udp.checksum = htons(0x0000);
745 if (payload && payload_len > 0) {
746 unsigned char *p = (unsigned char *)ret;
749 memcpy(p, payload, payload_len);
752 *_packet_len = packet_len - icmp_truncate_len;
756 static int swrap_get_pcap_fd(const char *fname)
760 if (fd != -1) return fd;
762 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
764 struct swrap_file_hdr file_hdr;
765 file_hdr.magic = 0xA1B2C3D4;
766 file_hdr.version_major = 0x0002;
767 file_hdr.version_minor = 0x0004;
768 file_hdr.timezone = 0x00000000;
769 file_hdr.sigfigs = 0x00000000;
770 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
771 file_hdr.link_type = 0x0065; /* 101 RAW IP */
773 write(fd, &file_hdr, sizeof(file_hdr));
777 fd = open(fname, O_WRONLY|O_APPEND, 0644);
782 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
783 enum swrap_packet_type type,
784 const void *buf, size_t len)
786 const struct sockaddr_in *src_addr;
787 const struct sockaddr_in *dest_addr;
788 const char *file_name;
789 unsigned long tcp_seq = 0;
790 unsigned long tcp_ack = 0;
791 unsigned char tcp_ctl = 0;
794 struct swrap_packet *packet;
795 size_t packet_len = 0;
798 file_name = socket_wrapper_pcap_file();
803 if (si->family != AF_INET) {
808 case SWRAP_CONNECT_SEND:
809 if (si->type != SOCK_STREAM) return;
811 src_addr = (const struct sockaddr_in *)si->myname;
812 dest_addr = (const struct sockaddr_in *)addr;
814 tcp_seq = si->io.pck_snd;
815 tcp_ack = si->io.pck_rcv;
816 tcp_ctl = 0x02; /* SYN */
822 case SWRAP_CONNECT_RECV:
823 if (si->type != SOCK_STREAM) return;
825 dest_addr = (const struct sockaddr_in *)si->myname;
826 src_addr = (const struct sockaddr_in *)addr;
828 tcp_seq = si->io.pck_rcv;
829 tcp_ack = si->io.pck_snd;
830 tcp_ctl = 0x12; /** SYN,ACK */
836 case SWRAP_CONNECT_UNREACH:
837 if (si->type != SOCK_STREAM) return;
839 dest_addr = (const struct sockaddr_in *)si->myname;
840 src_addr = (const struct sockaddr_in *)addr;
842 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
843 tcp_seq = si->io.pck_snd - 1;
844 tcp_ack = si->io.pck_rcv;
845 tcp_ctl = 0x02; /* SYN */
850 case SWRAP_CONNECT_ACK:
851 if (si->type != SOCK_STREAM) return;
853 src_addr = (const struct sockaddr_in *)si->myname;
854 dest_addr = (const struct sockaddr_in *)addr;
856 tcp_seq = si->io.pck_snd;
857 tcp_ack = si->io.pck_rcv;
858 tcp_ctl = 0x10; /* ACK */
862 case SWRAP_ACCEPT_SEND:
863 if (si->type != SOCK_STREAM) return;
865 dest_addr = (const struct sockaddr_in *)si->myname;
866 src_addr = (const struct sockaddr_in *)addr;
868 tcp_seq = si->io.pck_rcv;
869 tcp_ack = si->io.pck_snd;
870 tcp_ctl = 0x02; /* SYN */
876 case SWRAP_ACCEPT_RECV:
877 if (si->type != SOCK_STREAM) return;
879 src_addr = (const struct sockaddr_in *)si->myname;
880 dest_addr = (const struct sockaddr_in *)addr;
882 tcp_seq = si->io.pck_snd;
883 tcp_ack = si->io.pck_rcv;
884 tcp_ctl = 0x12; /* SYN,ACK */
890 case SWRAP_ACCEPT_ACK:
891 if (si->type != SOCK_STREAM) return;
893 dest_addr = (const struct sockaddr_in *)si->myname;
894 src_addr = (const struct sockaddr_in *)addr;
896 tcp_seq = si->io.pck_rcv;
897 tcp_ack = si->io.pck_snd;
898 tcp_ctl = 0x10; /* ACK */
903 src_addr = (const struct sockaddr_in *)si->myname;
904 dest_addr = (const struct sockaddr_in *)si->peername;
906 tcp_seq = si->io.pck_snd;
907 tcp_ack = si->io.pck_rcv;
908 tcp_ctl = 0x18; /* PSH,ACK */
910 si->io.pck_snd += len;
915 dest_addr = (const struct sockaddr_in *)si->myname;
916 src_addr = (const struct sockaddr_in *)si->peername;
918 if (si->type == SOCK_DGRAM) {
919 swrap_dump_packet(si, si->peername,
920 SWRAP_SENDTO_UNREACH,
925 tcp_seq = si->io.pck_rcv;
926 tcp_ack = si->io.pck_snd;
927 tcp_ctl = 0x14; /** RST,ACK */
931 case SWRAP_PENDING_RST:
932 dest_addr = (const struct sockaddr_in *)si->myname;
933 src_addr = (const struct sockaddr_in *)si->peername;
935 if (si->type == SOCK_DGRAM) {
939 tcp_seq = si->io.pck_rcv;
940 tcp_ack = si->io.pck_snd;
941 tcp_ctl = 0x14; /* RST,ACK */
946 dest_addr = (const struct sockaddr_in *)si->myname;
947 src_addr = (const struct sockaddr_in *)si->peername;
949 tcp_seq = si->io.pck_rcv;
950 tcp_ack = si->io.pck_snd;
951 tcp_ctl = 0x18; /* PSH,ACK */
953 si->io.pck_rcv += len;
958 dest_addr = (const struct sockaddr_in *)si->myname;
959 src_addr = (const struct sockaddr_in *)si->peername;
961 if (si->type == SOCK_DGRAM) {
965 tcp_seq = si->io.pck_rcv;
966 tcp_ack = si->io.pck_snd;
967 tcp_ctl = 0x14; /* RST,ACK */
972 src_addr = (const struct sockaddr_in *)si->myname;
973 dest_addr = (const struct sockaddr_in *)addr;
975 si->io.pck_snd += len;
979 case SWRAP_SENDTO_UNREACH:
980 dest_addr = (const struct sockaddr_in *)si->myname;
981 src_addr = (const struct sockaddr_in *)addr;
988 dest_addr = (const struct sockaddr_in *)si->myname;
989 src_addr = (const struct sockaddr_in *)addr;
991 si->io.pck_rcv += len;
995 case SWRAP_CLOSE_SEND:
996 if (si->type != SOCK_STREAM) return;
998 src_addr = (const struct sockaddr_in *)si->myname;
999 dest_addr = (const struct sockaddr_in *)si->peername;
1001 tcp_seq = si->io.pck_snd;
1002 tcp_ack = si->io.pck_rcv;
1003 tcp_ctl = 0x11; /* FIN, ACK */
1005 si->io.pck_snd += 1;
1009 case SWRAP_CLOSE_RECV:
1010 if (si->type != SOCK_STREAM) return;
1012 dest_addr = (const struct sockaddr_in *)si->myname;
1013 src_addr = (const struct sockaddr_in *)si->peername;
1015 tcp_seq = si->io.pck_rcv;
1016 tcp_ack = si->io.pck_snd;
1017 tcp_ctl = 0x11; /* FIN,ACK */
1019 si->io.pck_rcv += 1;
1023 case SWRAP_CLOSE_ACK:
1024 if (si->type != SOCK_STREAM) return;
1026 src_addr = (const struct sockaddr_in *)si->myname;
1027 dest_addr = (const struct sockaddr_in *)si->peername;
1029 tcp_seq = si->io.pck_snd;
1030 tcp_ack = si->io.pck_rcv;
1031 tcp_ctl = 0x10; /* ACK */
1038 swrapGetTimeOfDay(&tv);
1040 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1041 (const unsigned char *)buf, len,
1042 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1048 fd = swrap_get_pcap_fd(file_name);
1050 write(fd, packet, packet_len);
1056 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1058 struct socket_info *si;
1061 if (!socket_wrapper_dir()) {
1062 return real_socket(family, type, protocol);
1069 return real_socket(family, type, protocol);
1071 errno = EAFNOSUPPORT;
1081 errno = EPROTONOSUPPORT;
1089 errno = EPROTONOSUPPORT;
1093 fd = real_socket(AF_UNIX, type, 0);
1095 if (fd == -1) return -1;
1097 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1099 si->family = family;
1101 si->protocol = protocol;
1104 SWRAP_DLIST_ADD(sockets, si);
1109 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1111 struct socket_info *parent_si, *child_si;
1113 struct sockaddr_un un_addr;
1114 socklen_t un_addrlen = sizeof(un_addr);
1115 struct sockaddr_un un_my_addr;
1116 socklen_t un_my_addrlen = sizeof(un_my_addr);
1117 struct sockaddr my_addr;
1118 socklen_t my_addrlen = sizeof(my_addr);
1121 parent_si = find_socket_info(s);
1123 return real_accept(s, addr, addrlen);
1126 memset(&un_addr, 0, sizeof(un_addr));
1127 memset(&un_my_addr, 0, sizeof(un_my_addr));
1128 memset(&my_addr, 0, sizeof(my_addr));
1130 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1131 if (ret == -1) return ret;
1135 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1136 parent_si->family, addr, addrlen);
1142 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1143 memset(child_si, 0, sizeof(*child_si));
1146 child_si->family = parent_si->family;
1147 child_si->type = parent_si->type;
1148 child_si->protocol = parent_si->protocol;
1149 child_si->bound = 1;
1150 child_si->is_server = 1;
1152 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1159 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1160 child_si->family, &my_addr, &my_addrlen);
1167 child_si->myname_len = my_addrlen;
1168 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1170 child_si->peername_len = *addrlen;
1171 child_si->peername = sockaddr_dup(addr, *addrlen);
1173 SWRAP_DLIST_ADD(sockets, child_si);
1175 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1176 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1177 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1182 static int autobind_start_init;
1183 static int autobind_start;
1185 /* using sendto() or connect() on an unbound socket would give the
1186 recipient no way to reply, as unlike UDP and TCP, a unix domain
1187 socket can't auto-assign emphemeral port numbers, so we need to
1189 static int swrap_auto_bind(struct socket_info *si)
1191 struct sockaddr_un un_addr;
1192 struct sockaddr_in in;
1199 if (autobind_start_init != 1) {
1200 autobind_start_init = 1;
1201 autobind_start = getpid();
1202 autobind_start %= 50000;
1203 autobind_start += 10000;
1206 un_addr.sun_family = AF_UNIX;
1210 type = SOCKET_TYPE_CHAR_TCP;
1213 type = SOCKET_TYPE_CHAR_UDP;
1216 errno = ESOCKTNOSUPPORT;
1220 if (autobind_start > 60000) {
1221 autobind_start = 10000;
1224 for (i=0;i<1000;i++) {
1225 port = autobind_start + i;
1226 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1227 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1228 type, socket_wrapper_default_iface(), port);
1229 if (stat(un_addr.sun_path, &st) == 0) continue;
1231 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1232 if (ret == -1) return ret;
1234 si->tmp_path = strdup(un_addr.sun_path);
1236 autobind_start = port + 1;
1244 memset(&in, 0, sizeof(in));
1245 in.sin_family = AF_INET;
1246 in.sin_port = htons(port);
1247 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1249 si->myname_len = sizeof(in);
1250 si->myname = sockaddr_dup(&in, si->myname_len);
1255 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1258 struct sockaddr_un un_addr;
1259 struct socket_info *si = find_socket_info(s);
1262 return real_connect(s, serv_addr, addrlen);
1265 if (si->bound == 0) {
1266 ret = swrap_auto_bind(si);
1267 if (ret == -1) return -1;
1270 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1271 if (ret == -1) return -1;
1273 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1275 ret = real_connect(s, (struct sockaddr *)&un_addr,
1276 sizeof(struct sockaddr_un));
1278 /* to give better errors */
1279 if (ret == -1 && errno == ENOENT) {
1280 errno = EHOSTUNREACH;
1284 si->peername_len = addrlen;
1285 si->peername = sockaddr_dup(serv_addr, addrlen);
1287 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1288 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1290 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1296 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1299 struct sockaddr_un un_addr;
1300 struct socket_info *si = find_socket_info(s);
1303 return real_bind(s, myaddr, addrlen);
1306 si->myname_len = addrlen;
1307 si->myname = sockaddr_dup(myaddr, addrlen);
1309 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1310 if (ret == -1) return -1;
1312 unlink(un_addr.sun_path);
1314 ret = real_bind(s, (struct sockaddr *)&un_addr,
1315 sizeof(struct sockaddr_un));
1324 _PUBLIC_ int swrap_listen(int s, int backlog)
1327 struct socket_info *si = find_socket_info(s);
1330 return real_listen(s, backlog);
1333 ret = real_listen(s, backlog);
1338 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1340 struct socket_info *si = find_socket_info(s);
1343 return real_getpeername(s, name, addrlen);
1352 memcpy(name, si->peername, si->peername_len);
1353 *addrlen = si->peername_len;
1358 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1360 struct socket_info *si = find_socket_info(s);
1363 return real_getsockname(s, name, addrlen);
1366 memcpy(name, si->myname, si->myname_len);
1367 *addrlen = si->myname_len;
1372 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1374 struct socket_info *si = find_socket_info(s);
1377 return real_getsockopt(s, level, optname, optval, optlen);
1380 if (level == SOL_SOCKET) {
1381 return real_getsockopt(s, level, optname, optval, optlen);
1384 errno = ENOPROTOOPT;
1388 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1390 struct socket_info *si = find_socket_info(s);
1393 return real_setsockopt(s, level, optname, optval, optlen);
1396 if (level == SOL_SOCKET) {
1397 return real_setsockopt(s, level, optname, optval, optlen);
1400 switch (si->family) {
1404 errno = ENOPROTOOPT;
1409 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1411 struct sockaddr_un un_addr;
1412 socklen_t un_addrlen = sizeof(un_addr);
1414 struct socket_info *si = find_socket_info(s);
1417 return real_recvfrom(s, buf, len, flags, from, fromlen);
1420 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1421 memset(&un_addr, 0, sizeof(un_addr));
1422 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1426 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1427 si->family, from, fromlen) == -1) {
1431 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1437 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1439 struct sockaddr_un un_addr;
1441 struct socket_info *si = find_socket_info(s);
1445 return real_sendto(s, buf, len, flags, to, tolen);
1448 if (si->bound == 0) {
1449 ret = swrap_auto_bind(si);
1450 if (ret == -1) return -1;
1453 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1454 if (ret == -1) return -1;
1459 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1462 type = SOCKET_TYPE_CHAR_UDP;
1464 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1465 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1466 socket_wrapper_dir(), type, iface, prt);
1467 if (stat(un_addr.sun_path, &st) != 0) continue;
1469 /* ignore the any errors in broadcast sends */
1470 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1473 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1478 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1480 /* to give better errors */
1481 if (ret == -1 && errno == ENOENT) {
1482 errno = EHOSTUNREACH;
1486 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1487 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1489 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1495 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1498 struct socket_info *si = find_socket_info(s);
1502 return real_ioctl(s, r, p);
1505 ret = real_ioctl(s, r, p);
1509 value = *((int *)p);
1510 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1511 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1512 } else if (value == 0) { /* END OF FILE */
1513 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1521 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1524 struct socket_info *si = find_socket_info(s);
1527 return real_recv(s, buf, len, flags);
1530 ret = real_recv(s, buf, len, flags);
1531 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1532 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1533 } else if (ret == 0) { /* END OF FILE */
1534 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1536 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1543 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1546 struct socket_info *si = find_socket_info(s);
1549 return real_send(s, buf, len, flags);
1552 ret = real_send(s, buf, len, flags);
1555 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1556 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1558 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1564 _PUBLIC_ int swrap_close(int fd)
1566 struct socket_info *si = find_socket_info(fd);
1570 return real_close(fd);
1573 SWRAP_DLIST_REMOVE(sockets, si);
1575 if (si->myname && si->peername) {
1576 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1579 ret = real_close(fd);
1581 if (si->myname && si->peername) {
1582 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1583 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1586 if (si->path) free(si->path);
1587 if (si->myname) free(si->myname);
1588 if (si->peername) free(si->peername);
1590 unlink(si->tmp_path);