x
[heimdal.git] / lib / roken / socket_wrapper.c
blob9e6bfdd09811e34f22d4e282e61c09d53176229b
1 /*
2 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
32 * SUCH DAMAGE.
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
39 is set.
42 #define SOCKET_WRAPPER_NOT_REPLACE
44 #ifdef _SAMBA_BUILD_
46 #include "includes.h"
47 #include "system/network.h"
48 #include "system/filesys.h"
50 #ifdef malloc
51 #undef malloc
52 #endif
53 #ifdef calloc
54 #undef calloc
55 #endif
56 #ifdef strdup
57 #undef strdup
58 #endif
60 #else /* _SAMBA_BUILD_ */
62 #ifdef HAVE_CONFIG_H
63 #include <config.h>
64 #endif
65 #undef SOCKET_WRAPPER_REPLACE
67 #include <sys/types.h>
68 #ifdef TIME_WITH_SYS_TIME
69 #include <sys/time.h>
70 #include <time.h>
71 #elif defined(HAVE_SYS_TIME_H)
72 #include <sys/time.h>
73 #else
74 #include <time.h>
75 #endif
76 #include <sys/stat.h>
77 #include <sys/socket.h>
78 #include <sys/ioctl.h>
79 #ifdef HAVE_SYS_FILIO_H
80 #include <sys/filio.h>
81 #endif
82 #include <errno.h>
83 #include <sys/un.h>
84 #include <netinet/in.h>
85 #include <netinet/tcp.h>
86 #include <fcntl.h>
87 #include <stdlib.h>
88 #include <unistd.h>
89 #include <string.h>
90 #include <stdio.h>
91 #include "roken.h"
93 #include "socket_wrapper.h"
95 #define HAVE_GETTIMEOFDAY_TZ 1
97 #define _PUBLIC_
99 #endif
101 #define SWRAP_DLIST_ADD(list,item) do { \
102 if (!(list)) { \
103 (item)->prev = NULL; \
104 (item)->next = NULL; \
105 (list) = (item); \
106 } else { \
107 (item)->prev = NULL; \
108 (item)->next = (list); \
109 (list)->prev = (item); \
110 (list) = (item); \
112 } while (0)
114 #define SWRAP_DLIST_REMOVE(list,item) do { \
115 if ((list) == (item)) { \
116 (list) = (item)->next; \
117 if (list) { \
118 (list)->prev = NULL; \
120 } else { \
121 if ((item)->prev) { \
122 (item)->prev->next = (item)->next; \
124 if ((item)->next) { \
125 (item)->next->prev = (item)->prev; \
128 (item)->prev = NULL; \
129 (item)->next = NULL; \
130 } while (0)
132 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
133 * for now */
134 #define REWRITE_CALLS
136 #ifdef REWRITE_CALLS
137 #define real_accept accept
138 #define real_connect connect
139 #define real_bind bind
140 #define real_listen listen
141 #define real_getpeername getpeername
142 #define real_getsockname getsockname
143 #define real_getsockopt getsockopt
144 #define real_setsockopt setsockopt
145 #define real_recvfrom recvfrom
146 #define real_sendto sendto
147 #define real_ioctl ioctl
148 #define real_recv recv
149 #define real_send send
150 #define real_socket socket
151 #define real_close close
152 #define real_dup dup
153 #define real_dup2 dup2
154 #endif
156 #ifdef HAVE_GETTIMEOFDAY_TZ
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
158 #else
159 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
160 #endif
162 /* we need to use a very terse format here as IRIX 6.4 silently
163 truncates names to 16 chars, so if we use a longer name then we
164 can't tell which port a packet came from with recvfrom()
166 with this format we have 8 chars left for the directory name
168 #define SOCKET_FORMAT "%c%02X%04X"
169 #define SOCKET_TYPE_CHAR_TCP 'T'
170 #define SOCKET_TYPE_CHAR_UDP 'U'
171 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
172 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
174 #define MAX_WRAPPED_INTERFACES 16
176 #define SW_IPV6_ADDRESS 1
178 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
180 struct sockaddr *ret = (struct sockaddr *)malloc(len);
181 memcpy(ret, data, len);
182 return ret;
185 static void set_port(int family, int prt, struct sockaddr *addr)
187 switch (family) {
188 case AF_INET:
189 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
190 break;
191 #ifdef HAVE_IPV6
192 case AF_INET6:
193 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
194 break;
195 #endif
199 static int socket_length(int family)
201 switch (family) {
202 case AF_INET:
203 return sizeof(struct sockaddr_in);
204 #ifdef HAVE_IPV6
205 case AF_INET6:
206 return sizeof(struct sockaddr_in6);
207 #endif
209 return -1;
214 struct socket_info
216 int fd;
218 int family;
219 int type;
220 int protocol;
221 int bound;
222 int bcast;
223 int is_server;
225 char *path;
226 char *tmp_path;
228 struct sockaddr *myname;
229 socklen_t myname_len;
231 struct sockaddr *peername;
232 socklen_t peername_len;
234 struct {
235 unsigned long pck_snd;
236 unsigned long pck_rcv;
237 } io;
239 struct socket_info *prev, *next;
242 static struct socket_info *sockets;
245 static const char *socket_wrapper_dir(void)
247 const char *s = getenv("SOCKET_WRAPPER_DIR");
248 if (s == NULL) {
249 return NULL;
251 if (strncmp(s, "./", 2) == 0) {
252 s += 2;
254 return s;
257 static unsigned int socket_wrapper_default_iface(void)
259 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
260 if (s) {
261 unsigned int iface;
262 if (sscanf(s, "%u", &iface) == 1) {
263 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
264 return iface;
269 return 1;/* 127.0.0.1 */
272 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
274 unsigned int iface;
275 unsigned int prt;
276 const char *p;
277 char type;
279 p = strrchr(un->sun_path, '/');
280 if (p) p++; else p = un->sun_path;
282 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
283 errno = EINVAL;
284 return -1;
287 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
288 errno = EINVAL;
289 return -1;
292 if (prt > 0xFFFF) {
293 errno = EINVAL;
294 return -1;
297 switch(type) {
298 case SOCKET_TYPE_CHAR_TCP:
299 case SOCKET_TYPE_CHAR_UDP: {
300 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
302 if ((*len) < sizeof(*in2)) {
303 errno = EINVAL;
304 return -1;
307 memset(in2, 0, sizeof(*in2));
308 in2->sin_family = AF_INET;
309 in2->sin_addr.s_addr = htonl((127<<24) | iface);
310 in2->sin_port = htons(prt);
312 *len = sizeof(*in2);
313 break;
315 #ifdef HAVE_IPV6
316 case SOCKET_TYPE_CHAR_TCP_V6:
317 case SOCKET_TYPE_CHAR_UDP_V6: {
318 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
320 if ((*len) < sizeof(*in2)) {
321 errno = EINVAL;
322 return -1;
325 memset(in2, 0, sizeof(*in2));
326 in2->sin6_family = AF_INET6;
327 in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
328 in2->sin6_port = htons(prt);
330 *len = sizeof(*in2);
331 break;
333 #endif
334 default:
335 errno = EINVAL;
336 return -1;
339 return 0;
342 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
343 int *bcast)
345 char type = '\0';
346 unsigned int prt;
347 unsigned int iface;
348 int is_bcast = 0;
350 if (bcast) *bcast = 0;
352 switch (si->family) {
353 case AF_INET: {
354 const struct sockaddr_in *in =
355 (const struct sockaddr_in *)inaddr;
356 unsigned int addr = ntohl(in->sin_addr.s_addr);
357 char u_type = '\0';
358 char b_type = '\0';
359 char a_type = '\0';
361 switch (si->type) {
362 case SOCK_STREAM:
363 u_type = SOCKET_TYPE_CHAR_TCP;
364 break;
365 case SOCK_DGRAM:
366 u_type = SOCKET_TYPE_CHAR_UDP;
367 a_type = SOCKET_TYPE_CHAR_UDP;
368 b_type = SOCKET_TYPE_CHAR_UDP;
369 break;
372 prt = ntohs(in->sin_port);
373 if (a_type && addr == 0xFFFFFFFF) {
374 /* 255.255.255.255 only udp */
375 is_bcast = 2;
376 type = a_type;
377 iface = socket_wrapper_default_iface();
378 } else if (b_type && addr == 0x7FFFFFFF) {
379 /* 127.255.255.255 only udp */
380 is_bcast = 1;
381 type = b_type;
382 iface = socket_wrapper_default_iface();
383 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
384 /* 127.0.0.X */
385 is_bcast = 0;
386 type = u_type;
387 iface = (addr & 0x000000FF);
388 } else {
389 errno = ENETUNREACH;
390 return -1;
392 if (bcast) *bcast = is_bcast;
393 break;
395 #ifdef HAVE_IPV6
396 case AF_INET6: {
397 const struct sockaddr_in6 *in =
398 (const struct sockaddr_in6 *)inaddr;
400 switch (si->type) {
401 case SOCK_STREAM:
402 type = SOCKET_TYPE_CHAR_TCP_V6;
403 break;
404 case SOCK_DGRAM:
405 type = SOCKET_TYPE_CHAR_UDP_V6;
406 break;
409 /* XXX no multicast/broadcast */
411 prt = ntohs(in->sin6_port);
412 iface = SW_IPV6_ADDRESS;
414 break;
416 #endif
417 default:
418 errno = ENETUNREACH;
419 return -1;
422 if (prt == 0) {
423 errno = EINVAL;
424 return -1;
427 if (is_bcast) {
428 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
429 socket_wrapper_dir());
430 /* the caller need to do more processing */
431 return 0;
434 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
435 socket_wrapper_dir(), type, iface, prt);
437 return 0;
440 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
441 int *bcast)
443 char type = '\0';
444 unsigned int prt;
445 unsigned int iface;
446 struct stat st;
447 int is_bcast = 0;
449 if (bcast) *bcast = 0;
451 switch (si->family) {
452 case AF_INET: {
453 const struct sockaddr_in *in =
454 (const struct sockaddr_in *)inaddr;
455 unsigned int addr = ntohl(in->sin_addr.s_addr);
456 char u_type = '\0';
457 char d_type = '\0';
458 char b_type = '\0';
459 char a_type = '\0';
461 prt = ntohs(in->sin_port);
463 switch (si->type) {
464 case SOCK_STREAM:
465 u_type = SOCKET_TYPE_CHAR_TCP;
466 d_type = SOCKET_TYPE_CHAR_TCP;
467 break;
468 case SOCK_DGRAM:
469 u_type = SOCKET_TYPE_CHAR_UDP;
470 d_type = SOCKET_TYPE_CHAR_UDP;
471 a_type = SOCKET_TYPE_CHAR_UDP;
472 b_type = SOCKET_TYPE_CHAR_UDP;
473 break;
476 if (addr == 0) {
477 /* 0.0.0.0 */
478 is_bcast = 0;
479 type = d_type;
480 iface = socket_wrapper_default_iface();
481 } else if (a_type && addr == 0xFFFFFFFF) {
482 /* 255.255.255.255 only udp */
483 is_bcast = 2;
484 type = a_type;
485 iface = socket_wrapper_default_iface();
486 } else if (b_type && addr == 0x7FFFFFFF) {
487 /* 127.255.255.255 only udp */
488 is_bcast = 1;
489 type = b_type;
490 iface = socket_wrapper_default_iface();
491 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
492 /* 127.0.0.X */
493 is_bcast = 0;
494 type = u_type;
495 iface = (addr & 0x000000FF);
496 } else {
497 errno = EADDRNOTAVAIL;
498 return -1;
500 break;
502 #ifdef HAVE_IPV6
503 case AF_INET6: {
504 const struct sockaddr_in6 *in =
505 (const struct sockaddr_in6 *)inaddr;
507 switch (si->type) {
508 case SOCK_STREAM:
509 type = SOCKET_TYPE_CHAR_TCP_V6;
510 break;
511 case SOCK_DGRAM:
512 type = SOCKET_TYPE_CHAR_UDP_V6;
513 break;
516 /* XXX no multicast/broadcast */
518 prt = ntohs(in->sin6_port);
519 iface = SW_IPV6_ADDRESS;
521 break;
523 #endif
524 default:
525 errno = ENETUNREACH;
526 return -1;
530 if (bcast) *bcast = is_bcast;
532 if (prt == 0) {
533 /* handle auto-allocation of ephemeral ports */
534 for (prt = 5001; prt < 10000; prt++) {
535 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
536 socket_wrapper_dir(), type, iface, prt);
537 if (stat(un->sun_path, &st) == 0) continue;
539 set_port(si->family, prt, si->myname);
543 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
544 socket_wrapper_dir(), type, iface, prt);
545 return 0;
548 static struct socket_info *find_socket_info(int fd)
550 struct socket_info *i;
551 for (i = sockets; i; i = i->next) {
552 if (i->fd == fd)
553 return i;
556 return NULL;
559 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
560 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
562 if (!out_addr)
563 return 0;
565 out_addr->sun_family = AF_UNIX;
567 switch (in_addr->sa_family) {
568 case AF_INET:
569 #ifdef HAVE_IPV6
570 case AF_INET6:
571 #endif
572 switch (si->type) {
573 case SOCK_STREAM:
574 case SOCK_DGRAM:
575 break;
576 default:
577 errno = ESOCKTNOSUPPORT;
578 return -1;
580 if (alloc_sock) {
581 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
582 } else {
583 return convert_in_un_remote(si, in_addr, out_addr, bcast);
585 default:
586 break;
589 errno = EAFNOSUPPORT;
590 return -1;
593 static int sockaddr_convert_from_un(const struct socket_info *si,
594 const struct sockaddr_un *in_addr,
595 socklen_t un_addrlen,
596 int family,
597 struct sockaddr *out_addr,
598 socklen_t *out_addrlen)
600 if (out_addr == NULL || out_addrlen == NULL)
601 return 0;
603 if (un_addrlen == 0) {
604 *out_addrlen = 0;
605 return 0;
608 switch (family) {
609 case AF_INET:
610 #ifdef HAVE_IPV6
611 case AF_INET6:
612 #endif
613 switch (si->type) {
614 case SOCK_STREAM:
615 case SOCK_DGRAM:
616 break;
617 default:
618 errno = ESOCKTNOSUPPORT;
619 return -1;
621 return convert_un_in(in_addr, out_addr, out_addrlen);
622 default:
623 break;
626 errno = EAFNOSUPPORT;
627 return -1;
630 enum swrap_packet_type {
631 SWRAP_CONNECT_SEND,
632 SWRAP_CONNECT_UNREACH,
633 SWRAP_CONNECT_RECV,
634 SWRAP_CONNECT_ACK,
635 SWRAP_ACCEPT_SEND,
636 SWRAP_ACCEPT_RECV,
637 SWRAP_ACCEPT_ACK,
638 SWRAP_RECVFROM,
639 SWRAP_SENDTO,
640 SWRAP_SENDTO_UNREACH,
641 SWRAP_PENDING_RST,
642 SWRAP_RECV,
643 SWRAP_RECV_RST,
644 SWRAP_SEND,
645 SWRAP_SEND_RST,
646 SWRAP_CLOSE_SEND,
647 SWRAP_CLOSE_RECV,
648 SWRAP_CLOSE_ACK
651 struct swrap_file_hdr {
652 unsigned long magic;
653 unsigned short version_major;
654 unsigned short version_minor;
655 long timezone;
656 unsigned long sigfigs;
657 unsigned long frame_max_len;
658 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
659 unsigned long link_type;
661 #define SWRAP_FILE_HDR_SIZE 24
663 struct swrap_packet {
664 struct {
665 unsigned long seconds;
666 unsigned long micro_seconds;
667 unsigned long recorded_length;
668 unsigned long full_length;
669 } frame;
670 #define SWRAP_PACKET__FRAME_SIZE 16
672 struct {
673 struct {
674 unsigned char ver_hdrlen;
675 unsigned char tos;
676 unsigned short packet_length;
677 unsigned short identification;
678 unsigned char flags;
679 unsigned char fragment;
680 unsigned char ttl;
681 unsigned char protocol;
682 unsigned short hdr_checksum;
683 unsigned long src_addr;
684 unsigned long dest_addr;
685 } hdr;
686 #define SWRAP_PACKET__IP_HDR_SIZE 20
688 union {
689 struct {
690 unsigned short source_port;
691 unsigned short dest_port;
692 unsigned long seq_num;
693 unsigned long ack_num;
694 unsigned char hdr_length;
695 unsigned char control;
696 unsigned short window;
697 unsigned short checksum;
698 unsigned short urg;
699 } tcp;
700 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
701 struct {
702 unsigned short source_port;
703 unsigned short dest_port;
704 unsigned short length;
705 unsigned short checksum;
706 } udp;
707 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
708 struct {
709 unsigned char type;
710 unsigned char code;
711 unsigned short checksum;
712 unsigned long unused;
713 } icmp;
714 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
715 } p;
716 } ip;
718 #define SWRAP_PACKET_SIZE 56
720 static const char *socket_wrapper_pcap_file(void)
722 static int initialized = 0;
723 static const char *s = NULL;
724 static const struct swrap_file_hdr h;
725 static const struct swrap_packet p;
727 if (initialized == 1) {
728 return s;
730 initialized = 1;
733 * TODO: don't use the structs use plain buffer offsets
734 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
736 * for now make sure we disable PCAP support
737 * if the struct has alignment!
739 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
740 return NULL;
742 if (sizeof(p) != SWRAP_PACKET_SIZE) {
743 return NULL;
745 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
746 return NULL;
748 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
749 return NULL;
751 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
752 return NULL;
754 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
755 return NULL;
757 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
758 return NULL;
761 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
762 if (s == NULL) {
763 return NULL;
765 if (strncmp(s, "./", 2) == 0) {
766 s += 2;
768 return s;
771 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
772 const struct sockaddr_in *src_addr,
773 const struct sockaddr_in *dest_addr,
774 int socket_type,
775 const unsigned char *payload,
776 size_t payload_len,
777 unsigned long tcp_seq,
778 unsigned long tcp_ack,
779 unsigned char tcp_ctl,
780 int unreachable,
781 size_t *_packet_len)
783 struct swrap_packet *ret;
784 struct swrap_packet *packet;
785 size_t packet_len;
786 size_t alloc_len;
787 size_t nonwire_len = sizeof(packet->frame);
788 size_t wire_hdr_len = 0;
789 size_t wire_len = 0;
790 size_t icmp_hdr_len = 0;
791 size_t icmp_truncate_len = 0;
792 unsigned char protocol = 0, icmp_protocol = 0;
793 unsigned short src_port = src_addr->sin_port;
794 unsigned short dest_port = dest_addr->sin_port;
796 switch (socket_type) {
797 case SOCK_STREAM:
798 protocol = 0x06; /* TCP */
799 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
800 wire_len = wire_hdr_len + payload_len;
801 break;
803 case SOCK_DGRAM:
804 protocol = 0x11; /* UDP */
805 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
806 wire_len = wire_hdr_len + payload_len;
807 break;
810 if (unreachable) {
811 icmp_protocol = protocol;
812 protocol = 0x01; /* ICMP */
813 if (wire_len > 64 ) {
814 icmp_truncate_len = wire_len - 64;
816 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
817 wire_hdr_len += icmp_hdr_len;
818 wire_len += icmp_hdr_len;
821 packet_len = nonwire_len + wire_len;
822 alloc_len = packet_len;
823 if (alloc_len < sizeof(struct swrap_packet)) {
824 alloc_len = sizeof(struct swrap_packet);
826 ret = (struct swrap_packet *)malloc(alloc_len);
827 if (!ret) return NULL;
829 packet = ret;
831 packet->frame.seconds = tval->tv_sec;
832 packet->frame.micro_seconds = tval->tv_usec;
833 packet->frame.recorded_length = wire_len - icmp_truncate_len;
834 packet->frame.full_length = wire_len - icmp_truncate_len;
836 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
837 packet->ip.hdr.tos = 0x00;
838 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
839 packet->ip.hdr.identification = htons(0xFFFF);
840 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
841 packet->ip.hdr.fragment = htons(0x0000);
842 packet->ip.hdr.ttl = 0xFF;
843 packet->ip.hdr.protocol = protocol;
844 packet->ip.hdr.hdr_checksum = htons(0x0000);
845 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
846 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
848 if (unreachable) {
849 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
850 packet->ip.p.icmp.code = 0x01; /* host unreachable */
851 packet->ip.p.icmp.checksum = htons(0x0000);
852 packet->ip.p.icmp.unused = htonl(0x00000000);
854 /* set the ip header in the ICMP payload */
855 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
856 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
857 packet->ip.hdr.tos = 0x00;
858 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
859 packet->ip.hdr.identification = htons(0xFFFF);
860 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
861 packet->ip.hdr.fragment = htons(0x0000);
862 packet->ip.hdr.ttl = 0xFF;
863 packet->ip.hdr.protocol = icmp_protocol;
864 packet->ip.hdr.hdr_checksum = htons(0x0000);
865 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
866 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
868 src_port = dest_addr->sin_port;
869 dest_port = src_addr->sin_port;
872 switch (socket_type) {
873 case SOCK_STREAM:
874 packet->ip.p.tcp.source_port = src_port;
875 packet->ip.p.tcp.dest_port = dest_port;
876 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
877 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
878 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
879 packet->ip.p.tcp.control = tcp_ctl;
880 packet->ip.p.tcp.window = htons(0x7FFF);
881 packet->ip.p.tcp.checksum = htons(0x0000);
882 packet->ip.p.tcp.urg = htons(0x0000);
884 break;
886 case SOCK_DGRAM:
887 packet->ip.p.udp.source_port = src_addr->sin_port;
888 packet->ip.p.udp.dest_port = dest_addr->sin_port;
889 packet->ip.p.udp.length = htons(8 + payload_len);
890 packet->ip.p.udp.checksum = htons(0x0000);
892 break;
895 if (payload && payload_len > 0) {
896 unsigned char *p = (unsigned char *)ret;
897 p += nonwire_len;
898 p += wire_hdr_len;
899 memcpy(p, payload, payload_len);
902 *_packet_len = packet_len - icmp_truncate_len;
903 return ret;
906 static int swrap_get_pcap_fd(const char *fname)
908 static int fd = -1;
910 if (fd != -1) return fd;
912 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
913 if (fd != -1) {
914 struct swrap_file_hdr file_hdr;
915 file_hdr.magic = 0xA1B2C3D4;
916 file_hdr.version_major = 0x0002;
917 file_hdr.version_minor = 0x0004;
918 file_hdr.timezone = 0x00000000;
919 file_hdr.sigfigs = 0x00000000;
920 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
921 file_hdr.link_type = 0x0065; /* 101 RAW IP */
923 write(fd, &file_hdr, sizeof(file_hdr));
924 return fd;
927 fd = open(fname, O_WRONLY|O_APPEND, 0644);
929 return fd;
932 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
933 enum swrap_packet_type type,
934 const void *buf, size_t len)
936 const struct sockaddr_in *src_addr;
937 const struct sockaddr_in *dest_addr;
938 const char *file_name;
939 unsigned long tcp_seq = 0;
940 unsigned long tcp_ack = 0;
941 unsigned char tcp_ctl = 0;
942 int unreachable = 0;
943 struct timeval tv;
944 struct swrap_packet *packet;
945 size_t packet_len = 0;
946 int fd;
948 file_name = socket_wrapper_pcap_file();
949 if (!file_name) {
950 return;
953 switch (si->family) {
954 case AF_INET:
955 #ifdef HAVE_IPV6
956 case AF_INET6:
957 #endif
958 break;
959 default:
960 return;
963 switch (type) {
964 case SWRAP_CONNECT_SEND:
965 if (si->type != SOCK_STREAM) return;
967 src_addr = (const struct sockaddr_in *)si->myname;
968 dest_addr = (const struct sockaddr_in *)addr;
970 tcp_seq = si->io.pck_snd;
971 tcp_ack = si->io.pck_rcv;
972 tcp_ctl = 0x02; /* SYN */
974 si->io.pck_snd += 1;
976 break;
978 case SWRAP_CONNECT_RECV:
979 if (si->type != SOCK_STREAM) return;
981 dest_addr = (const struct sockaddr_in *)si->myname;
982 src_addr = (const struct sockaddr_in *)addr;
984 tcp_seq = si->io.pck_rcv;
985 tcp_ack = si->io.pck_snd;
986 tcp_ctl = 0x12; /** SYN,ACK */
988 si->io.pck_rcv += 1;
990 break;
992 case SWRAP_CONNECT_UNREACH:
993 if (si->type != SOCK_STREAM) return;
995 dest_addr = (const struct sockaddr_in *)si->myname;
996 src_addr = (const struct sockaddr_in *)addr;
998 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
999 tcp_seq = si->io.pck_snd - 1;
1000 tcp_ack = si->io.pck_rcv;
1001 tcp_ctl = 0x02; /* SYN */
1002 unreachable = 1;
1004 break;
1006 case SWRAP_CONNECT_ACK:
1007 if (si->type != SOCK_STREAM) return;
1009 src_addr = (const struct sockaddr_in *)si->myname;
1010 dest_addr = (const struct sockaddr_in *)addr;
1012 tcp_seq = si->io.pck_snd;
1013 tcp_ack = si->io.pck_rcv;
1014 tcp_ctl = 0x10; /* ACK */
1016 break;
1018 case SWRAP_ACCEPT_SEND:
1019 if (si->type != SOCK_STREAM) return;
1021 dest_addr = (const struct sockaddr_in *)si->myname;
1022 src_addr = (const struct sockaddr_in *)addr;
1024 tcp_seq = si->io.pck_rcv;
1025 tcp_ack = si->io.pck_snd;
1026 tcp_ctl = 0x02; /* SYN */
1028 si->io.pck_rcv += 1;
1030 break;
1032 case SWRAP_ACCEPT_RECV:
1033 if (si->type != SOCK_STREAM) return;
1035 src_addr = (const struct sockaddr_in *)si->myname;
1036 dest_addr = (const struct sockaddr_in *)addr;
1038 tcp_seq = si->io.pck_snd;
1039 tcp_ack = si->io.pck_rcv;
1040 tcp_ctl = 0x12; /* SYN,ACK */
1042 si->io.pck_snd += 1;
1044 break;
1046 case SWRAP_ACCEPT_ACK:
1047 if (si->type != SOCK_STREAM) return;
1049 dest_addr = (const struct sockaddr_in *)si->myname;
1050 src_addr = (const struct sockaddr_in *)addr;
1052 tcp_seq = si->io.pck_rcv;
1053 tcp_ack = si->io.pck_snd;
1054 tcp_ctl = 0x10; /* ACK */
1056 break;
1058 case SWRAP_SEND:
1059 src_addr = (const struct sockaddr_in *)si->myname;
1060 dest_addr = (const struct sockaddr_in *)si->peername;
1062 tcp_seq = si->io.pck_snd;
1063 tcp_ack = si->io.pck_rcv;
1064 tcp_ctl = 0x18; /* PSH,ACK */
1066 si->io.pck_snd += len;
1068 break;
1070 case SWRAP_SEND_RST:
1071 dest_addr = (const struct sockaddr_in *)si->myname;
1072 src_addr = (const struct sockaddr_in *)si->peername;
1074 if (si->type == SOCK_DGRAM) {
1075 swrap_dump_packet(si, si->peername,
1076 SWRAP_SENDTO_UNREACH,
1077 buf, len);
1078 return;
1081 tcp_seq = si->io.pck_rcv;
1082 tcp_ack = si->io.pck_snd;
1083 tcp_ctl = 0x14; /** RST,ACK */
1085 break;
1087 case SWRAP_PENDING_RST:
1088 dest_addr = (const struct sockaddr_in *)si->myname;
1089 src_addr = (const struct sockaddr_in *)si->peername;
1091 if (si->type == SOCK_DGRAM) {
1092 return;
1095 tcp_seq = si->io.pck_rcv;
1096 tcp_ack = si->io.pck_snd;
1097 tcp_ctl = 0x14; /* RST,ACK */
1099 break;
1101 case SWRAP_RECV:
1102 dest_addr = (const struct sockaddr_in *)si->myname;
1103 src_addr = (const struct sockaddr_in *)si->peername;
1105 tcp_seq = si->io.pck_rcv;
1106 tcp_ack = si->io.pck_snd;
1107 tcp_ctl = 0x18; /* PSH,ACK */
1109 si->io.pck_rcv += len;
1111 break;
1113 case SWRAP_RECV_RST:
1114 dest_addr = (const struct sockaddr_in *)si->myname;
1115 src_addr = (const struct sockaddr_in *)si->peername;
1117 if (si->type == SOCK_DGRAM) {
1118 return;
1121 tcp_seq = si->io.pck_rcv;
1122 tcp_ack = si->io.pck_snd;
1123 tcp_ctl = 0x14; /* RST,ACK */
1125 break;
1127 case SWRAP_SENDTO:
1128 src_addr = (const struct sockaddr_in *)si->myname;
1129 dest_addr = (const struct sockaddr_in *)addr;
1131 si->io.pck_snd += len;
1133 break;
1135 case SWRAP_SENDTO_UNREACH:
1136 dest_addr = (const struct sockaddr_in *)si->myname;
1137 src_addr = (const struct sockaddr_in *)addr;
1139 unreachable = 1;
1141 break;
1143 case SWRAP_RECVFROM:
1144 dest_addr = (const struct sockaddr_in *)si->myname;
1145 src_addr = (const struct sockaddr_in *)addr;
1147 si->io.pck_rcv += len;
1149 break;
1151 case SWRAP_CLOSE_SEND:
1152 if (si->type != SOCK_STREAM) return;
1154 src_addr = (const struct sockaddr_in *)si->myname;
1155 dest_addr = (const struct sockaddr_in *)si->peername;
1157 tcp_seq = si->io.pck_snd;
1158 tcp_ack = si->io.pck_rcv;
1159 tcp_ctl = 0x11; /* FIN, ACK */
1161 si->io.pck_snd += 1;
1163 break;
1165 case SWRAP_CLOSE_RECV:
1166 if (si->type != SOCK_STREAM) return;
1168 dest_addr = (const struct sockaddr_in *)si->myname;
1169 src_addr = (const struct sockaddr_in *)si->peername;
1171 tcp_seq = si->io.pck_rcv;
1172 tcp_ack = si->io.pck_snd;
1173 tcp_ctl = 0x11; /* FIN,ACK */
1175 si->io.pck_rcv += 1;
1177 break;
1179 case SWRAP_CLOSE_ACK:
1180 if (si->type != SOCK_STREAM) return;
1182 src_addr = (const struct sockaddr_in *)si->myname;
1183 dest_addr = (const struct sockaddr_in *)si->peername;
1185 tcp_seq = si->io.pck_snd;
1186 tcp_ack = si->io.pck_rcv;
1187 tcp_ctl = 0x10; /* ACK */
1189 break;
1190 default:
1191 return;
1194 swrapGetTimeOfDay(&tv);
1196 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1197 (const unsigned char *)buf, len,
1198 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1199 &packet_len);
1200 if (!packet) {
1201 return;
1204 fd = swrap_get_pcap_fd(file_name);
1205 if (fd != -1) {
1206 write(fd, packet, packet_len);
1209 free(packet);
1212 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1214 struct socket_info *si;
1215 int fd;
1217 if (!socket_wrapper_dir()) {
1218 return real_socket(family, type, protocol);
1221 switch (family) {
1222 case AF_INET:
1223 #ifdef HAVE_IPV6
1224 case AF_INET6:
1225 #endif
1226 break;
1227 case AF_UNIX:
1228 return real_socket(family, type, protocol);
1229 default:
1230 errno = EAFNOSUPPORT;
1231 return -1;
1234 switch (type) {
1235 case SOCK_STREAM:
1236 break;
1237 case SOCK_DGRAM:
1238 break;
1239 default:
1240 errno = EPROTONOSUPPORT;
1241 return -1;
1244 #if 0
1245 switch (protocol) {
1246 case 0:
1247 break;
1248 default:
1249 errno = EPROTONOSUPPORT;
1250 return -1;
1252 #endif
1254 fd = real_socket(AF_UNIX, type, 0);
1256 if (fd == -1) return -1;
1258 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1260 si->family = family;
1261 si->type = type;
1262 si->protocol = protocol;
1263 si->fd = fd;
1265 SWRAP_DLIST_ADD(sockets, si);
1267 return si->fd;
1270 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1272 struct socket_info *parent_si, *child_si;
1273 int fd;
1274 struct sockaddr_un un_addr;
1275 socklen_t un_addrlen = sizeof(un_addr);
1276 struct sockaddr_un un_my_addr;
1277 socklen_t un_my_addrlen = sizeof(un_my_addr);
1278 struct sockaddr *my_addr;
1279 socklen_t my_addrlen, len;
1280 int ret;
1282 parent_si = find_socket_info(s);
1283 if (!parent_si) {
1284 return real_accept(s, addr, addrlen);
1288 * assume out sockaddr have the same size as the in parent
1289 * socket family
1291 my_addrlen = socket_length(parent_si->family);
1292 if (my_addrlen < 0) {
1293 errno = EINVAL;
1294 return -1;
1297 my_addr = malloc(my_addrlen);
1298 if (my_addr == NULL) {
1299 return -1;
1302 memset(&un_addr, 0, sizeof(un_addr));
1303 memset(&un_my_addr, 0, sizeof(un_my_addr));
1305 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1306 if (ret == -1) {
1307 free(my_addr);
1308 return ret;
1311 fd = ret;
1313 len = my_addrlen;
1314 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1315 parent_si->family, my_addr, &len);
1316 if (ret == -1) {
1317 free(my_addr);
1318 close(fd);
1319 return ret;
1322 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1323 memset(child_si, 0, sizeof(*child_si));
1325 child_si->fd = fd;
1326 child_si->family = parent_si->family;
1327 child_si->type = parent_si->type;
1328 child_si->protocol = parent_si->protocol;
1329 child_si->bound = 1;
1330 child_si->is_server = 1;
1332 child_si->peername_len = len;
1333 child_si->peername = sockaddr_dup(my_addr, len);
1335 if (addr != NULL && addrlen != NULL) {
1336 *addrlen = len;
1337 if (*addrlen >= len)
1338 memcpy(addr, my_addr, len);
1339 *addrlen = 0;
1342 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1343 if (ret == -1) {
1344 free(child_si);
1345 close(fd);
1346 return ret;
1349 len = my_addrlen;
1350 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1351 child_si->family, my_addr, &len);
1352 if (ret == -1) {
1353 free(child_si);
1354 free(my_addr);
1355 close(fd);
1356 return ret;
1359 child_si->myname_len = len;
1360 child_si->myname = sockaddr_dup(my_addr, len);
1361 free(my_addr);
1363 SWRAP_DLIST_ADD(sockets, child_si);
1365 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1366 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1367 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1369 return fd;
1372 static int autobind_start_init;
1373 static int autobind_start;
1375 /* using sendto() or connect() on an unbound socket would give the
1376 recipient no way to reply, as unlike UDP and TCP, a unix domain
1377 socket can't auto-assign emphemeral port numbers, so we need to
1378 assign it here */
1379 static int swrap_auto_bind(struct socket_info *si)
1381 struct sockaddr_un un_addr;
1382 int i;
1383 char type;
1384 int ret;
1385 int port;
1386 struct stat st;
1388 if (autobind_start_init != 1) {
1389 autobind_start_init = 1;
1390 autobind_start = getpid();
1391 autobind_start %= 50000;
1392 autobind_start += 10000;
1395 un_addr.sun_family = AF_UNIX;
1397 switch (si->family) {
1398 case AF_INET: {
1399 struct sockaddr_in in;
1401 switch (si->type) {
1402 case SOCK_STREAM:
1403 type = SOCKET_TYPE_CHAR_TCP;
1404 break;
1405 case SOCK_DGRAM:
1406 type = SOCKET_TYPE_CHAR_UDP;
1407 break;
1408 default:
1409 errno = ESOCKTNOSUPPORT;
1410 return -1;
1413 memset(&in, 0, sizeof(in));
1414 in.sin_family = AF_INET;
1415 in.sin_addr.s_addr = htonl(127<<24 |
1416 socket_wrapper_default_iface());
1418 si->myname_len = sizeof(in);
1419 si->myname = sockaddr_dup(&in, si->myname_len);
1420 break;
1422 #ifdef HAVE_IPV6
1423 case AF_INET6: {
1424 struct sockaddr_in6 in6;
1426 switch (si->type) {
1427 case SOCK_STREAM:
1428 type = SOCKET_TYPE_CHAR_TCP_V6;
1429 break;
1430 case SOCK_DGRAM:
1431 type = SOCKET_TYPE_CHAR_UDP_V6;
1432 break;
1433 default:
1434 errno = ESOCKTNOSUPPORT;
1435 return -1;
1438 memset(&in6, 0, sizeof(in6));
1439 in6.sin6_family = AF_INET6;
1440 in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1441 si->myname_len = sizeof(in6);
1442 si->myname = sockaddr_dup(&in6, si->myname_len);
1443 break;
1445 #endif
1446 default:
1447 errno = ESOCKTNOSUPPORT;
1448 return -1;
1451 if (autobind_start > 60000) {
1452 autobind_start = 10000;
1455 for (i=0;i<1000;i++) {
1456 port = autobind_start + i;
1457 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1458 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1459 type, socket_wrapper_default_iface(), port);
1460 if (stat(un_addr.sun_path, &st) == 0) continue;
1462 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1463 if (ret == -1) return ret;
1465 si->tmp_path = strdup(un_addr.sun_path);
1466 si->bound = 1;
1467 autobind_start = port + 1;
1468 break;
1470 if (i == 1000) {
1471 errno = ENFILE;
1472 return -1;
1475 set_port(si->family, port, si->myname);
1477 return 0;
1481 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1483 int ret;
1484 struct sockaddr_un un_addr;
1485 struct socket_info *si = find_socket_info(s);
1487 if (!si) {
1488 return real_connect(s, serv_addr, addrlen);
1491 if (si->bound == 0) {
1492 ret = swrap_auto_bind(si);
1493 if (ret == -1) return -1;
1496 if (si->family != serv_addr->sa_family) {
1497 errno = EINVAL;
1498 return -1;
1501 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1502 if (ret == -1) return -1;
1504 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1506 ret = real_connect(s, (struct sockaddr *)&un_addr,
1507 sizeof(struct sockaddr_un));
1509 /* to give better errors */
1510 if (ret == -1 && errno == ENOENT) {
1511 errno = EHOSTUNREACH;
1514 if (ret == 0) {
1515 si->peername_len = addrlen;
1516 si->peername = sockaddr_dup(serv_addr, addrlen);
1518 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1519 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1520 } else {
1521 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1524 return ret;
1527 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1529 int ret;
1530 struct sockaddr_un un_addr;
1531 struct socket_info *si = find_socket_info(s);
1533 if (!si) {
1534 return real_bind(s, myaddr, addrlen);
1537 si->myname_len = addrlen;
1538 si->myname = sockaddr_dup(myaddr, addrlen);
1540 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1541 if (ret == -1) return -1;
1543 unlink(un_addr.sun_path);
1545 ret = real_bind(s, (struct sockaddr *)&un_addr,
1546 sizeof(struct sockaddr_un));
1548 if (ret == 0) {
1549 si->bound = 1;
1552 return ret;
1555 _PUBLIC_ int swrap_listen(int s, int backlog)
1557 int ret;
1558 struct socket_info *si = find_socket_info(s);
1560 if (!si) {
1561 return real_listen(s, backlog);
1564 ret = real_listen(s, backlog);
1566 return ret;
1569 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1571 struct socket_info *si = find_socket_info(s);
1573 if (!si) {
1574 return real_getpeername(s, name, addrlen);
1577 if (!si->peername)
1579 errno = ENOTCONN;
1580 return -1;
1583 memcpy(name, si->peername, si->peername_len);
1584 *addrlen = si->peername_len;
1586 return 0;
1589 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1591 struct socket_info *si = find_socket_info(s);
1593 if (!si) {
1594 return real_getsockname(s, name, addrlen);
1597 memcpy(name, si->myname, si->myname_len);
1598 *addrlen = si->myname_len;
1600 return 0;
1603 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1605 struct socket_info *si = find_socket_info(s);
1607 if (!si) {
1608 return real_getsockopt(s, level, optname, optval, optlen);
1611 if (level == SOL_SOCKET) {
1612 return real_getsockopt(s, level, optname, optval, optlen);
1615 errno = ENOPROTOOPT;
1616 return -1;
1619 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1621 struct socket_info *si = find_socket_info(s);
1623 if (!si) {
1624 return real_setsockopt(s, level, optname, optval, optlen);
1627 if (level == SOL_SOCKET) {
1628 return real_setsockopt(s, level, optname, optval, optlen);
1631 switch (si->family) {
1632 case AF_INET:
1633 return 0;
1634 default:
1635 errno = ENOPROTOOPT;
1636 return -1;
1640 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1642 struct sockaddr_un un_addr;
1643 socklen_t un_addrlen = sizeof(un_addr);
1644 int ret;
1645 struct socket_info *si = find_socket_info(s);
1647 if (!si) {
1648 return real_recvfrom(s, buf, len, flags, from, fromlen);
1651 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1652 memset(&un_addr, 0, sizeof(un_addr));
1653 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1654 if (ret == -1)
1655 return ret;
1657 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1658 si->family, from, fromlen) == -1) {
1659 return -1;
1662 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1664 return ret;
1668 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1670 struct sockaddr_un un_addr;
1671 int ret;
1672 struct socket_info *si = find_socket_info(s);
1673 int bcast = 0;
1675 if (!si) {
1676 return real_sendto(s, buf, len, flags, to, tolen);
1679 switch (si->type) {
1680 case SOCK_STREAM:
1681 ret = real_send(s, buf, len, flags);
1682 break;
1683 case SOCK_DGRAM:
1684 if (si->bound == 0) {
1685 ret = swrap_auto_bind(si);
1686 if (ret == -1) return -1;
1689 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1690 if (ret == -1) return -1;
1692 if (bcast) {
1693 struct stat st;
1694 unsigned int iface;
1695 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1696 char type;
1698 type = SOCKET_TYPE_CHAR_UDP;
1700 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1701 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1702 socket_wrapper_dir(), type, iface, prt);
1703 if (stat(un_addr.sun_path, &st) != 0) continue;
1705 /* ignore the any errors in broadcast sends */
1706 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1709 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1711 return len;
1714 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1715 break;
1716 default:
1717 ret = -1;
1718 errno = EHOSTUNREACH;
1719 break;
1722 /* to give better errors */
1723 if (ret == -1 && errno == ENOENT) {
1724 errno = EHOSTUNREACH;
1727 if (ret == -1) {
1728 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1729 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1730 } else {
1731 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1734 return ret;
1737 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1739 int ret;
1740 struct socket_info *si = find_socket_info(s);
1741 int value;
1743 if (!si) {
1744 return real_ioctl(s, r, p);
1747 ret = real_ioctl(s, r, p);
1749 switch (r) {
1750 case FIONREAD:
1751 value = *((int *)p);
1752 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1753 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1754 } else if (value == 0) { /* END OF FILE */
1755 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1757 break;
1760 return ret;
1763 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1765 int ret;
1766 struct socket_info *si = find_socket_info(s);
1768 if (!si) {
1769 return real_recv(s, buf, len, flags);
1772 ret = real_recv(s, buf, len, flags);
1773 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1774 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1775 } else if (ret == 0) { /* END OF FILE */
1776 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1777 } else {
1778 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1781 return ret;
1785 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1787 int ret;
1788 struct socket_info *si = find_socket_info(s);
1790 if (!si) {
1791 return real_send(s, buf, len, flags);
1794 ret = real_send(s, buf, len, flags);
1796 if (ret == -1) {
1797 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1798 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1799 } else {
1800 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1803 return ret;
1806 _PUBLIC_ int swrap_close(int fd)
1808 struct socket_info *si = find_socket_info(fd);
1809 int ret;
1811 if (!si) {
1812 return real_close(fd);
1815 SWRAP_DLIST_REMOVE(sockets, si);
1817 if (si->myname && si->peername) {
1818 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1821 ret = real_close(fd);
1823 if (si->myname && si->peername) {
1824 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1825 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1828 if (si->path) free(si->path);
1829 if (si->myname) free(si->myname);
1830 if (si->peername) free(si->peername);
1831 if (si->tmp_path) {
1832 unlink(si->tmp_path);
1833 free(si->tmp_path);
1835 free(si);
1837 return ret;
1840 static int
1841 dup_internal(const struct socket_info *si_oldd, int fd)
1843 struct socket_info *si_newd;
1845 si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1847 si_newd->fd = fd;
1849 si_newd->family = si_oldd->family;
1850 si_newd->type = si_oldd->type;
1851 si_newd->protocol = si_oldd->protocol;
1852 si_newd->bound = si_oldd->bound;
1853 si_newd->bcast = si_oldd->bcast;
1854 if (si_oldd->path)
1855 si_newd->path = strdup(si_oldd->path);
1856 if (si_oldd->tmp_path)
1857 si_newd->tmp_path = strdup(si_oldd->tmp_path);
1858 si_newd->myname =
1859 sockaddr_dup(si_oldd->myname, si_oldd->myname_len);
1860 si_newd->myname_len = si_oldd->myname_len;
1861 si_newd->peername =
1862 sockaddr_dup(si_oldd->peername, si_oldd->peername_len);
1863 si_newd->peername_len = si_oldd->peername_len;
1865 si_newd->io = si_oldd->io;
1867 SWRAP_DLIST_ADD(sockets, si_newd);
1869 return fd;
1873 _PUBLIC_ int swrap_dup(int oldd)
1875 struct socket_info *si;
1876 int fd;
1878 si = find_socket_info(oldd);
1879 if (si == NULL)
1880 return real_dup(oldd);
1882 fd = real_dup(si->fd);
1883 if (fd < 0)
1884 return fd;
1886 return dup_internal(si, fd);
1890 _PUBLIC_ int swrap_dup2(int oldd, int newd)
1892 struct socket_info *si_newd, *si_oldd;
1893 int fd;
1895 if (newd == oldd)
1896 return newd;
1898 si_oldd = find_socket_info(oldd);
1899 si_newd = find_socket_info(newd);
1901 if (si_oldd == NULL && si_newd == NULL)
1902 return real_dup2(oldd, newd);
1904 fd = real_dup2(si_oldd->fd, newd);
1905 if (fd < 0)
1906 return fd;
1908 /* close new socket first */
1909 if (si_newd)
1910 swrap_close(newd);
1912 return dup_internal(si_oldd, fd);