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>
66 #include <netinet/in.h>
67 #include <netinet/tcp.h>
75 #define SWRAP_DLIST_ADD(list,item) do { \
77 (item)->prev = NULL; \
78 (item)->next = NULL; \
81 (item)->prev = NULL; \
82 (item)->next = (list); \
83 (list)->prev = (item); \
88 #define SWRAP_DLIST_REMOVE(list,item) do { \
89 if ((list) == (item)) { \
90 (list) = (item)->next; \
92 (list)->prev = NULL; \
96 (item)->prev->next = (item)->next; \
99 (item)->next->prev = (item)->prev; \
102 (item)->prev = NULL; \
103 (item)->next = NULL; \
106 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
108 #define REWRITE_CALLS
111 #define real_accept accept
112 #define real_connect connect
113 #define real_bind bind
114 #define real_listen listen
115 #define real_getpeername getpeername
116 #define real_getsockname getsockname
117 #define real_getsockopt getsockopt
118 #define real_setsockopt setsockopt
119 #define real_recvfrom recvfrom
120 #define real_sendto sendto
121 #define real_ioctl ioctl
122 #define real_recv recv
123 #define real_send send
124 #define real_socket socket
125 #define real_close close
128 #ifdef HAVE_GETTIMEOFDAY_TZ
129 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
131 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
134 /* we need to use a very terse format here as IRIX 6.4 silently
135 truncates names to 16 chars, so if we use a longer name then we
136 can't tell which port a packet came from with recvfrom()
138 with this format we have 8 chars left for the directory name
140 #define SOCKET_FORMAT "%c%02X%04X"
141 #define SOCKET_TYPE_CHAR_TCP 'T'
142 #define SOCKET_TYPE_CHAR_UDP 'U'
144 #define MAX_WRAPPED_INTERFACES 16
146 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
148 struct sockaddr *ret = (struct sockaddr *)malloc(len);
149 memcpy(ret, data, len);
167 struct sockaddr *myname;
168 socklen_t myname_len;
170 struct sockaddr *peername;
171 socklen_t peername_len;
174 unsigned long pck_snd;
175 unsigned long pck_rcv;
178 struct socket_info *prev, *next;
181 static struct socket_info *sockets;
184 static const char *socket_wrapper_dir(void)
186 const char *s = getenv("SOCKET_WRAPPER_DIR");
190 if (strncmp(s, "./", 2) == 0) {
196 static unsigned int socket_wrapper_default_iface(void)
198 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
201 if (sscanf(s, "%u", &iface) == 1) {
202 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
208 return 1;/* 127.0.0.1 */
211 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
218 if ((*len) < sizeof(struct sockaddr_in)) {
222 p = strrchr(un->sun_path, '/');
223 if (p) p++; else p = un->sun_path;
225 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
230 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
235 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
245 in->sin_family = AF_INET;
246 in->sin_addr.s_addr = htonl((127<<24) | iface);
247 in->sin_port = htons(prt);
249 *len = sizeof(struct sockaddr_in);
253 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
260 unsigned int addr= ntohl(in->sin_addr.s_addr);
261 unsigned int prt = ntohs(in->sin_port);
265 if (bcast) *bcast = 0;
274 u_type = SOCKET_TYPE_CHAR_TCP;
277 u_type = SOCKET_TYPE_CHAR_UDP;
278 a_type = SOCKET_TYPE_CHAR_UDP;
279 b_type = SOCKET_TYPE_CHAR_UDP;
283 if (a_type && addr == 0xFFFFFFFF) {
284 /* 255.255.255.255 only udp */
287 iface = socket_wrapper_default_iface();
288 } else if (b_type && addr == 0x7FFFFFFF) {
289 /* 127.255.255.255 only udp */
292 iface = socket_wrapper_default_iface();
293 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
297 iface = (addr & 0x000000FF);
303 if (bcast) *bcast = is_bcast;
306 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
307 socket_wrapper_dir());
308 /* the caller need to do more processing */
312 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
313 socket_wrapper_dir(), type, iface, prt);
318 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
326 unsigned int addr= ntohl(in->sin_addr.s_addr);
327 unsigned int prt = ntohs(in->sin_port);
332 if (bcast) *bcast = 0;
336 u_type = SOCKET_TYPE_CHAR_TCP;
337 d_type = SOCKET_TYPE_CHAR_TCP;
340 u_type = SOCKET_TYPE_CHAR_UDP;
341 d_type = SOCKET_TYPE_CHAR_UDP;
342 a_type = SOCKET_TYPE_CHAR_UDP;
343 b_type = SOCKET_TYPE_CHAR_UDP;
351 iface = socket_wrapper_default_iface();
352 } else if (a_type && addr == 0xFFFFFFFF) {
353 /* 255.255.255.255 only udp */
356 iface = socket_wrapper_default_iface();
357 } else if (b_type && addr == 0x7FFFFFFF) {
358 /* 127.255.255.255 only udp */
361 iface = socket_wrapper_default_iface();
362 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
366 iface = (addr & 0x000000FF);
368 errno = EADDRNOTAVAIL;
372 if (bcast) *bcast = is_bcast;
375 /* handle auto-allocation of ephemeral ports */
376 for (prt = 5001; prt < 10000; prt++) {
377 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
378 socket_wrapper_dir(), type, iface, prt);
379 if (stat(un->sun_path, &st) == 0) continue;
381 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
388 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
389 socket_wrapper_dir(), type, iface, prt);
393 static struct socket_info *find_socket_info(int fd)
395 struct socket_info *i;
396 for (i = sockets; i; i = i->next) {
404 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
405 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
410 out_addr->sun_family = AF_UNIX;
412 switch (in_addr->sa_family) {
419 errno = ESOCKTNOSUPPORT;
423 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
425 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
431 errno = EAFNOSUPPORT;
435 static int sockaddr_convert_from_un(const struct socket_info *si,
436 const struct sockaddr_un *in_addr,
437 socklen_t un_addrlen,
439 struct sockaddr *out_addr,
440 socklen_t *_out_addrlen)
442 socklen_t out_addrlen;
444 if (out_addr == NULL || _out_addrlen == NULL)
447 if (un_addrlen == 0) {
452 out_addrlen = *_out_addrlen;
453 if (out_addrlen > un_addrlen) {
454 out_addrlen = un_addrlen;
464 errno = ESOCKTNOSUPPORT;
467 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
472 errno = EAFNOSUPPORT;
476 enum swrap_packet_type {
478 SWRAP_CONNECT_UNREACH,
486 SWRAP_SENDTO_UNREACH,
497 struct swrap_file_hdr {
499 unsigned short version_major;
500 unsigned short version_minor;
502 unsigned long sigfigs;
503 unsigned long frame_max_len;
504 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
505 unsigned long link_type;
507 #define SWRAP_FILE_HDR_SIZE 24
509 struct swrap_packet {
511 unsigned long seconds;
512 unsigned long micro_seconds;
513 unsigned long recorded_length;
514 unsigned long full_length;
516 #define SWRAP_PACKET__FRAME_SIZE 16
520 unsigned char ver_hdrlen;
522 unsigned short packet_length;
523 unsigned short identification;
525 unsigned char fragment;
527 unsigned char protocol;
528 unsigned short hdr_checksum;
529 unsigned long src_addr;
530 unsigned long dest_addr;
532 #define SWRAP_PACKET__IP_HDR_SIZE 20
536 unsigned short source_port;
537 unsigned short dest_port;
538 unsigned long seq_num;
539 unsigned long ack_num;
540 unsigned char hdr_length;
541 unsigned char control;
542 unsigned short window;
543 unsigned short checksum;
546 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
548 unsigned short source_port;
549 unsigned short dest_port;
550 unsigned short length;
551 unsigned short checksum;
553 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
557 unsigned short checksum;
558 unsigned long unused;
560 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
564 #define SWRAP_PACKET_SIZE 56
566 static const char *socket_wrapper_pcap_file(void)
568 static int initialized = 0;
569 static const char *s = NULL;
570 static const struct swrap_file_hdr h;
571 static const struct swrap_packet p;
573 if (initialized == 1) {
579 * TODO: don't use the structs use plain buffer offsets
580 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
582 * for now make sure we disable PCAP support
583 * if the struct has alignment!
585 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
588 if (sizeof(p) != SWRAP_PACKET_SIZE) {
591 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
594 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
597 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
600 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
603 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
607 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
611 if (strncmp(s, "./", 2) == 0) {
617 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
618 const struct sockaddr_in *src_addr,
619 const struct sockaddr_in *dest_addr,
621 const unsigned char *payload,
623 unsigned long tcp_seq,
624 unsigned long tcp_ack,
625 unsigned char tcp_ctl,
629 struct swrap_packet *ret;
630 struct swrap_packet *packet;
633 size_t nonwire_len = sizeof(packet->frame);
634 size_t wire_hdr_len = 0;
636 size_t icmp_hdr_len = 0;
637 size_t icmp_truncate_len = 0;
638 unsigned char protocol = 0, icmp_protocol = 0;
639 unsigned short src_port = src_addr->sin_port;
640 unsigned short dest_port = dest_addr->sin_port;
642 switch (socket_type) {
644 protocol = 0x06; /* TCP */
645 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
646 wire_len = wire_hdr_len + payload_len;
650 protocol = 0x11; /* UDP */
651 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
652 wire_len = wire_hdr_len + payload_len;
657 icmp_protocol = protocol;
658 protocol = 0x01; /* ICMP */
659 if (wire_len > 64 ) {
660 icmp_truncate_len = wire_len - 64;
662 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
663 wire_hdr_len += icmp_hdr_len;
664 wire_len += icmp_hdr_len;
667 packet_len = nonwire_len + wire_len;
668 alloc_len = packet_len;
669 if (alloc_len < sizeof(struct swrap_packet)) {
670 alloc_len = sizeof(struct swrap_packet);
672 ret = (struct swrap_packet *)malloc(alloc_len);
673 if (!ret) return NULL;
677 packet->frame.seconds = tval->tv_sec;
678 packet->frame.micro_seconds = tval->tv_usec;
679 packet->frame.recorded_length = wire_len - icmp_truncate_len;
680 packet->frame.full_length = wire_len - icmp_truncate_len;
682 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
683 packet->ip.hdr.tos = 0x00;
684 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
685 packet->ip.hdr.identification = htons(0xFFFF);
686 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
687 packet->ip.hdr.fragment = htons(0x0000);
688 packet->ip.hdr.ttl = 0xFF;
689 packet->ip.hdr.protocol = protocol;
690 packet->ip.hdr.hdr_checksum = htons(0x0000);
691 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
692 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
695 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
696 packet->ip.p.icmp.code = 0x01; /* host unreachable */
697 packet->ip.p.icmp.checksum = htons(0x0000);
698 packet->ip.p.icmp.unused = htonl(0x00000000);
700 /* set the ip header in the ICMP payload */
701 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
702 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
703 packet->ip.hdr.tos = 0x00;
704 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
705 packet->ip.hdr.identification = htons(0xFFFF);
706 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
707 packet->ip.hdr.fragment = htons(0x0000);
708 packet->ip.hdr.ttl = 0xFF;
709 packet->ip.hdr.protocol = icmp_protocol;
710 packet->ip.hdr.hdr_checksum = htons(0x0000);
711 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
712 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
714 src_port = dest_addr->sin_port;
715 dest_port = src_addr->sin_port;
718 switch (socket_type) {
720 packet->ip.p.tcp.source_port = src_port;
721 packet->ip.p.tcp.dest_port = dest_port;
722 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
723 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
724 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
725 packet->ip.p.tcp.control = tcp_ctl;
726 packet->ip.p.tcp.window = htons(0x7FFF);
727 packet->ip.p.tcp.checksum = htons(0x0000);
728 packet->ip.p.tcp.urg = htons(0x0000);
733 packet->ip.p.udp.source_port = src_addr->sin_port;
734 packet->ip.p.udp.dest_port = dest_addr->sin_port;
735 packet->ip.p.udp.length = htons(8 + payload_len);
736 packet->ip.p.udp.checksum = htons(0x0000);
741 if (payload && payload_len > 0) {
742 unsigned char *p = (unsigned char *)ret;
745 memcpy(p, payload, payload_len);
748 *_packet_len = packet_len - icmp_truncate_len;
752 static int swrap_get_pcap_fd(const char *fname)
756 if (fd != -1) return fd;
758 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
760 struct swrap_file_hdr file_hdr;
761 file_hdr.magic = 0xA1B2C3D4;
762 file_hdr.version_major = 0x0002;
763 file_hdr.version_minor = 0x0004;
764 file_hdr.timezone = 0x00000000;
765 file_hdr.sigfigs = 0x00000000;
766 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
767 file_hdr.link_type = 0x0065; /* 101 RAW IP */
769 write(fd, &file_hdr, sizeof(file_hdr));
773 fd = open(fname, O_WRONLY|O_APPEND, 0644);
778 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
779 enum swrap_packet_type type,
780 const void *buf, size_t len)
782 const struct sockaddr_in *src_addr;
783 const struct sockaddr_in *dest_addr;
784 const char *file_name;
785 unsigned long tcp_seq = 0;
786 unsigned long tcp_ack = 0;
787 unsigned char tcp_ctl = 0;
790 struct swrap_packet *packet;
791 size_t packet_len = 0;
794 file_name = socket_wrapper_pcap_file();
799 if (si->family != AF_INET) {
804 case SWRAP_CONNECT_SEND:
805 if (si->type != SOCK_STREAM) return;
807 src_addr = (const struct sockaddr_in *)si->myname;
808 dest_addr = (const struct sockaddr_in *)addr;
810 tcp_seq = si->io.pck_snd;
811 tcp_ack = si->io.pck_rcv;
812 tcp_ctl = 0x02; /* SYN */
818 case SWRAP_CONNECT_RECV:
819 if (si->type != SOCK_STREAM) return;
821 dest_addr = (const struct sockaddr_in *)si->myname;
822 src_addr = (const struct sockaddr_in *)addr;
824 tcp_seq = si->io.pck_rcv;
825 tcp_ack = si->io.pck_snd;
826 tcp_ctl = 0x12; /** SYN,ACK */
832 case SWRAP_CONNECT_UNREACH:
833 if (si->type != SOCK_STREAM) return;
835 dest_addr = (const struct sockaddr_in *)si->myname;
836 src_addr = (const struct sockaddr_in *)addr;
838 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
839 tcp_seq = si->io.pck_snd - 1;
840 tcp_ack = si->io.pck_rcv;
841 tcp_ctl = 0x02; /* SYN */
846 case SWRAP_CONNECT_ACK:
847 if (si->type != SOCK_STREAM) return;
849 src_addr = (const struct sockaddr_in *)si->myname;
850 dest_addr = (const struct sockaddr_in *)addr;
852 tcp_seq = si->io.pck_snd;
853 tcp_ack = si->io.pck_rcv;
854 tcp_ctl = 0x10; /* ACK */
858 case SWRAP_ACCEPT_SEND:
859 if (si->type != SOCK_STREAM) return;
861 dest_addr = (const struct sockaddr_in *)si->myname;
862 src_addr = (const struct sockaddr_in *)addr;
864 tcp_seq = si->io.pck_rcv;
865 tcp_ack = si->io.pck_snd;
866 tcp_ctl = 0x02; /* SYN */
872 case SWRAP_ACCEPT_RECV:
873 if (si->type != SOCK_STREAM) return;
875 src_addr = (const struct sockaddr_in *)si->myname;
876 dest_addr = (const struct sockaddr_in *)addr;
878 tcp_seq = si->io.pck_snd;
879 tcp_ack = si->io.pck_rcv;
880 tcp_ctl = 0x12; /* SYN,ACK */
886 case SWRAP_ACCEPT_ACK:
887 if (si->type != SOCK_STREAM) return;
889 dest_addr = (const struct sockaddr_in *)si->myname;
890 src_addr = (const struct sockaddr_in *)addr;
892 tcp_seq = si->io.pck_rcv;
893 tcp_ack = si->io.pck_snd;
894 tcp_ctl = 0x10; /* ACK */
899 src_addr = (const struct sockaddr_in *)si->myname;
900 dest_addr = (const struct sockaddr_in *)si->peername;
902 tcp_seq = si->io.pck_snd;
903 tcp_ack = si->io.pck_rcv;
904 tcp_ctl = 0x18; /* PSH,ACK */
906 si->io.pck_snd += len;
911 dest_addr = (const struct sockaddr_in *)si->myname;
912 src_addr = (const struct sockaddr_in *)si->peername;
914 if (si->type == SOCK_DGRAM) {
915 swrap_dump_packet(si, si->peername,
916 SWRAP_SENDTO_UNREACH,
921 tcp_seq = si->io.pck_rcv;
922 tcp_ack = si->io.pck_snd;
923 tcp_ctl = 0x14; /** RST,ACK */
927 case SWRAP_PENDING_RST:
928 dest_addr = (const struct sockaddr_in *)si->myname;
929 src_addr = (const struct sockaddr_in *)si->peername;
931 if (si->type == SOCK_DGRAM) {
935 tcp_seq = si->io.pck_rcv;
936 tcp_ack = si->io.pck_snd;
937 tcp_ctl = 0x14; /* RST,ACK */
942 dest_addr = (const struct sockaddr_in *)si->myname;
943 src_addr = (const struct sockaddr_in *)si->peername;
945 tcp_seq = si->io.pck_rcv;
946 tcp_ack = si->io.pck_snd;
947 tcp_ctl = 0x18; /* PSH,ACK */
949 si->io.pck_rcv += len;
954 dest_addr = (const struct sockaddr_in *)si->myname;
955 src_addr = (const struct sockaddr_in *)si->peername;
957 if (si->type == SOCK_DGRAM) {
961 tcp_seq = si->io.pck_rcv;
962 tcp_ack = si->io.pck_snd;
963 tcp_ctl = 0x14; /* RST,ACK */
968 src_addr = (const struct sockaddr_in *)si->myname;
969 dest_addr = (const struct sockaddr_in *)addr;
971 si->io.pck_snd += len;
975 case SWRAP_SENDTO_UNREACH:
976 dest_addr = (const struct sockaddr_in *)si->myname;
977 src_addr = (const struct sockaddr_in *)addr;
984 dest_addr = (const struct sockaddr_in *)si->myname;
985 src_addr = (const struct sockaddr_in *)addr;
987 si->io.pck_rcv += len;
991 case SWRAP_CLOSE_SEND:
992 if (si->type != SOCK_STREAM) return;
994 src_addr = (const struct sockaddr_in *)si->myname;
995 dest_addr = (const struct sockaddr_in *)si->peername;
997 tcp_seq = si->io.pck_snd;
998 tcp_ack = si->io.pck_rcv;
999 tcp_ctl = 0x11; /* FIN, ACK */
1001 si->io.pck_snd += 1;
1005 case SWRAP_CLOSE_RECV:
1006 if (si->type != SOCK_STREAM) return;
1008 dest_addr = (const struct sockaddr_in *)si->myname;
1009 src_addr = (const struct sockaddr_in *)si->peername;
1011 tcp_seq = si->io.pck_rcv;
1012 tcp_ack = si->io.pck_snd;
1013 tcp_ctl = 0x11; /* FIN,ACK */
1015 si->io.pck_rcv += 1;
1019 case SWRAP_CLOSE_ACK:
1020 if (si->type != SOCK_STREAM) return;
1022 src_addr = (const struct sockaddr_in *)si->myname;
1023 dest_addr = (const struct sockaddr_in *)si->peername;
1025 tcp_seq = si->io.pck_snd;
1026 tcp_ack = si->io.pck_rcv;
1027 tcp_ctl = 0x10; /* ACK */
1034 swrapGetTimeOfDay(&tv);
1036 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1037 (const unsigned char *)buf, len,
1038 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1044 fd = swrap_get_pcap_fd(file_name);
1046 write(fd, packet, packet_len);
1052 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1054 struct socket_info *si;
1057 if (!socket_wrapper_dir()) {
1058 return real_socket(family, type, protocol);
1065 return real_socket(family, type, protocol);
1067 errno = EAFNOSUPPORT;
1077 errno = EPROTONOSUPPORT;
1085 errno = EPROTONOSUPPORT;
1089 fd = real_socket(AF_UNIX, type, 0);
1091 if (fd == -1) return -1;
1093 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1095 si->family = family;
1097 si->protocol = protocol;
1100 SWRAP_DLIST_ADD(sockets, si);
1105 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1107 struct socket_info *parent_si, *child_si;
1109 struct sockaddr_un un_addr;
1110 socklen_t un_addrlen = sizeof(un_addr);
1111 struct sockaddr_un un_my_addr;
1112 socklen_t un_my_addrlen = sizeof(un_my_addr);
1113 struct sockaddr my_addr;
1114 socklen_t my_addrlen = sizeof(my_addr);
1117 parent_si = find_socket_info(s);
1119 return real_accept(s, addr, addrlen);
1122 memset(&un_addr, 0, sizeof(un_addr));
1123 memset(&un_my_addr, 0, sizeof(un_my_addr));
1124 memset(&my_addr, 0, sizeof(my_addr));
1126 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1127 if (ret == -1) return ret;
1131 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1132 parent_si->family, addr, addrlen);
1138 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1139 memset(child_si, 0, sizeof(*child_si));
1142 child_si->family = parent_si->family;
1143 child_si->type = parent_si->type;
1144 child_si->protocol = parent_si->protocol;
1145 child_si->bound = 1;
1146 child_si->is_server = 1;
1148 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1155 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1156 child_si->family, &my_addr, &my_addrlen);
1163 child_si->myname_len = my_addrlen;
1164 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1166 child_si->peername_len = *addrlen;
1167 child_si->peername = sockaddr_dup(addr, *addrlen);
1169 SWRAP_DLIST_ADD(sockets, child_si);
1171 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1172 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1173 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1178 static int autobind_start_init;
1179 static int autobind_start;
1181 /* using sendto() or connect() on an unbound socket would give the
1182 recipient no way to reply, as unlike UDP and TCP, a unix domain
1183 socket can't auto-assign emphemeral port numbers, so we need to
1185 static int swrap_auto_bind(struct socket_info *si)
1187 struct sockaddr_un un_addr;
1188 struct sockaddr_in in;
1195 if (autobind_start_init != 1) {
1196 autobind_start_init = 1;
1197 autobind_start = getpid();
1198 autobind_start %= 50000;
1199 autobind_start += 10000;
1202 un_addr.sun_family = AF_UNIX;
1206 type = SOCKET_TYPE_CHAR_TCP;
1209 type = SOCKET_TYPE_CHAR_UDP;
1212 errno = ESOCKTNOSUPPORT;
1216 if (autobind_start > 60000) {
1217 autobind_start = 10000;
1220 for (i=0;i<1000;i++) {
1221 port = autobind_start + i;
1222 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1223 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1224 type, socket_wrapper_default_iface(), port);
1225 if (stat(un_addr.sun_path, &st) == 0) continue;
1227 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1228 if (ret == -1) return ret;
1230 si->tmp_path = strdup(un_addr.sun_path);
1232 autobind_start = port + 1;
1240 memset(&in, 0, sizeof(in));
1241 in.sin_family = AF_INET;
1242 in.sin_port = htons(port);
1243 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1245 si->myname_len = sizeof(in);
1246 si->myname = sockaddr_dup(&in, si->myname_len);
1251 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1254 struct sockaddr_un un_addr;
1255 struct socket_info *si = find_socket_info(s);
1258 return real_connect(s, serv_addr, addrlen);
1261 if (si->bound == 0) {
1262 ret = swrap_auto_bind(si);
1263 if (ret == -1) return -1;
1266 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1267 if (ret == -1) return -1;
1269 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1271 ret = real_connect(s, (struct sockaddr *)&un_addr,
1272 sizeof(struct sockaddr_un));
1274 /* to give better errors */
1275 if (ret == -1 && errno == ENOENT) {
1276 errno = EHOSTUNREACH;
1280 si->peername_len = addrlen;
1281 si->peername = sockaddr_dup(serv_addr, addrlen);
1283 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1284 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1286 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1292 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1295 struct sockaddr_un un_addr;
1296 struct socket_info *si = find_socket_info(s);
1299 return real_bind(s, myaddr, addrlen);
1302 si->myname_len = addrlen;
1303 si->myname = sockaddr_dup(myaddr, addrlen);
1305 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1306 if (ret == -1) return -1;
1308 unlink(un_addr.sun_path);
1310 ret = real_bind(s, (struct sockaddr *)&un_addr,
1311 sizeof(struct sockaddr_un));
1320 _PUBLIC_ int swrap_listen(int s, int backlog)
1323 struct socket_info *si = find_socket_info(s);
1326 return real_listen(s, backlog);
1329 ret = real_listen(s, backlog);
1334 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1336 struct socket_info *si = find_socket_info(s);
1339 return real_getpeername(s, name, addrlen);
1348 memcpy(name, si->peername, si->peername_len);
1349 *addrlen = si->peername_len;
1354 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1356 struct socket_info *si = find_socket_info(s);
1359 return real_getsockname(s, name, addrlen);
1362 memcpy(name, si->myname, si->myname_len);
1363 *addrlen = si->myname_len;
1368 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1370 struct socket_info *si = find_socket_info(s);
1373 return real_getsockopt(s, level, optname, optval, optlen);
1376 if (level == SOL_SOCKET) {
1377 return real_getsockopt(s, level, optname, optval, optlen);
1380 errno = ENOPROTOOPT;
1384 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1386 struct socket_info *si = find_socket_info(s);
1389 return real_setsockopt(s, level, optname, optval, optlen);
1392 if (level == SOL_SOCKET) {
1393 return real_setsockopt(s, level, optname, optval, optlen);
1396 switch (si->family) {
1400 errno = ENOPROTOOPT;
1405 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1407 struct sockaddr_un un_addr;
1408 socklen_t un_addrlen = sizeof(un_addr);
1410 struct socket_info *si = find_socket_info(s);
1413 return real_recvfrom(s, buf, len, flags, from, fromlen);
1416 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1417 memset(&un_addr, 0, sizeof(un_addr));
1418 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1422 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1423 si->family, from, fromlen) == -1) {
1427 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1433 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1435 struct sockaddr_un un_addr;
1437 struct socket_info *si = find_socket_info(s);
1441 return real_sendto(s, buf, len, flags, to, tolen);
1444 if (si->bound == 0) {
1445 ret = swrap_auto_bind(si);
1446 if (ret == -1) return -1;
1449 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1450 if (ret == -1) return -1;
1455 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1458 type = SOCKET_TYPE_CHAR_UDP;
1460 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1461 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1462 socket_wrapper_dir(), type, iface, prt);
1463 if (stat(un_addr.sun_path, &st) != 0) continue;
1465 /* ignore the any errors in broadcast sends */
1466 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1469 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1474 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1476 /* to give better errors */
1477 if (ret == -1 && errno == ENOENT) {
1478 errno = EHOSTUNREACH;
1482 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1483 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1485 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1491 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1494 struct socket_info *si = find_socket_info(s);
1498 return real_ioctl(s, r, p);
1501 ret = real_ioctl(s, r, p);
1505 value = *((int *)p);
1506 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1507 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1508 } else if (value == 0) { /* END OF FILE */
1509 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1517 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1520 struct socket_info *si = find_socket_info(s);
1523 return real_recv(s, buf, len, flags);
1526 ret = real_recv(s, buf, len, flags);
1527 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1528 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1529 } else if (ret == 0) { /* END OF FILE */
1530 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1532 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1539 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1542 struct socket_info *si = find_socket_info(s);
1545 return real_send(s, buf, len, flags);
1548 ret = real_send(s, buf, len, flags);
1551 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1552 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1554 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1560 _PUBLIC_ int swrap_close(int fd)
1562 struct socket_info *si = find_socket_info(fd);
1566 return real_close(fd);
1569 SWRAP_DLIST_REMOVE(sockets, si);
1571 if (si->myname && si->peername) {
1572 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1575 ret = real_close(fd);
1577 if (si->myname && si->peername) {
1578 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1579 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1582 if (si->path) free(si->path);
1583 if (si->myname) free(si->myname);
1584 if (si->peername) free(si->peername);
1586 unlink(si->tmp_path);