xref: /freebsd/crypto/heimdal/lib/roken/socket_wrapper.c (revision 7aa383846770374466b1dcb2cefd71bde9acf463)
1 /*
2  * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3  * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
4  *
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:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
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.
17  *
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.
21  *
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.
33  *
34  */
35 
36 /*
37    Socket wrapper library. Passes all socket communication over
38    unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
39    is set.
40 */
41 
42 #define SOCKET_WRAPPER_NOT_REPLACE
43 
44 #ifdef _SAMBA_BUILD_
45 
46 #include "includes.h"
47 #include "system/network.h"
48 #include "system/filesys.h"
49 
50 #ifdef malloc
51 #undef malloc
52 #endif
53 #ifdef calloc
54 #undef calloc
55 #endif
56 #ifdef strdup
57 #undef strdup
58 #endif
59 
60 #else /* _SAMBA_BUILD_ */
61 
62 #ifdef HAVE_CONFIG_H
63 #include <config.h>
64 #endif
65 #undef SOCKET_WRAPPER_REPLACE
66 
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"
92 
93 #include "socket_wrapper.h"
94 
95 #define HAVE_GETTIMEOFDAY_TZ 1
96 
97 #define _PUBLIC_
98 
99 #endif
100 
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); \
111 	} \
112 } while (0)
113 
114 #define SWRAP_DLIST_REMOVE(list,item) do { \
115 	if ((list) == (item)) { \
116 		(list)		= (item)->next; \
117 		if (list) { \
118 			(list)->prev	= NULL; \
119 		} \
120 	} else { \
121 		if ((item)->prev) { \
122 			(item)->prev->next	= (item)->next; \
123 		} \
124 		if ((item)->next) { \
125 			(item)->next->prev	= (item)->prev; \
126 		} \
127 	} \
128 	(item)->prev	= NULL; \
129 	(item)->next	= NULL; \
130 } while (0)
131 
132 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
133  * for now */
134 #define REWRITE_CALLS
135 
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
155 
156 #ifdef HAVE_GETTIMEOFDAY_TZ
157 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
158 #else
159 #define swrapGetTimeOfDay(tval)	gettimeofday(tval)
160 #endif
161 
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()
165 
166    with this format we have 8 chars left for the directory name
167 */
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'
173 
174 #define MAX_WRAPPED_INTERFACES 16
175 
176 #define SW_IPV6_ADDRESS 1
177 
178 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
179 {
180 	struct sockaddr *ret = (struct sockaddr *)malloc(len);
181 	memcpy(ret, data, len);
182 	return ret;
183 }
184 
185 static void set_port(int family, int prt, struct sockaddr *addr)
186 {
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
196 	}
197 }
198 
199 static int socket_length(int family)
200 {
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
208 	}
209 	return -1;
210 }
211 
212 
213 
214 struct socket_info
215 {
216 	int fd;
217 
218 	int family;
219 	int type;
220 	int protocol;
221 	int bound;
222 	int bcast;
223 	int is_server;
224 
225 	char *path;
226 	char *tmp_path;
227 
228 	struct sockaddr *myname;
229 	socklen_t myname_len;
230 
231 	struct sockaddr *peername;
232 	socklen_t peername_len;
233 
234 	struct {
235 		unsigned long pck_snd;
236 		unsigned long pck_rcv;
237 	} io;
238 
239 	struct socket_info *prev, *next;
240 };
241 
242 static struct socket_info *sockets;
243 
244 
245 static const char *socket_wrapper_dir(void)
246 {
247 	const char *s = getenv("SOCKET_WRAPPER_DIR");
248 	if (s == NULL) {
249 		return NULL;
250 	}
251 	if (strncmp(s, "./", 2) == 0) {
252 		s += 2;
253 	}
254 	return s;
255 }
256 
257 static unsigned int socket_wrapper_default_iface(void)
258 {
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;
265 			}
266 		}
267 	}
268 
269 	return 1;/* 127.0.0.1 */
270 }
271 
272 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
273 {
274 	unsigned int iface;
275 	unsigned int prt;
276 	const char *p;
277 	char type;
278 
279 	p = strrchr(un->sun_path, '/');
280 	if (p) p++; else p = un->sun_path;
281 
282 	if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
283 		errno = EINVAL;
284 		return -1;
285 	}
286 
287 	if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
288 		errno = EINVAL;
289 		return -1;
290 	}
291 
292 	if (prt > 0xFFFF) {
293 		errno = EINVAL;
294 		return -1;
295 	}
296 
297 	switch(type) {
298 	case SOCKET_TYPE_CHAR_TCP:
299 	case SOCKET_TYPE_CHAR_UDP: {
300 		struct sockaddr_in *in2 = (struct sockaddr_in *)in;
301 
302 		if ((*len) < sizeof(*in2)) {
303 		    errno = EINVAL;
304 		    return -1;
305 		}
306 
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);
311 
312 		*len = sizeof(*in2);
313 		break;
314 	}
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;
319 
320 		if ((*len) < sizeof(*in2)) {
321 			errno = EINVAL;
322 			return -1;
323 		}
324 
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);
329 
330 		*len = sizeof(*in2);
331 		break;
332 	}
333 #endif
334 	default:
335 		errno = EINVAL;
336 		return -1;
337 	}
338 
339 	return 0;
340 }
341 
342 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
343 				int *bcast)
344 {
345 	char type = '\0';
346 	unsigned int prt;
347 	unsigned int iface;
348 	int is_bcast = 0;
349 
350 	if (bcast) *bcast = 0;
351 
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';
360 
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;
370 		}
371 
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;
391 		}
392 		if (bcast) *bcast = is_bcast;
393 		break;
394 	}
395 #ifdef HAVE_IPV6
396 	case AF_INET6: {
397 		const struct sockaddr_in6 *in =
398 		    (const struct sockaddr_in6 *)inaddr;
399 
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;
407 		}
408 
409 		/* XXX no multicast/broadcast */
410 
411 		prt = ntohs(in->sin6_port);
412 		iface = SW_IPV6_ADDRESS;
413 
414 		break;
415 	}
416 #endif
417 	default:
418 		errno = ENETUNREACH;
419 		return -1;
420 	}
421 
422 	if (prt == 0) {
423 		errno = EINVAL;
424 		return -1;
425 	}
426 
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;
432 	}
433 
434 	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
435 		 socket_wrapper_dir(), type, iface, prt);
436 
437 	return 0;
438 }
439 
440 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
441 			       int *bcast)
442 {
443 	char type = '\0';
444 	unsigned int prt;
445 	unsigned int iface;
446 	struct stat st;
447 	int is_bcast = 0;
448 
449 	if (bcast) *bcast = 0;
450 
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';
460 
461 		prt = ntohs(in->sin_port);
462 
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;
474 		}
475 
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;
499 		}
500 		break;
501 	}
502 #ifdef HAVE_IPV6
503 	case AF_INET6: {
504 		const struct sockaddr_in6 *in =
505 		    (const struct sockaddr_in6 *)inaddr;
506 
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;
514 		}
515 
516 		/* XXX no multicast/broadcast */
517 
518 		prt = ntohs(in->sin6_port);
519 		iface = SW_IPV6_ADDRESS;
520 
521 		break;
522 	}
523 #endif
524 	default:
525 		errno = ENETUNREACH;
526 		return -1;
527 	}
528 
529 
530 	if (bcast) *bcast = is_bcast;
531 
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;
538 
539 			set_port(si->family, prt, si->myname);
540 		}
541 	}
542 
543 	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
544 		 socket_wrapper_dir(), type, iface, prt);
545 	return 0;
546 }
547 
548 static struct socket_info *find_socket_info(int fd)
549 {
550 	struct socket_info *i;
551 	for (i = sockets; i; i = i->next) {
552 		if (i->fd == fd)
553 			return i;
554 	}
555 
556 	return NULL;
557 }
558 
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)
561 {
562 	if (!out_addr)
563 		return 0;
564 
565 	out_addr->sun_family = AF_UNIX;
566 
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;
579 		}
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);
584 		}
585 	default:
586 		break;
587 	}
588 
589 	errno = EAFNOSUPPORT;
590 	return -1;
591 }
592 
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)
599 {
600 	if (out_addr == NULL || out_addrlen == NULL)
601 		return 0;
602 
603 	if (un_addrlen == 0) {
604 		*out_addrlen = 0;
605 		return 0;
606 	}
607 
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;
620 		}
621 		return convert_un_in(in_addr, out_addr, out_addrlen);
622 	default:
623 		break;
624 	}
625 
626 	errno = EAFNOSUPPORT;
627 	return -1;
628 }
629 
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
649 };
650 
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;
660 };
661 #define SWRAP_FILE_HDR_SIZE 24
662 
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
671 
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
687 
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;
717 };
718 #define SWRAP_PACKET_SIZE 56
719 
720 static const char *socket_wrapper_pcap_file(void)
721 {
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;
726 
727 	if (initialized == 1) {
728 		return s;
729 	}
730 	initialized = 1;
731 
732 	/*
733 	 * TODO: don't use the structs use plain buffer offsets
734 	 *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
735 	 *
736 	 * for now make sure we disable PCAP support
737 	 * if the struct has alignment!
738 	 */
739 	if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
740 		return NULL;
741 	}
742 	if (sizeof(p) != SWRAP_PACKET_SIZE) {
743 		return NULL;
744 	}
745 	if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
746 		return NULL;
747 	}
748 	if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
749 		return NULL;
750 	}
751 	if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
752 		return NULL;
753 	}
754 	if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
755 		return NULL;
756 	}
757 	if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
758 		return NULL;
759 	}
760 
761 	s = getenv("SOCKET_WRAPPER_PCAP_FILE");
762 	if (s == NULL) {
763 		return NULL;
764 	}
765 	if (strncmp(s, "./", 2) == 0) {
766 		s += 2;
767 	}
768 	return s;
769 }
770 
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)
782 {
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;
795 
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;
802 
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;
808 	}
809 
810 	if (unreachable) {
811 		icmp_protocol = protocol;
812 		protocol = 0x01; /* ICMP */
813 		if (wire_len > 64 ) {
814 			icmp_truncate_len = wire_len - 64;
815 		}
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;
819 	}
820 
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);
825 	}
826 	ret = (struct swrap_packet *)malloc(alloc_len);
827 	if (!ret) return NULL;
828 
829 	packet = ret;
830 
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;
835 
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;
847 
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);
853 
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;
867 
868 		src_port = dest_addr->sin_port;
869 		dest_port = src_addr->sin_port;
870 	}
871 
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);
883 
884 		break;
885 
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);
891 
892 		break;
893 	}
894 
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);
900 	}
901 
902 	*_packet_len = packet_len - icmp_truncate_len;
903 	return ret;
904 }
905 
906 static int swrap_get_pcap_fd(const char *fname)
907 {
908 	static int fd = -1;
909 
910 	if (fd != -1) return fd;
911 
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 */
922 
923 		write(fd, &file_hdr, sizeof(file_hdr));
924 		return fd;
925 	}
926 
927 	fd = open(fname, O_WRONLY|O_APPEND, 0644);
928 
929 	return fd;
930 }
931 
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)
935 {
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;
947 
948 	file_name = socket_wrapper_pcap_file();
949 	if (!file_name) {
950 		return;
951 	}
952 
953 	switch (si->family) {
954 	case AF_INET:
955 #ifdef HAVE_IPV6
956 	case AF_INET6:
957 #endif
958 		break;
959 	default:
960 		return;
961 	}
962 
963 	switch (type) {
964 	case SWRAP_CONNECT_SEND:
965 		if (si->type != SOCK_STREAM) return;
966 
967 		src_addr = (const struct sockaddr_in *)si->myname;
968 		dest_addr = (const struct sockaddr_in *)addr;
969 
970 		tcp_seq = si->io.pck_snd;
971 		tcp_ack = si->io.pck_rcv;
972 		tcp_ctl = 0x02; /* SYN */
973 
974 		si->io.pck_snd += 1;
975 
976 		break;
977 
978 	case SWRAP_CONNECT_RECV:
979 		if (si->type != SOCK_STREAM) return;
980 
981 		dest_addr = (const struct sockaddr_in *)si->myname;
982 		src_addr = (const struct sockaddr_in *)addr;
983 
984 		tcp_seq = si->io.pck_rcv;
985 		tcp_ack = si->io.pck_snd;
986 		tcp_ctl = 0x12; /** SYN,ACK */
987 
988 		si->io.pck_rcv += 1;
989 
990 		break;
991 
992 	case SWRAP_CONNECT_UNREACH:
993 		if (si->type != SOCK_STREAM) return;
994 
995 		dest_addr = (const struct sockaddr_in *)si->myname;
996 		src_addr = (const struct sockaddr_in *)addr;
997 
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;
1003 
1004 		break;
1005 
1006 	case SWRAP_CONNECT_ACK:
1007 		if (si->type != SOCK_STREAM) return;
1008 
1009 		src_addr = (const struct sockaddr_in *)si->myname;
1010 		dest_addr = (const struct sockaddr_in *)addr;
1011 
1012 		tcp_seq = si->io.pck_snd;
1013 		tcp_ack = si->io.pck_rcv;
1014 		tcp_ctl = 0x10; /* ACK */
1015 
1016 		break;
1017 
1018 	case SWRAP_ACCEPT_SEND:
1019 		if (si->type != SOCK_STREAM) return;
1020 
1021 		dest_addr = (const struct sockaddr_in *)si->myname;
1022 		src_addr = (const struct sockaddr_in *)addr;
1023 
1024 		tcp_seq = si->io.pck_rcv;
1025 		tcp_ack = si->io.pck_snd;
1026 		tcp_ctl = 0x02; /* SYN */
1027 
1028 		si->io.pck_rcv += 1;
1029 
1030 		break;
1031 
1032 	case SWRAP_ACCEPT_RECV:
1033 		if (si->type != SOCK_STREAM) return;
1034 
1035 		src_addr = (const struct sockaddr_in *)si->myname;
1036 		dest_addr = (const struct sockaddr_in *)addr;
1037 
1038 		tcp_seq = si->io.pck_snd;
1039 		tcp_ack = si->io.pck_rcv;
1040 		tcp_ctl = 0x12; /* SYN,ACK */
1041 
1042 		si->io.pck_snd += 1;
1043 
1044 		break;
1045 
1046 	case SWRAP_ACCEPT_ACK:
1047 		if (si->type != SOCK_STREAM) return;
1048 
1049 		dest_addr = (const struct sockaddr_in *)si->myname;
1050 		src_addr = (const struct sockaddr_in *)addr;
1051 
1052 		tcp_seq = si->io.pck_rcv;
1053 		tcp_ack = si->io.pck_snd;
1054 		tcp_ctl = 0x10; /* ACK */
1055 
1056 		break;
1057 
1058 	case SWRAP_SEND:
1059 		src_addr = (const struct sockaddr_in *)si->myname;
1060 		dest_addr = (const struct sockaddr_in *)si->peername;
1061 
1062 		tcp_seq = si->io.pck_snd;
1063 		tcp_ack = si->io.pck_rcv;
1064 		tcp_ctl = 0x18; /* PSH,ACK */
1065 
1066 		si->io.pck_snd += len;
1067 
1068 		break;
1069 
1070 	case SWRAP_SEND_RST:
1071 		dest_addr = (const struct sockaddr_in *)si->myname;
1072 		src_addr = (const struct sockaddr_in *)si->peername;
1073 
1074 		if (si->type == SOCK_DGRAM) {
1075 			swrap_dump_packet(si, si->peername,
1076 					  SWRAP_SENDTO_UNREACH,
1077 			      		  buf, len);
1078 			return;
1079 		}
1080 
1081 		tcp_seq = si->io.pck_rcv;
1082 		tcp_ack = si->io.pck_snd;
1083 		tcp_ctl = 0x14; /** RST,ACK */
1084 
1085 		break;
1086 
1087 	case SWRAP_PENDING_RST:
1088 		dest_addr = (const struct sockaddr_in *)si->myname;
1089 		src_addr = (const struct sockaddr_in *)si->peername;
1090 
1091 		if (si->type == SOCK_DGRAM) {
1092 			return;
1093 		}
1094 
1095 		tcp_seq = si->io.pck_rcv;
1096 		tcp_ack = si->io.pck_snd;
1097 		tcp_ctl = 0x14; /* RST,ACK */
1098 
1099 		break;
1100 
1101 	case SWRAP_RECV:
1102 		dest_addr = (const struct sockaddr_in *)si->myname;
1103 		src_addr = (const struct sockaddr_in *)si->peername;
1104 
1105 		tcp_seq = si->io.pck_rcv;
1106 		tcp_ack = si->io.pck_snd;
1107 		tcp_ctl = 0x18; /* PSH,ACK */
1108 
1109 		si->io.pck_rcv += len;
1110 
1111 		break;
1112 
1113 	case SWRAP_RECV_RST:
1114 		dest_addr = (const struct sockaddr_in *)si->myname;
1115 		src_addr = (const struct sockaddr_in *)si->peername;
1116 
1117 		if (si->type == SOCK_DGRAM) {
1118 			return;
1119 		}
1120 
1121 		tcp_seq = si->io.pck_rcv;
1122 		tcp_ack = si->io.pck_snd;
1123 		tcp_ctl = 0x14; /* RST,ACK */
1124 
1125 		break;
1126 
1127 	case SWRAP_SENDTO:
1128 		src_addr = (const struct sockaddr_in *)si->myname;
1129 		dest_addr = (const struct sockaddr_in *)addr;
1130 
1131 		si->io.pck_snd += len;
1132 
1133 		break;
1134 
1135 	case SWRAP_SENDTO_UNREACH:
1136 		dest_addr = (const struct sockaddr_in *)si->myname;
1137 		src_addr = (const struct sockaddr_in *)addr;
1138 
1139 		unreachable = 1;
1140 
1141 		break;
1142 
1143 	case SWRAP_RECVFROM:
1144 		dest_addr = (const struct sockaddr_in *)si->myname;
1145 		src_addr = (const struct sockaddr_in *)addr;
1146 
1147 		si->io.pck_rcv += len;
1148 
1149 		break;
1150 
1151 	case SWRAP_CLOSE_SEND:
1152 		if (si->type != SOCK_STREAM) return;
1153 
1154 		src_addr = (const struct sockaddr_in *)si->myname;
1155 		dest_addr = (const struct sockaddr_in *)si->peername;
1156 
1157 		tcp_seq = si->io.pck_snd;
1158 		tcp_ack = si->io.pck_rcv;
1159 		tcp_ctl = 0x11; /* FIN, ACK */
1160 
1161 		si->io.pck_snd += 1;
1162 
1163 		break;
1164 
1165 	case SWRAP_CLOSE_RECV:
1166 		if (si->type != SOCK_STREAM) return;
1167 
1168 		dest_addr = (const struct sockaddr_in *)si->myname;
1169 		src_addr = (const struct sockaddr_in *)si->peername;
1170 
1171 		tcp_seq = si->io.pck_rcv;
1172 		tcp_ack = si->io.pck_snd;
1173 		tcp_ctl = 0x11; /* FIN,ACK */
1174 
1175 		si->io.pck_rcv += 1;
1176 
1177 		break;
1178 
1179 	case SWRAP_CLOSE_ACK:
1180 		if (si->type != SOCK_STREAM) return;
1181 
1182 		src_addr = (const struct sockaddr_in *)si->myname;
1183 		dest_addr = (const struct sockaddr_in *)si->peername;
1184 
1185 		tcp_seq = si->io.pck_snd;
1186 		tcp_ack = si->io.pck_rcv;
1187 		tcp_ctl = 0x10; /* ACK */
1188 
1189 		break;
1190 	default:
1191 		return;
1192 	}
1193 
1194 	swrapGetTimeOfDay(&tv);
1195 
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;
1202 	}
1203 
1204 	fd = swrap_get_pcap_fd(file_name);
1205 	if (fd != -1) {
1206 		write(fd, packet, packet_len);
1207 	}
1208 
1209 	free(packet);
1210 }
1211 
1212 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1213 {
1214 	struct socket_info *si;
1215 	int fd;
1216 
1217 	if (!socket_wrapper_dir()) {
1218 		return real_socket(family, type, protocol);
1219 	}
1220 
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;
1232 	}
1233 
1234 	switch (type) {
1235 	case SOCK_STREAM:
1236 		break;
1237 	case SOCK_DGRAM:
1238 		break;
1239 	default:
1240 		errno = EPROTONOSUPPORT;
1241 		return -1;
1242 	}
1243 
1244 #if 0
1245 	switch (protocol) {
1246 	case 0:
1247 		break;
1248 	default:
1249 		errno = EPROTONOSUPPORT;
1250 		return -1;
1251 	}
1252 #endif
1253 
1254 	fd = real_socket(AF_UNIX, type, 0);
1255 
1256 	if (fd == -1) return -1;
1257 
1258 	si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1259 
1260 	si->family = family;
1261 	si->type = type;
1262 	si->protocol = protocol;
1263 	si->fd = fd;
1264 
1265 	SWRAP_DLIST_ADD(sockets, si);
1266 
1267 	return si->fd;
1268 }
1269 
1270 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1271 {
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;
1281 
1282 	parent_si = find_socket_info(s);
1283 	if (!parent_si) {
1284 		return real_accept(s, addr, addrlen);
1285 	}
1286 
1287 	/*
1288 	 * assume out sockaddr have the same size as the in parent
1289 	 * socket family
1290 	 */
1291 	my_addrlen = socket_length(parent_si->family);
1292 	if (my_addrlen < 0) {
1293 		errno = EINVAL;
1294 		return -1;
1295 	}
1296 
1297 	my_addr = malloc(my_addrlen);
1298 	if (my_addr == NULL) {
1299 		return -1;
1300 	}
1301 
1302 	memset(&un_addr, 0, sizeof(un_addr));
1303 	memset(&un_my_addr, 0, sizeof(un_my_addr));
1304 
1305 	ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1306 	if (ret == -1) {
1307 		free(my_addr);
1308 		return ret;
1309 	}
1310 
1311 	fd = ret;
1312 
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;
1320 	}
1321 
1322 	child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1323 	memset(child_si, 0, sizeof(*child_si));
1324 
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;
1331 
1332 	child_si->peername_len = len;
1333 	child_si->peername = sockaddr_dup(my_addr, len);
1334 
1335 	if (addr != NULL && addrlen != NULL) {
1336 	    *addrlen = len;
1337 	    if (*addrlen >= len)
1338 		memcpy(addr, my_addr, len);
1339 	    *addrlen = 0;
1340 	}
1341 
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;
1347 	}
1348 
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;
1357 	}
1358 
1359 	child_si->myname_len = len;
1360 	child_si->myname = sockaddr_dup(my_addr, len);
1361 	free(my_addr);
1362 
1363 	SWRAP_DLIST_ADD(sockets, child_si);
1364 
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);
1368 
1369 	return fd;
1370 }
1371 
1372 static int autobind_start_init;
1373 static int autobind_start;
1374 
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)
1380 {
1381 	struct sockaddr_un un_addr;
1382 	int i;
1383 	char type;
1384 	int ret;
1385 	int port;
1386 	struct stat st;
1387 
1388 	if (autobind_start_init != 1) {
1389 		autobind_start_init = 1;
1390 		autobind_start = getpid();
1391 		autobind_start %= 50000;
1392 		autobind_start += 10000;
1393 	}
1394 
1395 	un_addr.sun_family = AF_UNIX;
1396 
1397 	switch (si->family) {
1398 	case AF_INET: {
1399 		struct sockaddr_in in;
1400 
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;
1411 		}
1412 
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());
1417 
1418 		si->myname_len = sizeof(in);
1419 		si->myname = sockaddr_dup(&in, si->myname_len);
1420 		break;
1421 	}
1422 #ifdef HAVE_IPV6
1423 	case AF_INET6: {
1424 		struct sockaddr_in6 in6;
1425 
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;
1436 		}
1437 
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;
1444 	}
1445 #endif
1446 	default:
1447 		errno = ESOCKTNOSUPPORT;
1448 		return -1;
1449 	}
1450 
1451 	if (autobind_start > 60000) {
1452 		autobind_start = 10000;
1453 	}
1454 
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;
1461 
1462 		ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1463 		if (ret == -1) return ret;
1464 
1465 		si->tmp_path = strdup(un_addr.sun_path);
1466 		si->bound = 1;
1467 		autobind_start = port + 1;
1468 		break;
1469 	}
1470 	if (i == 1000) {
1471 		errno = ENFILE;
1472 		return -1;
1473 	}
1474 
1475 	set_port(si->family, port, si->myname);
1476 
1477 	return 0;
1478 }
1479 
1480 
1481 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1482 {
1483 	int ret;
1484 	struct sockaddr_un un_addr;
1485 	struct socket_info *si = find_socket_info(s);
1486 
1487 	if (!si) {
1488 		return real_connect(s, serv_addr, addrlen);
1489 	}
1490 
1491 	if (si->bound == 0) {
1492 		ret = swrap_auto_bind(si);
1493 		if (ret == -1) return -1;
1494 	}
1495 
1496 	if (si->family != serv_addr->sa_family) {
1497 		errno = EINVAL;
1498 		return -1;
1499 	}
1500 
1501 	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1502 	if (ret == -1) return -1;
1503 
1504 	swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1505 
1506 	ret = real_connect(s, (struct sockaddr *)&un_addr,
1507 			   sizeof(struct sockaddr_un));
1508 
1509 	/* to give better errors */
1510 	if (ret == -1 && errno == ENOENT) {
1511 		errno = EHOSTUNREACH;
1512 	}
1513 
1514 	if (ret == 0) {
1515 		si->peername_len = addrlen;
1516 		si->peername = sockaddr_dup(serv_addr, addrlen);
1517 
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);
1522 	}
1523 
1524 	return ret;
1525 }
1526 
1527 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1528 {
1529 	int ret;
1530 	struct sockaddr_un un_addr;
1531 	struct socket_info *si = find_socket_info(s);
1532 
1533 	if (!si) {
1534 		return real_bind(s, myaddr, addrlen);
1535 	}
1536 
1537 	si->myname_len = addrlen;
1538 	si->myname = sockaddr_dup(myaddr, addrlen);
1539 
1540 	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1541 	if (ret == -1) return -1;
1542 
1543 	unlink(un_addr.sun_path);
1544 
1545 	ret = real_bind(s, (struct sockaddr *)&un_addr,
1546 			sizeof(struct sockaddr_un));
1547 
1548 	if (ret == 0) {
1549 		si->bound = 1;
1550 	}
1551 
1552 	return ret;
1553 }
1554 
1555 _PUBLIC_ int swrap_listen(int s, int backlog)
1556 {
1557 	int ret;
1558 	struct socket_info *si = find_socket_info(s);
1559 
1560 	if (!si) {
1561 		return real_listen(s, backlog);
1562 	}
1563 
1564 	ret = real_listen(s, backlog);
1565 
1566 	return ret;
1567 }
1568 
1569 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1570 {
1571 	struct socket_info *si = find_socket_info(s);
1572 
1573 	if (!si) {
1574 		return real_getpeername(s, name, addrlen);
1575 	}
1576 
1577 	if (!si->peername)
1578 	{
1579 		errno = ENOTCONN;
1580 		return -1;
1581 	}
1582 
1583 	memcpy(name, si->peername, si->peername_len);
1584 	*addrlen = si->peername_len;
1585 
1586 	return 0;
1587 }
1588 
1589 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1590 {
1591 	struct socket_info *si = find_socket_info(s);
1592 
1593 	if (!si) {
1594 		return real_getsockname(s, name, addrlen);
1595 	}
1596 
1597 	memcpy(name, si->myname, si->myname_len);
1598 	*addrlen = si->myname_len;
1599 
1600 	return 0;
1601 }
1602 
1603 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1604 {
1605 	struct socket_info *si = find_socket_info(s);
1606 
1607 	if (!si) {
1608 		return real_getsockopt(s, level, optname, optval, optlen);
1609 	}
1610 
1611 	if (level == SOL_SOCKET) {
1612 		return real_getsockopt(s, level, optname, optval, optlen);
1613 	}
1614 
1615 	errno = ENOPROTOOPT;
1616 	return -1;
1617 }
1618 
1619 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
1620 {
1621 	struct socket_info *si = find_socket_info(s);
1622 
1623 	if (!si) {
1624 		return real_setsockopt(s, level, optname, optval, optlen);
1625 	}
1626 
1627 	if (level == SOL_SOCKET) {
1628 		return real_setsockopt(s, level, optname, optval, optlen);
1629 	}
1630 
1631 	switch (si->family) {
1632 	case AF_INET:
1633 		return 0;
1634 	default:
1635 		errno = ENOPROTOOPT;
1636 		return -1;
1637 	}
1638 }
1639 
1640 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1641 {
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);
1646 
1647 	if (!si) {
1648 		return real_recvfrom(s, buf, len, flags, from, fromlen);
1649 	}
1650 
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;
1656 
1657 	if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1658 				     si->family, from, fromlen) == -1) {
1659 		return -1;
1660 	}
1661 
1662 	swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1663 
1664 	return ret;
1665 }
1666 
1667 
1668 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1669 {
1670 	struct sockaddr_un un_addr;
1671 	int ret;
1672 	struct socket_info *si = find_socket_info(s);
1673 	int bcast = 0;
1674 
1675 	if (!si) {
1676 		return real_sendto(s, buf, len, flags, to, tolen);
1677 	}
1678 
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;
1687 		}
1688 
1689 		ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1690 		if (ret == -1) return -1;
1691 
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;
1697 
1698 			type = SOCKET_TYPE_CHAR_UDP;
1699 
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;
1704 
1705 				/* ignore the any errors in broadcast sends */
1706 				real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1707 			}
1708 
1709 			swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1710 
1711 			return len;
1712 		}
1713 
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;
1720 	}
1721 
1722 	/* to give better errors */
1723 	if (ret == -1 && errno == ENOENT) {
1724 		errno = EHOSTUNREACH;
1725 	}
1726 
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);
1732 	}
1733 
1734 	return ret;
1735 }
1736 
1737 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1738 {
1739 	int ret;
1740 	struct socket_info *si = find_socket_info(s);
1741 	int value;
1742 
1743 	if (!si) {
1744 		return real_ioctl(s, r, p);
1745 	}
1746 
1747 	ret = real_ioctl(s, r, p);
1748 
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);
1756 		}
1757 		break;
1758 	}
1759 
1760 	return ret;
1761 }
1762 
1763 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1764 {
1765 	int ret;
1766 	struct socket_info *si = find_socket_info(s);
1767 
1768 	if (!si) {
1769 		return real_recv(s, buf, len, flags);
1770 	}
1771 
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);
1779 	}
1780 
1781 	return ret;
1782 }
1783 
1784 
1785 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1786 {
1787 	int ret;
1788 	struct socket_info *si = find_socket_info(s);
1789 
1790 	if (!si) {
1791 		return real_send(s, buf, len, flags);
1792 	}
1793 
1794 	ret = real_send(s, buf, len, flags);
1795 
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);
1801 	}
1802 
1803 	return ret;
1804 }
1805 
1806 _PUBLIC_ int swrap_close(int fd)
1807 {
1808 	struct socket_info *si = find_socket_info(fd);
1809 	int ret;
1810 
1811 	if (!si) {
1812 		return real_close(fd);
1813 	}
1814 
1815 	SWRAP_DLIST_REMOVE(sockets, si);
1816 
1817 	if (si->myname && si->peername) {
1818 		swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1819 	}
1820 
1821 	ret = real_close(fd);
1822 
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);
1826 	}
1827 
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);
1834 	}
1835 	free(si);
1836 
1837 	return ret;
1838 }
1839 
1840 static int
1841 dup_internal(const struct socket_info *si_oldd, int fd)
1842 {
1843 	struct socket_info *si_newd;
1844 
1845 	si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1846 
1847 	si_newd->fd = fd;
1848 
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;
1864 
1865 	si_newd->io = si_oldd->io;
1866 
1867 	SWRAP_DLIST_ADD(sockets, si_newd);
1868 
1869 	return fd;
1870 }
1871 
1872 
1873 _PUBLIC_ int swrap_dup(int oldd)
1874 {
1875 	struct socket_info *si;
1876 	int fd;
1877 
1878 	si = find_socket_info(oldd);
1879 	if (si == NULL)
1880 		return real_dup(oldd);
1881 
1882 	fd = real_dup(si->fd);
1883 	if (fd < 0)
1884 		return fd;
1885 
1886 	return dup_internal(si, fd);
1887 }
1888 
1889 
1890 _PUBLIC_ int swrap_dup2(int oldd, int newd)
1891 {
1892 	struct socket_info *si_newd, *si_oldd;
1893 	int fd;
1894 
1895 	if (newd == oldd)
1896 	    return newd;
1897 
1898 	si_oldd = find_socket_info(oldd);
1899 	si_newd = find_socket_info(newd);
1900 
1901 	if (si_oldd == NULL && si_newd == NULL)
1902 		return real_dup2(oldd, newd);
1903 
1904 	fd = real_dup2(si_oldd->fd, newd);
1905 	if (fd < 0)
1906 		return fd;
1907 
1908 	/* close new socket first */
1909 	if (si_newd)
1910 	       	swrap_close(newd);
1911 
1912 	return dup_internal(si_oldd, fd);
1913 }
1914