r19136: No conflict, after "svn up" it applied correctly", merge 19126 from 3_0
[Samba.git] / source4 / lib / socket_wrapper / socket_wrapper.c
blob9915789f0b506b4fb5c8ea37b86d8ed13a94d990
1 /*
2 Socket wrapper library. Passes all socket communication over
3 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
4 is set.
5 Copyright (C) Jelmer Vernooij 2005
6 Copyright (C) Stefan Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #ifdef _SAMBA_BUILD_
25 #define SOCKET_WRAPPER_NOT_REPLACE
26 #include "includes.h"
27 #include "system/network.h"
28 #include "system/filesys.h"
30 #ifndef _DLINKLIST_H
31 #include "lib/util/dlinklist.h"
32 #endif
34 #ifdef malloc
35 #undef malloc
36 #endif
37 #ifdef calloc
38 #undef calloc
39 #endif
40 #ifdef strdup
41 #undef strdup
42 #endif
44 #else /* _SAMBA_BUILD_ */
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <errno.h>
50 #include <sys/un.h>
51 #include <netinet/in.h>
52 #include <netinet/tcp.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <string.h>
56 #include <stdio.h>
58 #error "dlinklist.h missing"
60 #endif
62 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
63 * for now */
64 #define REWRITE_CALLS
66 #ifdef REWRITE_CALLS
67 #define real_accept accept
68 #define real_connect connect
69 #define real_bind bind
70 #define real_listen listen
71 #define real_getpeername getpeername
72 #define real_getsockname getsockname
73 #define real_getsockopt getsockopt
74 #define real_setsockopt setsockopt
75 #define real_recvfrom recvfrom
76 #define real_sendto sendto
77 #define real_ioctl ioctl
78 #define real_recv recv
79 #define real_send send
80 #define real_socket socket
81 #define real_close close
82 #endif
84 #ifdef HAVE_GETTIMEOFDAY_TZ
85 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
86 #else
87 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
88 #endif
90 /* we need to use a very terse format here as IRIX 6.4 silently
91 truncates names to 16 chars, so if we use a longer name then we
92 can't tell which port a packet came from with recvfrom()
94 with this format we have 8 chars left for the directory name
96 #define SOCKET_FORMAT "%c%02X%04X"
97 #define SOCKET_TYPE_CHAR_TCP 'T'
98 #define SOCKET_TYPE_CHAR_UDP 'U'
100 #define MAX_WRAPPED_INTERFACES 16
102 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
104 struct sockaddr *ret = (struct sockaddr *)malloc(len);
105 memcpy(ret, data, len);
106 return ret;
109 struct socket_info
111 int fd;
113 int family;
114 int type;
115 int protocol;
116 int bound;
117 int bcast;
118 int is_server;
120 char *path;
121 char *tmp_path;
123 struct sockaddr *myname;
124 socklen_t myname_len;
126 struct sockaddr *peername;
127 socklen_t peername_len;
129 struct {
130 unsigned long pck_snd;
131 unsigned long pck_rcv;
132 } io;
134 struct socket_info *prev, *next;
137 static struct socket_info *sockets;
140 static const char *socket_wrapper_dir(void)
142 const char *s = getenv("SOCKET_WRAPPER_DIR");
143 if (s == NULL) {
144 return NULL;
146 if (strncmp(s, "./", 2) == 0) {
147 s += 2;
149 return s;
152 static unsigned int socket_wrapper_default_iface(void)
154 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
155 if (s) {
156 unsigned int iface;
157 if (sscanf(s, "%u", &iface) == 1) {
158 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
159 return iface;
164 return 1;/* 127.0.0.1 */
167 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
169 unsigned int iface;
170 unsigned int prt;
171 const char *p;
172 char type;
174 if ((*len) < sizeof(struct sockaddr_in)) {
175 return 0;
178 p = strrchr(un->sun_path, '/');
179 if (p) p++; else p = un->sun_path;
181 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
182 errno = EINVAL;
183 return -1;
186 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
187 errno = EINVAL;
188 return -1;
191 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
192 errno = EINVAL;
193 return -1;
196 if (prt > 0xFFFF) {
197 errno = EINVAL;
198 return -1;
201 in->sin_family = AF_INET;
202 in->sin_addr.s_addr = htonl((127<<24) | iface);
203 in->sin_port = htons(prt);
205 *len = sizeof(struct sockaddr_in);
206 return 0;
209 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
210 int *bcast)
212 char u_type = '\0';
213 char b_type = '\0';
214 char a_type = '\0';
215 char type = '\0';
216 unsigned int addr= ntohl(in->sin_addr.s_addr);
217 unsigned int prt = ntohs(in->sin_port);
218 unsigned int iface;
219 int is_bcast = 0;
221 if (bcast) *bcast = 0;
223 if (prt == 0) {
224 errno = EINVAL;
225 return -1;
228 switch (si->type) {
229 case SOCK_STREAM:
230 u_type = SOCKET_TYPE_CHAR_TCP;
231 break;
232 case SOCK_DGRAM:
233 u_type = SOCKET_TYPE_CHAR_UDP;
234 a_type = SOCKET_TYPE_CHAR_UDP;
235 b_type = SOCKET_TYPE_CHAR_UDP;
236 break;
239 if (a_type && addr == 0xFFFFFFFF) {
240 /* 255.255.255.255 only udp */
241 is_bcast = 2;
242 type = a_type;
243 iface = socket_wrapper_default_iface();
244 } else if (b_type && addr == 0x7FFFFFFF) {
245 /* 127.255.255.255 only udp */
246 is_bcast = 1;
247 type = b_type;
248 iface = socket_wrapper_default_iface();
249 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
250 /* 127.0.0.X */
251 is_bcast = 0;
252 type = u_type;
253 iface = (addr & 0x000000FF);
254 } else {
255 errno = ENETUNREACH;
256 return -1;
259 if (bcast) *bcast = is_bcast;
261 if (is_bcast) {
262 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
263 socket_wrapper_dir());
264 /* the caller need to do more processing */
265 return 0;
268 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
269 socket_wrapper_dir(), type, iface, prt);
271 return 0;
274 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
275 int *bcast)
277 char u_type = '\0';
278 char d_type = '\0';
279 char b_type = '\0';
280 char a_type = '\0';
281 char type = '\0';
282 unsigned int addr= ntohl(in->sin_addr.s_addr);
283 unsigned int prt = ntohs(in->sin_port);
284 unsigned int iface;
285 struct stat st;
286 int is_bcast = 0;
288 if (bcast) *bcast = 0;
290 switch (si->type) {
291 case SOCK_STREAM:
292 u_type = SOCKET_TYPE_CHAR_TCP;
293 d_type = SOCKET_TYPE_CHAR_TCP;
294 break;
295 case SOCK_DGRAM:
296 u_type = SOCKET_TYPE_CHAR_UDP;
297 d_type = SOCKET_TYPE_CHAR_UDP;
298 a_type = SOCKET_TYPE_CHAR_UDP;
299 b_type = SOCKET_TYPE_CHAR_UDP;
300 break;
303 if (addr == 0) {
304 /* 0.0.0.0 */
305 is_bcast = 0;
306 type = d_type;
307 iface = socket_wrapper_default_iface();
308 } else if (a_type && addr == 0xFFFFFFFF) {
309 /* 255.255.255.255 only udp */
310 is_bcast = 2;
311 type = a_type;
312 iface = socket_wrapper_default_iface();
313 } else if (b_type && addr == 0x7FFFFFFF) {
314 /* 127.255.255.255 only udp */
315 is_bcast = 1;
316 type = b_type;
317 iface = socket_wrapper_default_iface();
318 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
319 /* 127.0.0.X */
320 is_bcast = 0;
321 type = u_type;
322 iface = (addr & 0x000000FF);
323 } else {
324 errno = EADDRNOTAVAIL;
325 return -1;
328 if (bcast) *bcast = is_bcast;
330 if (prt == 0) {
331 /* handle auto-allocation of ephemeral ports */
332 for (prt = 5001; prt < 10000; prt++) {
333 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
334 socket_wrapper_dir(), type, iface, prt);
335 if (stat(un->sun_path, &st) == 0) continue;
337 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
338 return 0;
340 errno = ENFILE;
341 return -1;
344 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
345 socket_wrapper_dir(), type, iface, prt);
346 return 0;
349 static struct socket_info *find_socket_info(int fd)
351 struct socket_info *i;
352 for (i = sockets; i; i = i->next) {
353 if (i->fd == fd)
354 return i;
357 return NULL;
360 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
361 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
363 if (!out_addr)
364 return 0;
366 out_addr->sun_family = AF_UNIX;
368 switch (in_addr->sa_family) {
369 case AF_INET:
370 switch (si->type) {
371 case SOCK_STREAM:
372 case SOCK_DGRAM:
373 break;
374 default:
375 errno = ESOCKTNOSUPPORT;
376 return -1;
378 if (alloc_sock) {
379 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
380 } else {
381 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
383 default:
384 break;
387 errno = EAFNOSUPPORT;
388 return -1;
391 static int sockaddr_convert_from_un(const struct socket_info *si,
392 const struct sockaddr_un *in_addr,
393 socklen_t un_addrlen,
394 int family,
395 struct sockaddr *out_addr,
396 socklen_t *_out_addrlen)
398 socklen_t out_addrlen;
400 if (out_addr == NULL || _out_addrlen == NULL)
401 return 0;
403 if (un_addrlen == 0) {
404 *_out_addrlen = 0;
405 return 0;
408 out_addrlen = *_out_addrlen;
409 if (out_addrlen > un_addrlen) {
410 out_addrlen = un_addrlen;
413 switch (family) {
414 case AF_INET:
415 switch (si->type) {
416 case SOCK_STREAM:
417 case SOCK_DGRAM:
418 break;
419 default:
420 errno = ESOCKTNOSUPPORT;
421 return -1;
423 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
424 default:
425 break;
428 errno = EAFNOSUPPORT;
429 return -1;
432 enum swrap_packet_type {
433 SWRAP_CONNECT_SEND,
434 SWRAP_CONNECT_UNREACH,
435 SWRAP_CONNECT_RECV,
436 SWRAP_CONNECT_ACK,
437 SWRAP_ACCEPT_SEND,
438 SWRAP_ACCEPT_RECV,
439 SWRAP_ACCEPT_ACK,
440 SWRAP_RECVFROM,
441 SWRAP_SENDTO,
442 SWRAP_SENDTO_UNREACH,
443 SWRAP_PENDING_RST,
444 SWRAP_RECV,
445 SWRAP_RECV_RST,
446 SWRAP_SEND,
447 SWRAP_SEND_RST,
448 SWRAP_CLOSE_SEND,
449 SWRAP_CLOSE_RECV,
450 SWRAP_CLOSE_ACK
453 struct swrap_file_hdr {
454 unsigned long magic;
455 unsigned short version_major;
456 unsigned short version_minor;
457 long timezone;
458 unsigned long sigfigs;
459 unsigned long frame_max_len;
460 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
461 unsigned long link_type;
463 #define SWRAP_FILE_HDR_SIZE 24
465 struct swrap_packet {
466 struct {
467 unsigned long seconds;
468 unsigned long micro_seconds;
469 unsigned long recorded_length;
470 unsigned long full_length;
471 } frame;
472 #define SWRAP_PACKET__FRAME_SIZE 16
474 struct {
475 struct {
476 unsigned char ver_hdrlen;
477 unsigned char tos;
478 unsigned short packet_length;
479 unsigned short identification;
480 unsigned char flags;
481 unsigned char fragment;
482 unsigned char ttl;
483 unsigned char protocol;
484 unsigned short hdr_checksum;
485 unsigned long src_addr;
486 unsigned long dest_addr;
487 } hdr;
488 #define SWRAP_PACKET__IP_HDR_SIZE 20
490 union {
491 struct {
492 unsigned short source_port;
493 unsigned short dest_port;
494 unsigned long seq_num;
495 unsigned long ack_num;
496 unsigned char hdr_length;
497 unsigned char control;
498 unsigned short window;
499 unsigned short checksum;
500 unsigned short urg;
501 } tcp;
502 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
503 struct {
504 unsigned short source_port;
505 unsigned short dest_port;
506 unsigned short length;
507 unsigned short checksum;
508 } udp;
509 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
510 struct {
511 unsigned char type;
512 unsigned char code;
513 unsigned short checksum;
514 unsigned long unused;
515 } icmp;
516 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
517 } p;
518 } ip;
520 #define SWRAP_PACKET_SIZE 56
522 static const char *socket_wrapper_pcap_file(void)
524 static int initialized = 0;
525 static const char *s = NULL;
526 static const struct swrap_file_hdr h;
527 static const struct swrap_packet p;
529 if (initialized == 1) {
530 return s;
532 initialized = 1;
535 * TODO: don't use the structs use plain buffer offsets
536 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
538 * for now make sure we disable PCAP support
539 * if the struct has alignment!
541 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
542 return NULL;
544 if (sizeof(p) != SWRAP_PACKET_SIZE) {
545 return NULL;
547 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
548 return NULL;
550 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
551 return NULL;
553 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
554 return NULL;
556 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
557 return NULL;
559 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
560 return NULL;
563 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
564 if (s == NULL) {
565 return NULL;
567 if (strncmp(s, "./", 2) == 0) {
568 s += 2;
570 return s;
573 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
574 const struct sockaddr_in *src_addr,
575 const struct sockaddr_in *dest_addr,
576 int socket_type,
577 const unsigned char *payload,
578 size_t payload_len,
579 unsigned long tcp_seq,
580 unsigned long tcp_ack,
581 unsigned char tcp_ctl,
582 int unreachable,
583 size_t *_packet_len)
585 struct swrap_packet *ret;
586 struct swrap_packet *packet;
587 size_t packet_len;
588 size_t alloc_len;
589 size_t nonwire_len = sizeof(packet->frame);
590 size_t wire_hdr_len = 0;
591 size_t wire_len = 0;
592 size_t icmp_hdr_len = 0;
593 size_t icmp_truncate_len = 0;
594 unsigned char protocol = 0, icmp_protocol = 0;
595 unsigned short src_port = src_addr->sin_port;
596 unsigned short dest_port = dest_addr->sin_port;
598 switch (socket_type) {
599 case SOCK_STREAM:
600 protocol = 0x06; /* TCP */
601 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
602 wire_len = wire_hdr_len + payload_len;
603 break;
605 case SOCK_DGRAM:
606 protocol = 0x11; /* UDP */
607 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
608 wire_len = wire_hdr_len + payload_len;
609 break;
612 if (unreachable) {
613 icmp_protocol = protocol;
614 protocol = 0x01; /* ICMP */
615 if (wire_len > 64 ) {
616 icmp_truncate_len = wire_len - 64;
618 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
619 wire_hdr_len += icmp_hdr_len;
620 wire_len += icmp_hdr_len;
623 packet_len = nonwire_len + wire_len;
624 alloc_len = packet_len;
625 if (alloc_len < sizeof(struct swrap_packet)) {
626 alloc_len = sizeof(struct swrap_packet);
628 ret = (struct swrap_packet *)malloc(alloc_len);
629 if (!ret) return NULL;
631 packet = ret;
633 packet->frame.seconds = tval->tv_sec;
634 packet->frame.micro_seconds = tval->tv_usec;
635 packet->frame.recorded_length = wire_len - icmp_truncate_len;
636 packet->frame.full_length = wire_len - icmp_truncate_len;
638 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
639 packet->ip.hdr.tos = 0x00;
640 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
641 packet->ip.hdr.identification = htons(0xFFFF);
642 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
643 packet->ip.hdr.fragment = htons(0x0000);
644 packet->ip.hdr.ttl = 0xFF;
645 packet->ip.hdr.protocol = protocol;
646 packet->ip.hdr.hdr_checksum = htons(0x0000);
647 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
648 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
650 if (unreachable) {
651 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
652 packet->ip.p.icmp.code = 0x01; /* host unreachable */
653 packet->ip.p.icmp.checksum = htons(0x0000);
654 packet->ip.p.icmp.unused = htonl(0x00000000);
656 /* set the ip header in the ICMP payload */
657 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
658 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
659 packet->ip.hdr.tos = 0x00;
660 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
661 packet->ip.hdr.identification = htons(0xFFFF);
662 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
663 packet->ip.hdr.fragment = htons(0x0000);
664 packet->ip.hdr.ttl = 0xFF;
665 packet->ip.hdr.protocol = icmp_protocol;
666 packet->ip.hdr.hdr_checksum = htons(0x0000);
667 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
668 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
670 src_port = dest_addr->sin_port;
671 dest_port = src_addr->sin_port;
674 switch (socket_type) {
675 case SOCK_STREAM:
676 packet->ip.p.tcp.source_port = src_port;
677 packet->ip.p.tcp.dest_port = dest_port;
678 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
679 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
680 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
681 packet->ip.p.tcp.control = tcp_ctl;
682 packet->ip.p.tcp.window = htons(0x7FFF);
683 packet->ip.p.tcp.checksum = htons(0x0000);
684 packet->ip.p.tcp.urg = htons(0x0000);
686 break;
688 case SOCK_DGRAM:
689 packet->ip.p.udp.source_port = src_addr->sin_port;
690 packet->ip.p.udp.dest_port = dest_addr->sin_port;
691 packet->ip.p.udp.length = htons(8 + payload_len);
692 packet->ip.p.udp.checksum = htons(0x0000);
694 break;
697 if (payload && payload_len > 0) {
698 unsigned char *p = (unsigned char *)ret;
699 p += nonwire_len;
700 p += wire_hdr_len;
701 memcpy(p, payload, payload_len);
704 *_packet_len = packet_len - icmp_truncate_len;
705 return ret;
708 static int swrap_get_pcap_fd(const char *fname)
710 static int fd = -1;
712 if (fd != -1) return fd;
714 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
715 if (fd != -1) {
716 struct swrap_file_hdr file_hdr;
717 file_hdr.magic = 0xA1B2C3D4;
718 file_hdr.version_major = 0x0002;
719 file_hdr.version_minor = 0x0004;
720 file_hdr.timezone = 0x00000000;
721 file_hdr.sigfigs = 0x00000000;
722 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
723 file_hdr.link_type = 0x0065; /* 101 RAW IP */
725 write(fd, &file_hdr, sizeof(file_hdr));
726 return fd;
729 fd = open(fname, O_WRONLY|O_APPEND, 0644);
731 return fd;
734 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
735 enum swrap_packet_type type,
736 const void *buf, size_t len)
738 const struct sockaddr_in *src_addr;
739 const struct sockaddr_in *dest_addr;
740 const char *file_name;
741 unsigned long tcp_seq = 0;
742 unsigned long tcp_ack = 0;
743 unsigned char tcp_ctl = 0;
744 int unreachable = 0;
745 struct timeval tv;
746 struct swrap_packet *packet;
747 size_t packet_len = 0;
748 int fd;
750 file_name = socket_wrapper_pcap_file();
751 if (!file_name) {
752 return;
755 if (si->family != AF_INET) {
756 return;
759 switch (type) {
760 case SWRAP_CONNECT_SEND:
761 if (si->type != SOCK_STREAM) return;
763 src_addr = (const struct sockaddr_in *)si->myname;
764 dest_addr = (const struct sockaddr_in *)addr;
766 tcp_seq = si->io.pck_snd;
767 tcp_ack = si->io.pck_rcv;
768 tcp_ctl = 0x02; /* SYN */
770 si->io.pck_snd += 1;
772 break;
774 case SWRAP_CONNECT_RECV:
775 if (si->type != SOCK_STREAM) return;
777 dest_addr = (const struct sockaddr_in *)si->myname;
778 src_addr = (const struct sockaddr_in *)addr;
780 tcp_seq = si->io.pck_rcv;
781 tcp_ack = si->io.pck_snd;
782 tcp_ctl = 0x12; /** SYN,ACK */
784 si->io.pck_rcv += 1;
786 break;
788 case SWRAP_CONNECT_UNREACH:
789 if (si->type != SOCK_STREAM) return;
791 dest_addr = (const struct sockaddr_in *)si->myname;
792 src_addr = (const struct sockaddr_in *)addr;
794 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
795 tcp_seq = si->io.pck_snd - 1;
796 tcp_ack = si->io.pck_rcv;
797 tcp_ctl = 0x02; /* SYN */
798 unreachable = 1;
800 break;
802 case SWRAP_CONNECT_ACK:
803 if (si->type != SOCK_STREAM) return;
805 src_addr = (const struct sockaddr_in *)si->myname;
806 dest_addr = (const struct sockaddr_in *)addr;
808 tcp_seq = si->io.pck_snd;
809 tcp_ack = si->io.pck_rcv;
810 tcp_ctl = 0x10; /* ACK */
812 break;
814 case SWRAP_ACCEPT_SEND:
815 if (si->type != SOCK_STREAM) return;
817 dest_addr = (const struct sockaddr_in *)si->myname;
818 src_addr = (const struct sockaddr_in *)addr;
820 tcp_seq = si->io.pck_rcv;
821 tcp_ack = si->io.pck_snd;
822 tcp_ctl = 0x02; /* SYN */
824 si->io.pck_rcv += 1;
826 break;
828 case SWRAP_ACCEPT_RECV:
829 if (si->type != SOCK_STREAM) return;
831 src_addr = (const struct sockaddr_in *)si->myname;
832 dest_addr = (const struct sockaddr_in *)addr;
834 tcp_seq = si->io.pck_snd;
835 tcp_ack = si->io.pck_rcv;
836 tcp_ctl = 0x12; /* SYN,ACK */
838 si->io.pck_snd += 1;
840 break;
842 case SWRAP_ACCEPT_ACK:
843 if (si->type != SOCK_STREAM) return;
845 dest_addr = (const struct sockaddr_in *)si->myname;
846 src_addr = (const struct sockaddr_in *)addr;
848 tcp_seq = si->io.pck_rcv;
849 tcp_ack = si->io.pck_snd;
850 tcp_ctl = 0x10; /* ACK */
852 break;
854 case SWRAP_SEND:
855 src_addr = (const struct sockaddr_in *)si->myname;
856 dest_addr = (const struct sockaddr_in *)si->peername;
858 tcp_seq = si->io.pck_snd;
859 tcp_ack = si->io.pck_rcv;
860 tcp_ctl = 0x18; /* PSH,ACK */
862 si->io.pck_snd += len;
864 break;
866 case SWRAP_SEND_RST:
867 dest_addr = (const struct sockaddr_in *)si->myname;
868 src_addr = (const struct sockaddr_in *)si->peername;
870 if (si->type == SOCK_DGRAM) {
871 swrap_dump_packet(si, si->peername,
872 SWRAP_SENDTO_UNREACH,
873 buf, len);
874 return;
877 tcp_seq = si->io.pck_rcv;
878 tcp_ack = si->io.pck_snd;
879 tcp_ctl = 0x14; /** RST,ACK */
881 break;
883 case SWRAP_PENDING_RST:
884 dest_addr = (const struct sockaddr_in *)si->myname;
885 src_addr = (const struct sockaddr_in *)si->peername;
887 if (si->type == SOCK_DGRAM) {
888 return;
891 tcp_seq = si->io.pck_rcv;
892 tcp_ack = si->io.pck_snd;
893 tcp_ctl = 0x14; /* RST,ACK */
895 break;
897 case SWRAP_RECV:
898 dest_addr = (const struct sockaddr_in *)si->myname;
899 src_addr = (const struct sockaddr_in *)si->peername;
901 tcp_seq = si->io.pck_rcv;
902 tcp_ack = si->io.pck_snd;
903 tcp_ctl = 0x18; /* PSH,ACK */
905 si->io.pck_rcv += len;
907 break;
909 case SWRAP_RECV_RST:
910 dest_addr = (const struct sockaddr_in *)si->myname;
911 src_addr = (const struct sockaddr_in *)si->peername;
913 if (si->type == SOCK_DGRAM) {
914 return;
917 tcp_seq = si->io.pck_rcv;
918 tcp_ack = si->io.pck_snd;
919 tcp_ctl = 0x14; /* RST,ACK */
921 break;
923 case SWRAP_SENDTO:
924 src_addr = (const struct sockaddr_in *)si->myname;
925 dest_addr = (const struct sockaddr_in *)addr;
927 si->io.pck_snd += len;
929 break;
931 case SWRAP_SENDTO_UNREACH:
932 dest_addr = (const struct sockaddr_in *)si->myname;
933 src_addr = (const struct sockaddr_in *)addr;
935 unreachable = 1;
937 break;
939 case SWRAP_RECVFROM:
940 dest_addr = (const struct sockaddr_in *)si->myname;
941 src_addr = (const struct sockaddr_in *)addr;
943 si->io.pck_rcv += len;
945 break;
947 case SWRAP_CLOSE_SEND:
948 if (si->type != SOCK_STREAM) return;
950 src_addr = (const struct sockaddr_in *)si->myname;
951 dest_addr = (const struct sockaddr_in *)si->peername;
953 tcp_seq = si->io.pck_snd;
954 tcp_ack = si->io.pck_rcv;
955 tcp_ctl = 0x11; /* FIN, ACK */
957 si->io.pck_snd += 1;
959 break;
961 case SWRAP_CLOSE_RECV:
962 if (si->type != SOCK_STREAM) return;
964 dest_addr = (const struct sockaddr_in *)si->myname;
965 src_addr = (const struct sockaddr_in *)si->peername;
967 tcp_seq = si->io.pck_rcv;
968 tcp_ack = si->io.pck_snd;
969 tcp_ctl = 0x11; /* FIN,ACK */
971 si->io.pck_rcv += 1;
973 break;
975 case SWRAP_CLOSE_ACK:
976 if (si->type != SOCK_STREAM) return;
978 src_addr = (const struct sockaddr_in *)si->myname;
979 dest_addr = (const struct sockaddr_in *)si->peername;
981 tcp_seq = si->io.pck_snd;
982 tcp_ack = si->io.pck_rcv;
983 tcp_ctl = 0x10; /* ACK */
985 break;
986 default:
987 return;
990 swrapGetTimeOfDay(&tv);
992 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
993 (const unsigned char *)buf, len,
994 tcp_seq, tcp_ack, tcp_ctl, unreachable,
995 &packet_len);
996 if (!packet) {
997 return;
1000 fd = swrap_get_pcap_fd(file_name);
1001 if (fd != -1) {
1002 write(fd, packet, packet_len);
1005 free(packet);
1008 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1010 struct socket_info *si;
1011 int fd;
1013 if (!socket_wrapper_dir()) {
1014 return real_socket(family, type, protocol);
1017 switch (family) {
1018 case AF_INET:
1019 break;
1020 case AF_UNIX:
1021 return real_socket(family, type, protocol);
1022 default:
1023 errno = EAFNOSUPPORT;
1024 return -1;
1027 switch (type) {
1028 case SOCK_STREAM:
1029 break;
1030 case SOCK_DGRAM:
1031 break;
1032 default:
1033 errno = EPROTONOSUPPORT;
1034 return -1;
1037 switch (protocol) {
1038 case 0:
1039 break;
1040 default:
1041 errno = EPROTONOSUPPORT;
1042 return -1;
1045 fd = real_socket(AF_UNIX, type, 0);
1047 if (fd == -1) return -1;
1049 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1051 si->family = family;
1052 si->type = type;
1053 si->protocol = protocol;
1054 si->fd = fd;
1056 DLIST_ADD(sockets, si);
1058 return si->fd;
1061 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1063 struct socket_info *parent_si, *child_si;
1064 int fd;
1065 struct sockaddr_un un_addr;
1066 socklen_t un_addrlen = sizeof(un_addr);
1067 struct sockaddr_un un_my_addr;
1068 socklen_t un_my_addrlen = sizeof(un_my_addr);
1069 struct sockaddr my_addr;
1070 socklen_t my_addrlen = sizeof(my_addr);
1071 int ret;
1073 parent_si = find_socket_info(s);
1074 if (!parent_si) {
1075 return real_accept(s, addr, addrlen);
1078 memset(&un_addr, 0, sizeof(un_addr));
1079 memset(&un_my_addr, 0, sizeof(un_my_addr));
1080 memset(&my_addr, 0, sizeof(my_addr));
1082 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1083 if (ret == -1) return ret;
1085 fd = ret;
1087 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1088 parent_si->family, addr, addrlen);
1089 if (ret == -1) {
1090 close(fd);
1091 return ret;
1094 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1095 memset(child_si, 0, sizeof(*child_si));
1097 child_si->fd = fd;
1098 child_si->family = parent_si->family;
1099 child_si->type = parent_si->type;
1100 child_si->protocol = parent_si->protocol;
1101 child_si->bound = 1;
1102 child_si->is_server = 1;
1104 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1105 if (ret == -1) {
1106 free(child_si);
1107 close(fd);
1108 return ret;
1111 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1112 child_si->family, &my_addr, &my_addrlen);
1113 if (ret == -1) {
1114 free(child_si);
1115 close(fd);
1116 return ret;
1119 child_si->myname_len = my_addrlen;
1120 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1122 child_si->peername_len = *addrlen;
1123 child_si->peername = sockaddr_dup(addr, *addrlen);
1125 DLIST_ADD(sockets, child_si);
1127 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1128 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1129 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1131 return fd;
1134 static int autobind_start_init;
1135 static int autobind_start;
1137 /* using sendto() or connect() on an unbound socket would give the
1138 recipient no way to reply, as unlike UDP and TCP, a unix domain
1139 socket can't auto-assign emphemeral port numbers, so we need to
1140 assign it here */
1141 static int swrap_auto_bind(struct socket_info *si)
1143 struct sockaddr_un un_addr;
1144 struct sockaddr_in in;
1145 int i;
1146 char type;
1147 int ret;
1148 int port;
1149 struct stat st;
1151 if (autobind_start_init != 1) {
1152 autobind_start_init = 1;
1153 autobind_start = getpid();
1154 autobind_start %= 50000;
1155 autobind_start += 10000;
1158 un_addr.sun_family = AF_UNIX;
1160 switch (si->type) {
1161 case SOCK_STREAM:
1162 type = SOCKET_TYPE_CHAR_TCP;
1163 break;
1164 case SOCK_DGRAM:
1165 type = SOCKET_TYPE_CHAR_UDP;
1166 break;
1167 default:
1168 errno = ESOCKTNOSUPPORT;
1169 return -1;
1172 if (autobind_start > 60000) {
1173 autobind_start = 10000;
1176 for (i=0;i<1000;i++) {
1177 port = autobind_start + i;
1178 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1179 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1180 type, socket_wrapper_default_iface(), port);
1181 if (stat(un_addr.sun_path, &st) == 0) continue;
1183 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1184 if (ret == -1) return ret;
1186 si->tmp_path = strdup(un_addr.sun_path);
1187 si->bound = 1;
1188 autobind_start = port + 1;
1189 break;
1191 if (i == 1000) {
1192 errno = ENFILE;
1193 return -1;
1196 memset(&in, 0, sizeof(in));
1197 in.sin_family = AF_INET;
1198 in.sin_port = htons(port);
1199 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1201 si->myname_len = sizeof(in);
1202 si->myname = sockaddr_dup(&in, si->myname_len);
1203 return 0;
1207 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1209 int ret;
1210 struct sockaddr_un un_addr;
1211 struct socket_info *si = find_socket_info(s);
1213 if (!si) {
1214 return real_connect(s, serv_addr, addrlen);
1217 if (si->bound == 0) {
1218 ret = swrap_auto_bind(si);
1219 if (ret == -1) return -1;
1222 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1223 if (ret == -1) return -1;
1225 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1227 ret = real_connect(s, (struct sockaddr *)&un_addr,
1228 sizeof(struct sockaddr_un));
1230 /* to give better errors */
1231 if (ret == -1 && errno == ENOENT) {
1232 errno = EHOSTUNREACH;
1235 if (ret == 0) {
1236 si->peername_len = addrlen;
1237 si->peername = sockaddr_dup(serv_addr, addrlen);
1239 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1240 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1241 } else {
1242 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1245 return ret;
1248 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1250 int ret;
1251 struct sockaddr_un un_addr;
1252 struct socket_info *si = find_socket_info(s);
1254 if (!si) {
1255 return real_bind(s, myaddr, addrlen);
1258 si->myname_len = addrlen;
1259 si->myname = sockaddr_dup(myaddr, addrlen);
1261 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1262 if (ret == -1) return -1;
1264 unlink(un_addr.sun_path);
1266 ret = real_bind(s, (struct sockaddr *)&un_addr,
1267 sizeof(struct sockaddr_un));
1269 if (ret == 0) {
1270 si->bound = 1;
1273 return ret;
1276 _PUBLIC_ int swrap_listen(int s, int backlog)
1278 int ret;
1279 struct socket_info *si = find_socket_info(s);
1281 if (!si) {
1282 return real_listen(s, backlog);
1285 ret = real_listen(s, backlog);
1287 return ret;
1290 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1292 struct socket_info *si = find_socket_info(s);
1294 if (!si) {
1295 return real_getpeername(s, name, addrlen);
1298 if (!si->peername)
1300 errno = ENOTCONN;
1301 return -1;
1304 memcpy(name, si->peername, si->peername_len);
1305 *addrlen = si->peername_len;
1307 return 0;
1310 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1312 struct socket_info *si = find_socket_info(s);
1314 if (!si) {
1315 return real_getsockname(s, name, addrlen);
1318 memcpy(name, si->myname, si->myname_len);
1319 *addrlen = si->myname_len;
1321 return 0;
1324 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1326 struct socket_info *si = find_socket_info(s);
1328 if (!si) {
1329 return real_getsockopt(s, level, optname, optval, optlen);
1332 if (level == SOL_SOCKET) {
1333 return real_getsockopt(s, level, optname, optval, optlen);
1336 errno = ENOPROTOOPT;
1337 return -1;
1340 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1342 struct socket_info *si = find_socket_info(s);
1344 if (!si) {
1345 return real_setsockopt(s, level, optname, optval, optlen);
1348 if (level == SOL_SOCKET) {
1349 return real_setsockopt(s, level, optname, optval, optlen);
1352 switch (si->family) {
1353 case AF_INET:
1354 return 0;
1355 default:
1356 errno = ENOPROTOOPT;
1357 return -1;
1361 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1363 struct sockaddr_un un_addr;
1364 socklen_t un_addrlen = sizeof(un_addr);
1365 int ret;
1366 struct socket_info *si = find_socket_info(s);
1368 if (!si) {
1369 return real_recvfrom(s, buf, len, flags, from, fromlen);
1372 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1373 memset(&un_addr, 0, sizeof(un_addr));
1374 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1375 if (ret == -1)
1376 return ret;
1378 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1379 si->family, from, fromlen) == -1) {
1380 return -1;
1383 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1385 return ret;
1389 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1391 struct sockaddr_un un_addr;
1392 int ret;
1393 struct socket_info *si = find_socket_info(s);
1394 int bcast = 0;
1396 if (!si) {
1397 return real_sendto(s, buf, len, flags, to, tolen);
1400 if (si->bound == 0) {
1401 ret = swrap_auto_bind(si);
1402 if (ret == -1) return -1;
1405 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1406 if (ret == -1) return -1;
1408 if (bcast) {
1409 struct stat st;
1410 unsigned int iface;
1411 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1412 char type;
1414 type = SOCKET_TYPE_CHAR_UDP;
1416 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1417 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1418 socket_wrapper_dir(), type, iface, prt);
1419 if (stat(un_addr.sun_path, &st) != 0) continue;
1421 /* ignore the any errors in broadcast sends */
1422 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1425 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1427 return len;
1430 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1432 /* to give better errors */
1433 if (ret == -1 && errno == ENOENT) {
1434 errno = EHOSTUNREACH;
1437 if (ret == -1) {
1438 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1439 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1440 } else {
1441 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1444 return ret;
1447 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1449 int ret;
1450 struct socket_info *si = find_socket_info(s);
1451 int value;
1453 if (!si) {
1454 return real_ioctl(s, r, p);
1457 ret = real_ioctl(s, r, p);
1459 switch (r) {
1460 case FIONREAD:
1461 value = *((int *)p);
1462 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1463 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1464 } else if (value == 0) { /* END OF FILE */
1465 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1467 break;
1470 return ret;
1473 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1475 int ret;
1476 struct socket_info *si = find_socket_info(s);
1478 if (!si) {
1479 return real_recv(s, buf, len, flags);
1482 ret = real_recv(s, buf, len, flags);
1483 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1484 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1485 } else if (ret == 0) { /* END OF FILE */
1486 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1487 } else {
1488 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1491 return ret;
1495 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1497 int ret;
1498 struct socket_info *si = find_socket_info(s);
1500 if (!si) {
1501 return real_send(s, buf, len, flags);
1504 ret = real_send(s, buf, len, flags);
1506 if (ret == -1) {
1507 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1508 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1509 } else {
1510 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1513 return ret;
1516 _PUBLIC_ int swrap_close(int fd)
1518 struct socket_info *si = find_socket_info(fd);
1519 int ret;
1521 if (!si) {
1522 return real_close(fd);
1525 DLIST_REMOVE(sockets, si);
1527 if (si->myname && si->peername) {
1528 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1531 ret = real_close(fd);
1533 if (si->myname && si->peername) {
1534 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1535 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1538 if (si->path) free(si->path);
1539 if (si->myname) free(si->myname);
1540 if (si->peername) free(si->peername);
1541 if (si->tmp_path) {
1542 unlink(si->tmp_path);
1543 free(si->tmp_path);
1545 free(si);
1547 return ret;