2 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the author nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
44 #define SOCKET_WRAPPER_NOT_REPLACE
46 #include "system/network.h"
47 #include "system/filesys.h"
59 #else /* _SAMBA_BUILD_ */
61 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <sys/ioctl.h>
66 #include <sys/filio.h>
69 #include <netinet/in.h>
70 #include <netinet/tcp.h>
81 #define SWRAP_DLIST_ADD(list,item) do { \
83 (item)->prev = NULL; \
84 (item)->next = NULL; \
87 (item)->prev = NULL; \
88 (item)->next = (list); \
89 (list)->prev = (item); \
94 #define SWRAP_DLIST_REMOVE(list,item) do { \
95 if ((list) == (item)) { \
96 (list) = (item)->next; \
98 (list)->prev = NULL; \
101 if ((item)->prev) { \
102 (item)->prev->next = (item)->next; \
104 if ((item)->next) { \
105 (item)->next->prev = (item)->prev; \
108 (item)->prev = NULL; \
109 (item)->next = NULL; \
112 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
114 #define REWRITE_CALLS
117 #define real_accept accept
118 #define real_connect connect
119 #define real_bind bind
120 #define real_listen listen
121 #define real_getpeername getpeername
122 #define real_getsockname getsockname
123 #define real_getsockopt getsockopt
124 #define real_setsockopt setsockopt
125 #define real_recvfrom recvfrom
126 #define real_sendto sendto
127 #define real_ioctl ioctl
128 #define real_recv recv
129 #define real_send send
130 #define real_socket socket
131 #define real_close close
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
140 /* we need to use a very terse format here as IRIX 6.4 silently
141 truncates names to 16 chars, so if we use a longer name then we
142 can't tell which port a packet came from with recvfrom()
144 with this format we have 8 chars left for the directory name
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
150 #define MAX_WRAPPED_INTERFACES 16
152 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
154 struct sockaddr *ret = (struct sockaddr *)malloc(len);
155 memcpy(ret, data, len);
173 struct sockaddr *myname;
174 socklen_t myname_len;
176 struct sockaddr *peername;
177 socklen_t peername_len;
180 unsigned long pck_snd;
181 unsigned long pck_rcv;
184 struct socket_info *prev, *next;
187 static struct socket_info *sockets;
190 const char *socket_wrapper_dir(void)
192 const char *s = getenv("SOCKET_WRAPPER_DIR");
196 if (strncmp(s, "./", 2) == 0) {
202 static unsigned int socket_wrapper_default_iface(void)
204 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
207 if (sscanf(s, "%u", &iface) == 1) {
208 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
214 return 1;/* 127.0.0.1 */
217 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
224 if ((*len) < sizeof(struct sockaddr_in)) {
228 p = strrchr(un->sun_path, '/');
229 if (p) p++; else p = un->sun_path;
231 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
236 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
241 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
251 in->sin_family = AF_INET;
252 in->sin_addr.s_addr = htonl((127<<24) | iface);
253 in->sin_port = htons(prt);
255 *len = sizeof(struct sockaddr_in);
259 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
266 unsigned int addr= ntohl(in->sin_addr.s_addr);
267 unsigned int prt = ntohs(in->sin_port);
271 if (bcast) *bcast = 0;
280 u_type = SOCKET_TYPE_CHAR_TCP;
283 u_type = SOCKET_TYPE_CHAR_UDP;
284 a_type = SOCKET_TYPE_CHAR_UDP;
285 b_type = SOCKET_TYPE_CHAR_UDP;
289 if (a_type && addr == 0xFFFFFFFF) {
290 /* 255.255.255.255 only udp */
293 iface = socket_wrapper_default_iface();
294 } else if (b_type && addr == 0x7FFFFFFF) {
295 /* 127.255.255.255 only udp */
298 iface = socket_wrapper_default_iface();
299 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
303 iface = (addr & 0x000000FF);
309 if (bcast) *bcast = is_bcast;
312 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
313 socket_wrapper_dir());
314 /* the caller need to do more processing */
318 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
319 socket_wrapper_dir(), type, iface, prt);
324 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
332 unsigned int addr= ntohl(in->sin_addr.s_addr);
333 unsigned int prt = ntohs(in->sin_port);
338 if (bcast) *bcast = 0;
342 u_type = SOCKET_TYPE_CHAR_TCP;
343 d_type = SOCKET_TYPE_CHAR_TCP;
346 u_type = SOCKET_TYPE_CHAR_UDP;
347 d_type = SOCKET_TYPE_CHAR_UDP;
348 a_type = SOCKET_TYPE_CHAR_UDP;
349 b_type = SOCKET_TYPE_CHAR_UDP;
357 iface = socket_wrapper_default_iface();
358 } else if (a_type && addr == 0xFFFFFFFF) {
359 /* 255.255.255.255 only udp */
362 iface = socket_wrapper_default_iface();
363 } else if (b_type && addr == 0x7FFFFFFF) {
364 /* 127.255.255.255 only udp */
367 iface = socket_wrapper_default_iface();
368 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
372 iface = (addr & 0x000000FF);
374 errno = EADDRNOTAVAIL;
378 if (bcast) *bcast = is_bcast;
381 /* handle auto-allocation of ephemeral ports */
382 for (prt = 5001; prt < 10000; prt++) {
383 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
384 socket_wrapper_dir(), type, iface, prt);
385 if (stat(un->sun_path, &st) == 0) continue;
387 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
394 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
395 socket_wrapper_dir(), type, iface, prt);
399 static struct socket_info *find_socket_info(int fd)
401 struct socket_info *i;
402 for (i = sockets; i; i = i->next) {
410 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
411 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
416 out_addr->sun_family = AF_UNIX;
418 switch (in_addr->sa_family) {
425 errno = ESOCKTNOSUPPORT;
429 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
431 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
437 errno = EAFNOSUPPORT;
441 static int sockaddr_convert_from_un(const struct socket_info *si,
442 const struct sockaddr_un *in_addr,
443 socklen_t un_addrlen,
445 struct sockaddr *out_addr,
446 socklen_t *_out_addrlen)
448 socklen_t out_addrlen;
450 if (out_addr == NULL || _out_addrlen == NULL)
453 if (un_addrlen == 0) {
458 out_addrlen = *_out_addrlen;
459 if (out_addrlen > un_addrlen) {
460 out_addrlen = un_addrlen;
470 errno = ESOCKTNOSUPPORT;
473 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
478 errno = EAFNOSUPPORT;
482 enum swrap_packet_type {
484 SWRAP_CONNECT_UNREACH,
492 SWRAP_SENDTO_UNREACH,
503 struct swrap_file_hdr {
505 unsigned short version_major;
506 unsigned short version_minor;
508 unsigned long sigfigs;
509 unsigned long frame_max_len;
510 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
511 unsigned long link_type;
513 #define SWRAP_FILE_HDR_SIZE 24
515 struct swrap_packet {
517 unsigned long seconds;
518 unsigned long micro_seconds;
519 unsigned long recorded_length;
520 unsigned long full_length;
522 #define SWRAP_PACKET__FRAME_SIZE 16
526 unsigned char ver_hdrlen;
528 unsigned short packet_length;
529 unsigned short identification;
531 unsigned char fragment;
533 unsigned char protocol;
534 unsigned short hdr_checksum;
535 unsigned long src_addr;
536 unsigned long dest_addr;
538 #define SWRAP_PACKET__IP_HDR_SIZE 20
542 unsigned short source_port;
543 unsigned short dest_port;
544 unsigned long seq_num;
545 unsigned long ack_num;
546 unsigned char hdr_length;
547 unsigned char control;
548 unsigned short window;
549 unsigned short checksum;
552 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
554 unsigned short source_port;
555 unsigned short dest_port;
556 unsigned short length;
557 unsigned short checksum;
559 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
563 unsigned short checksum;
564 unsigned long unused;
566 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
570 #define SWRAP_PACKET_SIZE 56
572 static const char *socket_wrapper_pcap_file(void)
574 static int initialized = 0;
575 static const char *s = NULL;
576 static const struct swrap_file_hdr h;
577 static const struct swrap_packet p;
579 if (initialized == 1) {
585 * TODO: don't use the structs use plain buffer offsets
586 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
588 * for now make sure we disable PCAP support
589 * if the struct has alignment!
591 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
594 if (sizeof(p) != SWRAP_PACKET_SIZE) {
597 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
600 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
603 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
606 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
609 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
613 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
617 if (strncmp(s, "./", 2) == 0) {
623 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
624 const struct sockaddr_in *src_addr,
625 const struct sockaddr_in *dest_addr,
627 const unsigned char *payload,
629 unsigned long tcp_seq,
630 unsigned long tcp_ack,
631 unsigned char tcp_ctl,
635 struct swrap_packet *ret;
636 struct swrap_packet *packet;
639 size_t nonwire_len = sizeof(packet->frame);
640 size_t wire_hdr_len = 0;
642 size_t icmp_hdr_len = 0;
643 size_t icmp_truncate_len = 0;
644 unsigned char protocol = 0, icmp_protocol = 0;
645 unsigned short src_port = src_addr->sin_port;
646 unsigned short dest_port = dest_addr->sin_port;
648 switch (socket_type) {
650 protocol = 0x06; /* TCP */
651 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
652 wire_len = wire_hdr_len + payload_len;
656 protocol = 0x11; /* UDP */
657 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
658 wire_len = wire_hdr_len + payload_len;
663 icmp_protocol = protocol;
664 protocol = 0x01; /* ICMP */
665 if (wire_len > 64 ) {
666 icmp_truncate_len = wire_len - 64;
668 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
669 wire_hdr_len += icmp_hdr_len;
670 wire_len += icmp_hdr_len;
673 packet_len = nonwire_len + wire_len;
674 alloc_len = packet_len;
675 if (alloc_len < sizeof(struct swrap_packet)) {
676 alloc_len = sizeof(struct swrap_packet);
678 ret = (struct swrap_packet *)malloc(alloc_len);
679 if (!ret) return NULL;
683 packet->frame.seconds = tval->tv_sec;
684 packet->frame.micro_seconds = tval->tv_usec;
685 packet->frame.recorded_length = wire_len - icmp_truncate_len;
686 packet->frame.full_length = wire_len - icmp_truncate_len;
688 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
689 packet->ip.hdr.tos = 0x00;
690 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
691 packet->ip.hdr.identification = htons(0xFFFF);
692 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
693 packet->ip.hdr.fragment = htons(0x0000);
694 packet->ip.hdr.ttl = 0xFF;
695 packet->ip.hdr.protocol = protocol;
696 packet->ip.hdr.hdr_checksum = htons(0x0000);
697 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
698 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
701 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
702 packet->ip.p.icmp.code = 0x01; /* host unreachable */
703 packet->ip.p.icmp.checksum = htons(0x0000);
704 packet->ip.p.icmp.unused = htonl(0x00000000);
706 /* set the ip header in the ICMP payload */
707 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
708 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
709 packet->ip.hdr.tos = 0x00;
710 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
711 packet->ip.hdr.identification = htons(0xFFFF);
712 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
713 packet->ip.hdr.fragment = htons(0x0000);
714 packet->ip.hdr.ttl = 0xFF;
715 packet->ip.hdr.protocol = icmp_protocol;
716 packet->ip.hdr.hdr_checksum = htons(0x0000);
717 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
718 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
720 src_port = dest_addr->sin_port;
721 dest_port = src_addr->sin_port;
724 switch (socket_type) {
726 packet->ip.p.tcp.source_port = src_port;
727 packet->ip.p.tcp.dest_port = dest_port;
728 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
729 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
730 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
731 packet->ip.p.tcp.control = tcp_ctl;
732 packet->ip.p.tcp.window = htons(0x7FFF);
733 packet->ip.p.tcp.checksum = htons(0x0000);
734 packet->ip.p.tcp.urg = htons(0x0000);
739 packet->ip.p.udp.source_port = src_addr->sin_port;
740 packet->ip.p.udp.dest_port = dest_addr->sin_port;
741 packet->ip.p.udp.length = htons(8 + payload_len);
742 packet->ip.p.udp.checksum = htons(0x0000);
747 if (payload && payload_len > 0) {
748 unsigned char *p = (unsigned char *)ret;
751 memcpy(p, payload, payload_len);
754 *_packet_len = packet_len - icmp_truncate_len;
758 static int swrap_get_pcap_fd(const char *fname)
762 if (fd != -1) return fd;
764 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
766 struct swrap_file_hdr file_hdr;
767 file_hdr.magic = 0xA1B2C3D4;
768 file_hdr.version_major = 0x0002;
769 file_hdr.version_minor = 0x0004;
770 file_hdr.timezone = 0x00000000;
771 file_hdr.sigfigs = 0x00000000;
772 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
773 file_hdr.link_type = 0x0065; /* 101 RAW IP */
775 write(fd, &file_hdr, sizeof(file_hdr));
779 fd = open(fname, O_WRONLY|O_APPEND, 0644);
784 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
785 enum swrap_packet_type type,
786 const void *buf, size_t len)
788 const struct sockaddr_in *src_addr;
789 const struct sockaddr_in *dest_addr;
790 const char *file_name;
791 unsigned long tcp_seq = 0;
792 unsigned long tcp_ack = 0;
793 unsigned char tcp_ctl = 0;
796 struct swrap_packet *packet;
797 size_t packet_len = 0;
800 file_name = socket_wrapper_pcap_file();
805 if (si->family != AF_INET) {
810 case SWRAP_CONNECT_SEND:
811 if (si->type != SOCK_STREAM) return;
813 src_addr = (const struct sockaddr_in *)si->myname;
814 dest_addr = (const struct sockaddr_in *)addr;
816 tcp_seq = si->io.pck_snd;
817 tcp_ack = si->io.pck_rcv;
818 tcp_ctl = 0x02; /* SYN */
824 case SWRAP_CONNECT_RECV:
825 if (si->type != SOCK_STREAM) return;
827 dest_addr = (const struct sockaddr_in *)si->myname;
828 src_addr = (const struct sockaddr_in *)addr;
830 tcp_seq = si->io.pck_rcv;
831 tcp_ack = si->io.pck_snd;
832 tcp_ctl = 0x12; /** SYN,ACK */
838 case SWRAP_CONNECT_UNREACH:
839 if (si->type != SOCK_STREAM) return;
841 dest_addr = (const struct sockaddr_in *)si->myname;
842 src_addr = (const struct sockaddr_in *)addr;
844 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
845 tcp_seq = si->io.pck_snd - 1;
846 tcp_ack = si->io.pck_rcv;
847 tcp_ctl = 0x02; /* SYN */
852 case SWRAP_CONNECT_ACK:
853 if (si->type != SOCK_STREAM) return;
855 src_addr = (const struct sockaddr_in *)si->myname;
856 dest_addr = (const struct sockaddr_in *)addr;
858 tcp_seq = si->io.pck_snd;
859 tcp_ack = si->io.pck_rcv;
860 tcp_ctl = 0x10; /* ACK */
864 case SWRAP_ACCEPT_SEND:
865 if (si->type != SOCK_STREAM) return;
867 dest_addr = (const struct sockaddr_in *)si->myname;
868 src_addr = (const struct sockaddr_in *)addr;
870 tcp_seq = si->io.pck_rcv;
871 tcp_ack = si->io.pck_snd;
872 tcp_ctl = 0x02; /* SYN */
878 case SWRAP_ACCEPT_RECV:
879 if (si->type != SOCK_STREAM) return;
881 src_addr = (const struct sockaddr_in *)si->myname;
882 dest_addr = (const struct sockaddr_in *)addr;
884 tcp_seq = si->io.pck_snd;
885 tcp_ack = si->io.pck_rcv;
886 tcp_ctl = 0x12; /* SYN,ACK */
892 case SWRAP_ACCEPT_ACK:
893 if (si->type != SOCK_STREAM) return;
895 dest_addr = (const struct sockaddr_in *)si->myname;
896 src_addr = (const struct sockaddr_in *)addr;
898 tcp_seq = si->io.pck_rcv;
899 tcp_ack = si->io.pck_snd;
900 tcp_ctl = 0x10; /* ACK */
905 src_addr = (const struct sockaddr_in *)si->myname;
906 dest_addr = (const struct sockaddr_in *)si->peername;
908 tcp_seq = si->io.pck_snd;
909 tcp_ack = si->io.pck_rcv;
910 tcp_ctl = 0x18; /* PSH,ACK */
912 si->io.pck_snd += len;
917 dest_addr = (const struct sockaddr_in *)si->myname;
918 src_addr = (const struct sockaddr_in *)si->peername;
920 if (si->type == SOCK_DGRAM) {
921 swrap_dump_packet(si, si->peername,
922 SWRAP_SENDTO_UNREACH,
927 tcp_seq = si->io.pck_rcv;
928 tcp_ack = si->io.pck_snd;
929 tcp_ctl = 0x14; /** RST,ACK */
933 case SWRAP_PENDING_RST:
934 dest_addr = (const struct sockaddr_in *)si->myname;
935 src_addr = (const struct sockaddr_in *)si->peername;
937 if (si->type == SOCK_DGRAM) {
941 tcp_seq = si->io.pck_rcv;
942 tcp_ack = si->io.pck_snd;
943 tcp_ctl = 0x14; /* RST,ACK */
948 dest_addr = (const struct sockaddr_in *)si->myname;
949 src_addr = (const struct sockaddr_in *)si->peername;
951 tcp_seq = si->io.pck_rcv;
952 tcp_ack = si->io.pck_snd;
953 tcp_ctl = 0x18; /* PSH,ACK */
955 si->io.pck_rcv += len;
960 dest_addr = (const struct sockaddr_in *)si->myname;
961 src_addr = (const struct sockaddr_in *)si->peername;
963 if (si->type == SOCK_DGRAM) {
967 tcp_seq = si->io.pck_rcv;
968 tcp_ack = si->io.pck_snd;
969 tcp_ctl = 0x14; /* RST,ACK */
974 src_addr = (const struct sockaddr_in *)si->myname;
975 dest_addr = (const struct sockaddr_in *)addr;
977 si->io.pck_snd += len;
981 case SWRAP_SENDTO_UNREACH:
982 dest_addr = (const struct sockaddr_in *)si->myname;
983 src_addr = (const struct sockaddr_in *)addr;
990 dest_addr = (const struct sockaddr_in *)si->myname;
991 src_addr = (const struct sockaddr_in *)addr;
993 si->io.pck_rcv += len;
997 case SWRAP_CLOSE_SEND:
998 if (si->type != SOCK_STREAM) return;
1000 src_addr = (const struct sockaddr_in *)si->myname;
1001 dest_addr = (const struct sockaddr_in *)si->peername;
1003 tcp_seq = si->io.pck_snd;
1004 tcp_ack = si->io.pck_rcv;
1005 tcp_ctl = 0x11; /* FIN, ACK */
1007 si->io.pck_snd += 1;
1011 case SWRAP_CLOSE_RECV:
1012 if (si->type != SOCK_STREAM) return;
1014 dest_addr = (const struct sockaddr_in *)si->myname;
1015 src_addr = (const struct sockaddr_in *)si->peername;
1017 tcp_seq = si->io.pck_rcv;
1018 tcp_ack = si->io.pck_snd;
1019 tcp_ctl = 0x11; /* FIN,ACK */
1021 si->io.pck_rcv += 1;
1025 case SWRAP_CLOSE_ACK:
1026 if (si->type != SOCK_STREAM) return;
1028 src_addr = (const struct sockaddr_in *)si->myname;
1029 dest_addr = (const struct sockaddr_in *)si->peername;
1031 tcp_seq = si->io.pck_snd;
1032 tcp_ack = si->io.pck_rcv;
1033 tcp_ctl = 0x10; /* ACK */
1040 swrapGetTimeOfDay(&tv);
1042 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1043 (const unsigned char *)buf, len,
1044 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1050 fd = swrap_get_pcap_fd(file_name);
1052 write(fd, packet, packet_len);
1058 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1060 struct socket_info *si;
1063 if (!socket_wrapper_dir()) {
1064 return real_socket(family, type, protocol);
1071 return real_socket(family, type, protocol);
1073 errno = EAFNOSUPPORT;
1083 errno = EPROTONOSUPPORT;
1091 errno = EPROTONOSUPPORT;
1095 fd = real_socket(AF_UNIX, type, 0);
1097 if (fd == -1) return -1;
1099 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1101 si->family = family;
1103 si->protocol = protocol;
1106 SWRAP_DLIST_ADD(sockets, si);
1111 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1113 struct socket_info *parent_si, *child_si;
1115 struct sockaddr_un un_addr;
1116 socklen_t un_addrlen = sizeof(un_addr);
1117 struct sockaddr_un un_my_addr;
1118 socklen_t un_my_addrlen = sizeof(un_my_addr);
1119 struct sockaddr my_addr;
1120 socklen_t my_addrlen = sizeof(my_addr);
1123 parent_si = find_socket_info(s);
1125 return real_accept(s, addr, addrlen);
1128 memset(&un_addr, 0, sizeof(un_addr));
1129 memset(&un_my_addr, 0, sizeof(un_my_addr));
1130 memset(&my_addr, 0, sizeof(my_addr));
1132 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1133 if (ret == -1) return ret;
1137 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1138 parent_si->family, addr, addrlen);
1144 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1145 memset(child_si, 0, sizeof(*child_si));
1148 child_si->family = parent_si->family;
1149 child_si->type = parent_si->type;
1150 child_si->protocol = parent_si->protocol;
1151 child_si->bound = 1;
1152 child_si->is_server = 1;
1154 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1161 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1162 child_si->family, &my_addr, &my_addrlen);
1169 child_si->myname_len = my_addrlen;
1170 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1172 child_si->peername_len = *addrlen;
1173 child_si->peername = sockaddr_dup(addr, *addrlen);
1175 SWRAP_DLIST_ADD(sockets, child_si);
1177 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1178 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1179 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1184 static int autobind_start_init;
1185 static int autobind_start;
1187 /* using sendto() or connect() on an unbound socket would give the
1188 recipient no way to reply, as unlike UDP and TCP, a unix domain
1189 socket can't auto-assign emphemeral port numbers, so we need to
1191 static int swrap_auto_bind(struct socket_info *si)
1193 struct sockaddr_un un_addr;
1194 struct sockaddr_in in;
1201 if (autobind_start_init != 1) {
1202 autobind_start_init = 1;
1203 autobind_start = getpid();
1204 autobind_start %= 50000;
1205 autobind_start += 10000;
1208 un_addr.sun_family = AF_UNIX;
1212 type = SOCKET_TYPE_CHAR_TCP;
1215 type = SOCKET_TYPE_CHAR_UDP;
1218 errno = ESOCKTNOSUPPORT;
1222 if (autobind_start > 60000) {
1223 autobind_start = 10000;
1226 for (i=0;i<1000;i++) {
1227 port = autobind_start + i;
1228 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1229 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1230 type, socket_wrapper_default_iface(), port);
1231 if (stat(un_addr.sun_path, &st) == 0) continue;
1233 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1234 if (ret == -1) return ret;
1236 si->tmp_path = strdup(un_addr.sun_path);
1238 autobind_start = port + 1;
1246 memset(&in, 0, sizeof(in));
1247 in.sin_family = AF_INET;
1248 in.sin_port = htons(port);
1249 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1251 si->myname_len = sizeof(in);
1252 si->myname = sockaddr_dup(&in, si->myname_len);
1257 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1260 struct sockaddr_un un_addr;
1261 struct socket_info *si = find_socket_info(s);
1264 return real_connect(s, serv_addr, addrlen);
1267 if (si->bound == 0) {
1268 ret = swrap_auto_bind(si);
1269 if (ret == -1) return -1;
1272 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1273 if (ret == -1) return -1;
1275 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1277 ret = real_connect(s, (struct sockaddr *)&un_addr,
1278 sizeof(struct sockaddr_un));
1280 /* to give better errors */
1281 if (ret == -1 && errno == ENOENT) {
1282 errno = EHOSTUNREACH;
1286 si->peername_len = addrlen;
1287 si->peername = sockaddr_dup(serv_addr, addrlen);
1289 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1290 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1292 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1298 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1301 struct sockaddr_un un_addr;
1302 struct socket_info *si = find_socket_info(s);
1305 return real_bind(s, myaddr, addrlen);
1308 si->myname_len = addrlen;
1309 si->myname = sockaddr_dup(myaddr, addrlen);
1311 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1312 if (ret == -1) return -1;
1314 unlink(un_addr.sun_path);
1316 ret = real_bind(s, (struct sockaddr *)&un_addr,
1317 sizeof(struct sockaddr_un));
1326 _PUBLIC_ int swrap_listen(int s, int backlog)
1329 struct socket_info *si = find_socket_info(s);
1332 return real_listen(s, backlog);
1335 ret = real_listen(s, backlog);
1340 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1342 struct socket_info *si = find_socket_info(s);
1345 return real_getpeername(s, name, addrlen);
1354 memcpy(name, si->peername, si->peername_len);
1355 *addrlen = si->peername_len;
1360 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1362 struct socket_info *si = find_socket_info(s);
1365 return real_getsockname(s, name, addrlen);
1368 memcpy(name, si->myname, si->myname_len);
1369 *addrlen = si->myname_len;
1374 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1376 struct socket_info *si = find_socket_info(s);
1379 return real_getsockopt(s, level, optname, optval, optlen);
1382 if (level == SOL_SOCKET) {
1383 return real_getsockopt(s, level, optname, optval, optlen);
1386 errno = ENOPROTOOPT;
1390 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1392 struct socket_info *si = find_socket_info(s);
1395 return real_setsockopt(s, level, optname, optval, optlen);
1398 if (level == SOL_SOCKET) {
1399 return real_setsockopt(s, level, optname, optval, optlen);
1402 switch (si->family) {
1406 errno = ENOPROTOOPT;
1411 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1413 struct sockaddr_un un_addr;
1414 socklen_t un_addrlen = sizeof(un_addr);
1416 struct socket_info *si = find_socket_info(s);
1419 return real_recvfrom(s, buf, len, flags, from, fromlen);
1422 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1423 memset(&un_addr, 0, sizeof(un_addr));
1424 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1428 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1429 si->family, from, fromlen) == -1) {
1433 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1439 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1441 struct sockaddr_un un_addr;
1443 struct socket_info *si = find_socket_info(s);
1447 return real_sendto(s, buf, len, flags, to, tolen);
1450 if (si->bound == 0) {
1451 ret = swrap_auto_bind(si);
1452 if (ret == -1) return -1;
1455 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1456 if (ret == -1) return -1;
1461 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1464 type = SOCKET_TYPE_CHAR_UDP;
1466 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1467 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1468 socket_wrapper_dir(), type, iface, prt);
1469 if (stat(un_addr.sun_path, &st) != 0) continue;
1471 /* ignore the any errors in broadcast sends */
1472 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1475 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1480 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1482 /* to give better errors */
1483 if (ret == -1 && errno == ENOENT) {
1484 errno = EHOSTUNREACH;
1488 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1489 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1491 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1497 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1500 struct socket_info *si = find_socket_info(s);
1504 return real_ioctl(s, r, p);
1507 ret = real_ioctl(s, r, p);
1511 value = *((int *)p);
1512 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1513 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1514 } else if (value == 0) { /* END OF FILE */
1515 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1523 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1526 struct socket_info *si = find_socket_info(s);
1529 return real_recv(s, buf, len, flags);
1532 ret = real_recv(s, buf, len, flags);
1533 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1534 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1535 } else if (ret == 0) { /* END OF FILE */
1536 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1538 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1545 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1548 struct socket_info *si = find_socket_info(s);
1551 return real_send(s, buf, len, flags);
1554 ret = real_send(s, buf, len, flags);
1557 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1558 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1560 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1566 _PUBLIC_ int swrap_close(int fd)
1568 struct socket_info *si = find_socket_info(fd);
1572 return real_close(fd);
1575 SWRAP_DLIST_REMOVE(sockets, si);
1577 if (si->myname && si->peername) {
1578 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1581 ret = real_close(fd);
1583 if (si->myname && si->peername) {
1584 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1585 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1588 if (si->path) free(si->path);
1589 if (si->myname) free(si->myname);
1590 if (si->peername) free(si->peername);
1592 unlink(si->tmp_path);