xref: /freebsd/crypto/heimdal/lib/roken/socket_wrapper.c (revision fed1ca4b719c56c930f2259d80663cd34be812bb)
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 #include <config.h>
63 #undef SOCKET_WRAPPER_REPLACE
64 
65 #include <sys/types.h>
66 #ifdef TIME_WITH_SYS_TIME
67 #include <sys/time.h>
68 #include <time.h>
69 #elif defined(HAVE_SYS_TIME_H)
70 #include <sys/time.h>
71 #else
72 #include <time.h>
73 #endif
74 #include <sys/stat.h>
75 #include <sys/socket.h>
76 #include <sys/ioctl.h>
77 #ifdef HAVE_SYS_FILIO_H
78 #include <sys/filio.h>
79 #endif
80 #include <errno.h>
81 #include <sys/un.h>
82 #include <netinet/in.h>
83 #include <netinet/tcp.h>
84 #include <fcntl.h>
85 #include <stdlib.h>
86 #include <unistd.h>
87 #include <string.h>
88 #include <stdio.h>
89 #include "roken.h"
90 
91 #include "socket_wrapper.h"
92 
93 #define HAVE_GETTIMEOFDAY_TZ 1
94 
95 #define _PUBLIC_
96 
97 #endif
98 
99 #define SWRAP_DLIST_ADD(list,item) do { \
100 	if (!(list)) { \
101 		(item)->prev	= NULL; \
102 		(item)->next	= NULL; \
103 		(list)		= (item); \
104 	} else { \
105 		(item)->prev	= NULL; \
106 		(item)->next	= (list); \
107 		(list)->prev	= (item); \
108 		(list)		= (item); \
109 	} \
110 } while (0)
111 
112 #define SWRAP_DLIST_REMOVE(list,item) do { \
113 	if ((list) == (item)) { \
114 		(list)		= (item)->next; \
115 		if (list) { \
116 			(list)->prev	= NULL; \
117 		} \
118 	} else { \
119 		if ((item)->prev) { \
120 			(item)->prev->next	= (item)->next; \
121 		} \
122 		if ((item)->next) { \
123 			(item)->next->prev	= (item)->prev; \
124 		} \
125 	} \
126 	(item)->prev	= NULL; \
127 	(item)->next	= NULL; \
128 } while (0)
129 
130 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
131  * for now */
132 #define REWRITE_CALLS
133 
134 #ifdef REWRITE_CALLS
135 #define real_accept accept
136 #define real_connect connect
137 #define real_bind bind
138 #define real_listen listen
139 #define real_getpeername getpeername
140 #define real_getsockname getsockname
141 #define real_getsockopt getsockopt
142 #define real_setsockopt setsockopt
143 #define real_recvfrom recvfrom
144 #define real_sendto sendto
145 #define real_ioctl ioctl
146 #define real_recv recv
147 #define real_send send
148 #define real_socket socket
149 #define real_close close
150 #define real_dup dup
151 #define real_dup2 dup2
152 #endif
153 
154 #ifdef HAVE_GETTIMEOFDAY_TZ
155 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
156 #else
157 #define swrapGetTimeOfDay(tval)	gettimeofday(tval)
158 #endif
159 
160 /* we need to use a very terse format here as IRIX 6.4 silently
161    truncates names to 16 chars, so if we use a longer name then we
162    can't tell which port a packet came from with recvfrom()
163 
164    with this format we have 8 chars left for the directory name
165 */
166 #define SOCKET_FORMAT "%c%02X%04X"
167 #define SOCKET_TYPE_CHAR_TCP		'T'
168 #define SOCKET_TYPE_CHAR_UDP		'U'
169 #define SOCKET_TYPE_CHAR_TCP_V6		'X'
170 #define SOCKET_TYPE_CHAR_UDP_V6		'Y'
171 
172 #define MAX_WRAPPED_INTERFACES 16
173 
174 #define SW_IPV6_ADDRESS 1
175 
176 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
177 {
178 	struct sockaddr *ret = (struct sockaddr *)malloc(len);
179 	memcpy(ret, data, len);
180 	return ret;
181 }
182 
183 static void set_port(int family, int prt, struct sockaddr *addr)
184 {
185 	switch (family) {
186 	case AF_INET:
187 		((struct sockaddr_in *)addr)->sin_port = htons(prt);
188 		break;
189 #ifdef HAVE_IPV6
190 	case AF_INET6:
191 		((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
192 		break;
193 #endif
194 	}
195 }
196 
197 static int socket_length(int family)
198 {
199 	switch (family) {
200 	case AF_INET:
201 		return sizeof(struct sockaddr_in);
202 #ifdef HAVE_IPV6
203 	case AF_INET6:
204 		return sizeof(struct sockaddr_in6);
205 #endif
206 	}
207 	return -1;
208 }
209 
210 
211 
212 struct socket_info
213 {
214 	int fd;
215 
216 	int family;
217 	int type;
218 	int protocol;
219 	int bound;
220 	int bcast;
221 	int is_server;
222 
223 	char *path;
224 	char *tmp_path;
225 
226 	struct sockaddr *myname;
227 	socklen_t myname_len;
228 
229 	struct sockaddr *peername;
230 	socklen_t peername_len;
231 
232 	struct {
233 		unsigned long pck_snd;
234 		unsigned long pck_rcv;
235 	} io;
236 
237 	struct socket_info *prev, *next;
238 };
239 
240 static struct socket_info *sockets;
241 
242 
243 static const char *socket_wrapper_dir(void)
244 {
245 	const char *s = getenv("SOCKET_WRAPPER_DIR");
246 	if (s == NULL) {
247 		return NULL;
248 	}
249 	if (strncmp(s, "./", 2) == 0) {
250 		s += 2;
251 	}
252 	return s;
253 }
254 
255 static unsigned int socket_wrapper_default_iface(void)
256 {
257 	const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
258 	if (s) {
259 		unsigned int iface;
260 		if (sscanf(s, "%u", &iface) == 1) {
261 			if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
262 				return iface;
263 			}
264 		}
265 	}
266 
267 	return 1;/* 127.0.0.1 */
268 }
269 
270 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
271 {
272 	unsigned int iface;
273 	unsigned int prt;
274 	const char *p;
275 	char type;
276 
277 	p = strrchr(un->sun_path, '/');
278 	if (p) p++; else p = un->sun_path;
279 
280 	if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
281 		errno = EINVAL;
282 		return -1;
283 	}
284 
285 	if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
286 		errno = EINVAL;
287 		return -1;
288 	}
289 
290 	if (prt > 0xFFFF) {
291 		errno = EINVAL;
292 		return -1;
293 	}
294 
295 	switch(type) {
296 	case SOCKET_TYPE_CHAR_TCP:
297 	case SOCKET_TYPE_CHAR_UDP: {
298 		struct sockaddr_in *in2 = (struct sockaddr_in *)in;
299 
300 		if ((*len) < sizeof(*in2)) {
301 		    errno = EINVAL;
302 		    return -1;
303 		}
304 
305 		memset(in2, 0, sizeof(*in2));
306 		in2->sin_family = AF_INET;
307 		in2->sin_addr.s_addr = htonl((127<<24) | iface);
308 		in2->sin_port = htons(prt);
309 
310 		*len = sizeof(*in2);
311 		break;
312 	}
313 #ifdef HAVE_IPV6
314 	case SOCKET_TYPE_CHAR_TCP_V6:
315 	case SOCKET_TYPE_CHAR_UDP_V6: {
316 		struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
317 
318 		if ((*len) < sizeof(*in2)) {
319 			errno = EINVAL;
320 			return -1;
321 		}
322 
323 		memset(in2, 0, sizeof(*in2));
324 		in2->sin6_family = AF_INET6;
325 		in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
326 		in2->sin6_port = htons(prt);
327 
328 		*len = sizeof(*in2);
329 		break;
330 	}
331 #endif
332 	default:
333 		errno = EINVAL;
334 		return -1;
335 	}
336 
337 	return 0;
338 }
339 
340 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
341 				int *bcast)
342 {
343 	char type = '\0';
344 	unsigned int prt;
345 	unsigned int iface;
346 	int is_bcast = 0;
347 
348 	if (bcast) *bcast = 0;
349 
350 	switch (si->family) {
351 	case AF_INET: {
352 		const struct sockaddr_in *in =
353 		    (const struct sockaddr_in *)inaddr;
354 		unsigned int addr = ntohl(in->sin_addr.s_addr);
355 		char u_type = '\0';
356 		char b_type = '\0';
357 		char a_type = '\0';
358 
359 		switch (si->type) {
360 		case SOCK_STREAM:
361 			u_type = SOCKET_TYPE_CHAR_TCP;
362 			break;
363 		case SOCK_DGRAM:
364 			u_type = SOCKET_TYPE_CHAR_UDP;
365 			a_type = SOCKET_TYPE_CHAR_UDP;
366 			b_type = SOCKET_TYPE_CHAR_UDP;
367 			break;
368 		}
369 
370 		prt = ntohs(in->sin_port);
371 		if (a_type && addr == 0xFFFFFFFF) {
372 			/* 255.255.255.255 only udp */
373 			is_bcast = 2;
374 			type = a_type;
375 			iface = socket_wrapper_default_iface();
376 		} else if (b_type && addr == 0x7FFFFFFF) {
377 			/* 127.255.255.255 only udp */
378 			is_bcast = 1;
379 			type = b_type;
380 			iface = socket_wrapper_default_iface();
381 		} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
382 			/* 127.0.0.X */
383 			is_bcast = 0;
384 			type = u_type;
385 			iface = (addr & 0x000000FF);
386 		} else {
387 			errno = ENETUNREACH;
388 			return -1;
389 		}
390 		if (bcast) *bcast = is_bcast;
391 		break;
392 	}
393 #ifdef HAVE_IPV6
394 	case AF_INET6: {
395 		const struct sockaddr_in6 *in =
396 		    (const struct sockaddr_in6 *)inaddr;
397 
398 		switch (si->type) {
399 		case SOCK_STREAM:
400 			type = SOCKET_TYPE_CHAR_TCP_V6;
401 			break;
402 		case SOCK_DGRAM:
403 			type = SOCKET_TYPE_CHAR_UDP_V6;
404 			break;
405 		}
406 
407 		/* XXX no multicast/broadcast */
408 
409 		prt = ntohs(in->sin6_port);
410 		iface = SW_IPV6_ADDRESS;
411 
412 		break;
413 	}
414 #endif
415 	default:
416 		errno = ENETUNREACH;
417 		return -1;
418 	}
419 
420 	if (prt == 0) {
421 		errno = EINVAL;
422 		return -1;
423 	}
424 
425 	if (is_bcast) {
426 		snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
427 			 socket_wrapper_dir());
428 		/* the caller need to do more processing */
429 		return 0;
430 	}
431 
432 	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
433 		 socket_wrapper_dir(), type, iface, prt);
434 
435 	return 0;
436 }
437 
438 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
439 			       int *bcast)
440 {
441 	char type = '\0';
442 	unsigned int prt;
443 	unsigned int iface;
444 	struct stat st;
445 	int is_bcast = 0;
446 
447 	if (bcast) *bcast = 0;
448 
449 	switch (si->family) {
450 	case AF_INET: {
451 		const struct sockaddr_in *in =
452 		    (const struct sockaddr_in *)inaddr;
453 		unsigned int addr = ntohl(in->sin_addr.s_addr);
454 		char u_type = '\0';
455 		char d_type = '\0';
456 		char b_type = '\0';
457 		char a_type = '\0';
458 
459 		prt = ntohs(in->sin_port);
460 
461 		switch (si->type) {
462 		case SOCK_STREAM:
463 			u_type = SOCKET_TYPE_CHAR_TCP;
464 			d_type = SOCKET_TYPE_CHAR_TCP;
465 			break;
466 		case SOCK_DGRAM:
467 			u_type = SOCKET_TYPE_CHAR_UDP;
468 			d_type = SOCKET_TYPE_CHAR_UDP;
469 			a_type = SOCKET_TYPE_CHAR_UDP;
470 			b_type = SOCKET_TYPE_CHAR_UDP;
471 			break;
472 		}
473 
474 		if (addr == 0) {
475 			/* 0.0.0.0 */
476 		 	is_bcast = 0;
477 			type = d_type;
478 			iface = socket_wrapper_default_iface();
479 		} else if (a_type && addr == 0xFFFFFFFF) {
480 			/* 255.255.255.255 only udp */
481 			is_bcast = 2;
482 			type = a_type;
483 			iface = socket_wrapper_default_iface();
484 		} else if (b_type && addr == 0x7FFFFFFF) {
485 			/* 127.255.255.255 only udp */
486 			is_bcast = 1;
487 			type = b_type;
488 			iface = socket_wrapper_default_iface();
489 		} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
490 			/* 127.0.0.X */
491 			is_bcast = 0;
492 			type = u_type;
493 			iface = (addr & 0x000000FF);
494 		} else {
495 			errno = EADDRNOTAVAIL;
496 			return -1;
497 		}
498 		break;
499 	}
500 #ifdef HAVE_IPV6
501 	case AF_INET6: {
502 		const struct sockaddr_in6 *in =
503 		    (const struct sockaddr_in6 *)inaddr;
504 
505 		switch (si->type) {
506 		case SOCK_STREAM:
507 			type = SOCKET_TYPE_CHAR_TCP_V6;
508 			break;
509 		case SOCK_DGRAM:
510 			type = SOCKET_TYPE_CHAR_UDP_V6;
511 			break;
512 		}
513 
514 		/* XXX no multicast/broadcast */
515 
516 		prt = ntohs(in->sin6_port);
517 		iface = SW_IPV6_ADDRESS;
518 
519 		break;
520 	}
521 #endif
522 	default:
523 		errno = ENETUNREACH;
524 		return -1;
525 	}
526 
527 
528 	if (bcast) *bcast = is_bcast;
529 
530 	if (prt == 0) {
531 		/* handle auto-allocation of ephemeral ports */
532 		for (prt = 5001; prt < 10000; prt++) {
533 			snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
534 				 socket_wrapper_dir(), type, iface, prt);
535 			if (stat(un->sun_path, &st) == 0) continue;
536 
537 			set_port(si->family, prt, si->myname);
538 		}
539 	}
540 
541 	snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
542 		 socket_wrapper_dir(), type, iface, prt);
543 	return 0;
544 }
545 
546 static struct socket_info *find_socket_info(int fd)
547 {
548 	struct socket_info *i;
549 	for (i = sockets; i; i = i->next) {
550 		if (i->fd == fd)
551 			return i;
552 	}
553 
554 	return NULL;
555 }
556 
557 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
558 				  struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
559 {
560 	if (!out_addr)
561 		return 0;
562 
563 	out_addr->sun_family = AF_UNIX;
564 
565 	switch (in_addr->sa_family) {
566 	case AF_INET:
567 #ifdef HAVE_IPV6
568 	case AF_INET6:
569 #endif
570 		switch (si->type) {
571 		case SOCK_STREAM:
572 		case SOCK_DGRAM:
573 			break;
574 		default:
575 			errno = ESOCKTNOSUPPORT;
576 			return -1;
577 		}
578 		if (alloc_sock) {
579 			return convert_in_un_alloc(si, in_addr, out_addr, bcast);
580 		} else {
581 			return convert_in_un_remote(si, in_addr, out_addr, bcast);
582 		}
583 	default:
584 		break;
585 	}
586 
587 	errno = EAFNOSUPPORT;
588 	return -1;
589 }
590 
591 static int sockaddr_convert_from_un(const struct socket_info *si,
592 				    const struct sockaddr_un *in_addr,
593 				    socklen_t un_addrlen,
594 				    int family,
595 				    struct sockaddr *out_addr,
596 				    socklen_t *out_addrlen)
597 {
598 	if (out_addr == NULL || out_addrlen == NULL)
599 		return 0;
600 
601 	if (un_addrlen == 0) {
602 		*out_addrlen = 0;
603 		return 0;
604 	}
605 
606 	switch (family) {
607 	case AF_INET:
608 #ifdef HAVE_IPV6
609 	case AF_INET6:
610 #endif
611 		switch (si->type) {
612 		case SOCK_STREAM:
613 		case SOCK_DGRAM:
614 			break;
615 		default:
616 			errno = ESOCKTNOSUPPORT;
617 			return -1;
618 		}
619 		return convert_un_in(in_addr, out_addr, out_addrlen);
620 	default:
621 		break;
622 	}
623 
624 	errno = EAFNOSUPPORT;
625 	return -1;
626 }
627 
628 enum swrap_packet_type {
629 	SWRAP_CONNECT_SEND,
630 	SWRAP_CONNECT_UNREACH,
631 	SWRAP_CONNECT_RECV,
632 	SWRAP_CONNECT_ACK,
633 	SWRAP_ACCEPT_SEND,
634 	SWRAP_ACCEPT_RECV,
635 	SWRAP_ACCEPT_ACK,
636 	SWRAP_RECVFROM,
637 	SWRAP_SENDTO,
638 	SWRAP_SENDTO_UNREACH,
639 	SWRAP_PENDING_RST,
640 	SWRAP_RECV,
641 	SWRAP_RECV_RST,
642 	SWRAP_SEND,
643 	SWRAP_SEND_RST,
644 	SWRAP_CLOSE_SEND,
645 	SWRAP_CLOSE_RECV,
646 	SWRAP_CLOSE_ACK
647 };
648 
649 struct swrap_file_hdr {
650 	unsigned long	magic;
651 	unsigned short	version_major;
652 	unsigned short	version_minor;
653 	long		timezone;
654 	unsigned long	sigfigs;
655 	unsigned long	frame_max_len;
656 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
657 	unsigned long	link_type;
658 };
659 #define SWRAP_FILE_HDR_SIZE 24
660 
661 struct swrap_packet {
662 	struct {
663 		unsigned long seconds;
664 		unsigned long micro_seconds;
665 		unsigned long recorded_length;
666 		unsigned long full_length;
667 	} frame;
668 #define SWRAP_PACKET__FRAME_SIZE 16
669 
670 	struct {
671 		struct {
672 			unsigned char	ver_hdrlen;
673 			unsigned char	tos;
674 			unsigned short	packet_length;
675 			unsigned short	identification;
676 			unsigned char	flags;
677 			unsigned char	fragment;
678 			unsigned char	ttl;
679 			unsigned char	protocol;
680 			unsigned short	hdr_checksum;
681 			unsigned long	src_addr;
682 			unsigned long	dest_addr;
683 		} hdr;
684 #define SWRAP_PACKET__IP_HDR_SIZE 20
685 
686 		union {
687 			struct {
688 				unsigned short	source_port;
689 				unsigned short	dest_port;
690 				unsigned long	seq_num;
691 				unsigned long	ack_num;
692 				unsigned char	hdr_length;
693 				unsigned char	control;
694 				unsigned short	window;
695 				unsigned short	checksum;
696 				unsigned short	urg;
697 			} tcp;
698 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
699 			struct {
700 				unsigned short	source_port;
701 				unsigned short	dest_port;
702 				unsigned short	length;
703 				unsigned short	checksum;
704 			} udp;
705 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
706 			struct {
707 				unsigned char	type;
708 				unsigned char	code;
709 				unsigned short	checksum;
710 				unsigned long	unused;
711 			} icmp;
712 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
713 		} p;
714 	} ip;
715 };
716 #define SWRAP_PACKET_SIZE 56
717 
718 static const char *socket_wrapper_pcap_file(void)
719 {
720 	static int initialized = 0;
721 	static const char *s = NULL;
722 	static const struct swrap_file_hdr h;
723 	static const struct swrap_packet p;
724 
725 	if (initialized == 1) {
726 		return s;
727 	}
728 	initialized = 1;
729 
730 	/*
731 	 * TODO: don't use the structs use plain buffer offsets
732 	 *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
733 	 *
734 	 * for now make sure we disable PCAP support
735 	 * if the struct has alignment!
736 	 */
737 	if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
738 		return NULL;
739 	}
740 	if (sizeof(p) != SWRAP_PACKET_SIZE) {
741 		return NULL;
742 	}
743 	if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
744 		return NULL;
745 	}
746 	if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
747 		return NULL;
748 	}
749 	if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
750 		return NULL;
751 	}
752 	if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
753 		return NULL;
754 	}
755 	if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
756 		return NULL;
757 	}
758 
759 	s = getenv("SOCKET_WRAPPER_PCAP_FILE");
760 	if (s == NULL) {
761 		return NULL;
762 	}
763 	if (strncmp(s, "./", 2) == 0) {
764 		s += 2;
765 	}
766 	return s;
767 }
768 
769 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
770 					      const struct sockaddr_in *src_addr,
771 					      const struct sockaddr_in *dest_addr,
772 					      int socket_type,
773 					      const unsigned char *payload,
774 					      size_t payload_len,
775 					      unsigned long tcp_seq,
776 					      unsigned long tcp_ack,
777 					      unsigned char tcp_ctl,
778 					      int unreachable,
779 					      size_t *_packet_len)
780 {
781 	struct swrap_packet *ret;
782 	struct swrap_packet *packet;
783 	size_t packet_len;
784 	size_t alloc_len;
785 	size_t nonwire_len = sizeof(packet->frame);
786 	size_t wire_hdr_len = 0;
787 	size_t wire_len = 0;
788 	size_t icmp_hdr_len = 0;
789 	size_t icmp_truncate_len = 0;
790 	unsigned char protocol = 0, icmp_protocol = 0;
791 	unsigned short src_port = src_addr->sin_port;
792 	unsigned short dest_port = dest_addr->sin_port;
793 
794 	switch (socket_type) {
795 	case SOCK_STREAM:
796 		protocol = 0x06; /* TCP */
797 		wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
798 		wire_len = wire_hdr_len + payload_len;
799 		break;
800 
801 	case SOCK_DGRAM:
802 		protocol = 0x11; /* UDP */
803 		wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
804 		wire_len = wire_hdr_len + payload_len;
805 		break;
806 	}
807 
808 	if (unreachable) {
809 		icmp_protocol = protocol;
810 		protocol = 0x01; /* ICMP */
811 		if (wire_len > 64 ) {
812 			icmp_truncate_len = wire_len - 64;
813 		}
814 		icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
815 		wire_hdr_len += icmp_hdr_len;
816 		wire_len += icmp_hdr_len;
817 	}
818 
819 	packet_len = nonwire_len + wire_len;
820 	alloc_len = packet_len;
821 	if (alloc_len < sizeof(struct swrap_packet)) {
822 		alloc_len = sizeof(struct swrap_packet);
823 	}
824 	ret = (struct swrap_packet *)malloc(alloc_len);
825 	if (!ret) return NULL;
826 
827 	packet = ret;
828 
829 	packet->frame.seconds		= tval->tv_sec;
830 	packet->frame.micro_seconds	= tval->tv_usec;
831 	packet->frame.recorded_length	= wire_len - icmp_truncate_len;
832 	packet->frame.full_length	= wire_len - icmp_truncate_len;
833 
834 	packet->ip.hdr.ver_hdrlen	= 0x45; /* version 4 and 5 * 32 bit words */
835 	packet->ip.hdr.tos		= 0x00;
836 	packet->ip.hdr.packet_length	= htons(wire_len - icmp_truncate_len);
837 	packet->ip.hdr.identification	= htons(0xFFFF);
838 	packet->ip.hdr.flags		= 0x40; /* BIT 1 set - means don't fraqment */
839 	packet->ip.hdr.fragment		= htons(0x0000);
840 	packet->ip.hdr.ttl		= 0xFF;
841 	packet->ip.hdr.protocol		= protocol;
842 	packet->ip.hdr.hdr_checksum	= htons(0x0000);
843 	packet->ip.hdr.src_addr		= src_addr->sin_addr.s_addr;
844 	packet->ip.hdr.dest_addr	= dest_addr->sin_addr.s_addr;
845 
846 	if (unreachable) {
847 		packet->ip.p.icmp.type		= 0x03; /* destination unreachable */
848 		packet->ip.p.icmp.code		= 0x01; /* host unreachable */
849 		packet->ip.p.icmp.checksum	= htons(0x0000);
850 		packet->ip.p.icmp.unused	= htonl(0x00000000);
851 
852 		/* set the ip header in the ICMP payload */
853 		packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
854 		packet->ip.hdr.ver_hdrlen	= 0x45; /* version 4 and 5 * 32 bit words */
855 		packet->ip.hdr.tos		= 0x00;
856 		packet->ip.hdr.packet_length	= htons(wire_len - icmp_hdr_len);
857 		packet->ip.hdr.identification	= htons(0xFFFF);
858 		packet->ip.hdr.flags		= 0x40; /* BIT 1 set - means don't fraqment */
859 		packet->ip.hdr.fragment		= htons(0x0000);
860 		packet->ip.hdr.ttl		= 0xFF;
861 		packet->ip.hdr.protocol		= icmp_protocol;
862 		packet->ip.hdr.hdr_checksum	= htons(0x0000);
863 		packet->ip.hdr.src_addr		= dest_addr->sin_addr.s_addr;
864 		packet->ip.hdr.dest_addr	= src_addr->sin_addr.s_addr;
865 
866 		src_port = dest_addr->sin_port;
867 		dest_port = src_addr->sin_port;
868 	}
869 
870 	switch (socket_type) {
871 	case SOCK_STREAM:
872 		packet->ip.p.tcp.source_port	= src_port;
873 		packet->ip.p.tcp.dest_port	= dest_port;
874 		packet->ip.p.tcp.seq_num	= htonl(tcp_seq);
875 		packet->ip.p.tcp.ack_num	= htonl(tcp_ack);
876 		packet->ip.p.tcp.hdr_length	= 0x50; /* 5 * 32 bit words */
877 		packet->ip.p.tcp.control	= tcp_ctl;
878 		packet->ip.p.tcp.window		= htons(0x7FFF);
879 		packet->ip.p.tcp.checksum	= htons(0x0000);
880 		packet->ip.p.tcp.urg		= htons(0x0000);
881 
882 		break;
883 
884 	case SOCK_DGRAM:
885 		packet->ip.p.udp.source_port	= src_addr->sin_port;
886 		packet->ip.p.udp.dest_port	= dest_addr->sin_port;
887 		packet->ip.p.udp.length		= htons(8 + payload_len);
888 		packet->ip.p.udp.checksum	= htons(0x0000);
889 
890 		break;
891 	}
892 
893 	if (payload && payload_len > 0) {
894 		unsigned char *p = (unsigned char *)ret;
895 		p += nonwire_len;
896 		p += wire_hdr_len;
897 		memcpy(p, payload, payload_len);
898 	}
899 
900 	*_packet_len = packet_len - icmp_truncate_len;
901 	return ret;
902 }
903 
904 static int swrap_get_pcap_fd(const char *fname)
905 {
906 	static int fd = -1;
907 
908 	if (fd != -1) return fd;
909 
910 	fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
911 	if (fd != -1) {
912 		struct swrap_file_hdr file_hdr;
913 		file_hdr.magic		= 0xA1B2C3D4;
914 		file_hdr.version_major	= 0x0002;
915 		file_hdr.version_minor	= 0x0004;
916 		file_hdr.timezone	= 0x00000000;
917 		file_hdr.sigfigs	= 0x00000000;
918 		file_hdr.frame_max_len	= SWRAP_FRAME_LENGTH_MAX;
919 		file_hdr.link_type	= 0x0065; /* 101 RAW IP */
920 
921 		write(fd, &file_hdr, sizeof(file_hdr));
922 		return fd;
923 	}
924 
925 	fd = open(fname, O_WRONLY|O_APPEND, 0644);
926 
927 	return fd;
928 }
929 
930 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
931 			      enum swrap_packet_type type,
932 			      const void *buf, size_t len)
933 {
934 	const struct sockaddr_in *src_addr;
935 	const struct sockaddr_in *dest_addr;
936 	const char *file_name;
937 	unsigned long tcp_seq = 0;
938 	unsigned long tcp_ack = 0;
939 	unsigned char tcp_ctl = 0;
940 	int unreachable = 0;
941 	struct timeval tv;
942 	struct swrap_packet *packet;
943 	size_t packet_len = 0;
944 	int fd;
945 
946 	file_name = socket_wrapper_pcap_file();
947 	if (!file_name) {
948 		return;
949 	}
950 
951 	switch (si->family) {
952 	case AF_INET:
953 #ifdef HAVE_IPV6
954 	case AF_INET6:
955 #endif
956 		break;
957 	default:
958 		return;
959 	}
960 
961 	switch (type) {
962 	case SWRAP_CONNECT_SEND:
963 		if (si->type != SOCK_STREAM) return;
964 
965 		src_addr = (const struct sockaddr_in *)si->myname;
966 		dest_addr = (const struct sockaddr_in *)addr;
967 
968 		tcp_seq = si->io.pck_snd;
969 		tcp_ack = si->io.pck_rcv;
970 		tcp_ctl = 0x02; /* SYN */
971 
972 		si->io.pck_snd += 1;
973 
974 		break;
975 
976 	case SWRAP_CONNECT_RECV:
977 		if (si->type != SOCK_STREAM) return;
978 
979 		dest_addr = (const struct sockaddr_in *)si->myname;
980 		src_addr = (const struct sockaddr_in *)addr;
981 
982 		tcp_seq = si->io.pck_rcv;
983 		tcp_ack = si->io.pck_snd;
984 		tcp_ctl = 0x12; /** SYN,ACK */
985 
986 		si->io.pck_rcv += 1;
987 
988 		break;
989 
990 	case SWRAP_CONNECT_UNREACH:
991 		if (si->type != SOCK_STREAM) return;
992 
993 		dest_addr = (const struct sockaddr_in *)si->myname;
994 		src_addr = (const struct sockaddr_in *)addr;
995 
996 		/* Unreachable: resend the data of SWRAP_CONNECT_SEND */
997 		tcp_seq = si->io.pck_snd - 1;
998 		tcp_ack = si->io.pck_rcv;
999 		tcp_ctl = 0x02; /* SYN */
1000 		unreachable = 1;
1001 
1002 		break;
1003 
1004 	case SWRAP_CONNECT_ACK:
1005 		if (si->type != SOCK_STREAM) return;
1006 
1007 		src_addr = (const struct sockaddr_in *)si->myname;
1008 		dest_addr = (const struct sockaddr_in *)addr;
1009 
1010 		tcp_seq = si->io.pck_snd;
1011 		tcp_ack = si->io.pck_rcv;
1012 		tcp_ctl = 0x10; /* ACK */
1013 
1014 		break;
1015 
1016 	case SWRAP_ACCEPT_SEND:
1017 		if (si->type != SOCK_STREAM) return;
1018 
1019 		dest_addr = (const struct sockaddr_in *)si->myname;
1020 		src_addr = (const struct sockaddr_in *)addr;
1021 
1022 		tcp_seq = si->io.pck_rcv;
1023 		tcp_ack = si->io.pck_snd;
1024 		tcp_ctl = 0x02; /* SYN */
1025 
1026 		si->io.pck_rcv += 1;
1027 
1028 		break;
1029 
1030 	case SWRAP_ACCEPT_RECV:
1031 		if (si->type != SOCK_STREAM) return;
1032 
1033 		src_addr = (const struct sockaddr_in *)si->myname;
1034 		dest_addr = (const struct sockaddr_in *)addr;
1035 
1036 		tcp_seq = si->io.pck_snd;
1037 		tcp_ack = si->io.pck_rcv;
1038 		tcp_ctl = 0x12; /* SYN,ACK */
1039 
1040 		si->io.pck_snd += 1;
1041 
1042 		break;
1043 
1044 	case SWRAP_ACCEPT_ACK:
1045 		if (si->type != SOCK_STREAM) return;
1046 
1047 		dest_addr = (const struct sockaddr_in *)si->myname;
1048 		src_addr = (const struct sockaddr_in *)addr;
1049 
1050 		tcp_seq = si->io.pck_rcv;
1051 		tcp_ack = si->io.pck_snd;
1052 		tcp_ctl = 0x10; /* ACK */
1053 
1054 		break;
1055 
1056 	case SWRAP_SEND:
1057 		src_addr = (const struct sockaddr_in *)si->myname;
1058 		dest_addr = (const struct sockaddr_in *)si->peername;
1059 
1060 		tcp_seq = si->io.pck_snd;
1061 		tcp_ack = si->io.pck_rcv;
1062 		tcp_ctl = 0x18; /* PSH,ACK */
1063 
1064 		si->io.pck_snd += len;
1065 
1066 		break;
1067 
1068 	case SWRAP_SEND_RST:
1069 		dest_addr = (const struct sockaddr_in *)si->myname;
1070 		src_addr = (const struct sockaddr_in *)si->peername;
1071 
1072 		if (si->type == SOCK_DGRAM) {
1073 			swrap_dump_packet(si, si->peername,
1074 					  SWRAP_SENDTO_UNREACH,
1075 			      		  buf, len);
1076 			return;
1077 		}
1078 
1079 		tcp_seq = si->io.pck_rcv;
1080 		tcp_ack = si->io.pck_snd;
1081 		tcp_ctl = 0x14; /** RST,ACK */
1082 
1083 		break;
1084 
1085 	case SWRAP_PENDING_RST:
1086 		dest_addr = (const struct sockaddr_in *)si->myname;
1087 		src_addr = (const struct sockaddr_in *)si->peername;
1088 
1089 		if (si->type == SOCK_DGRAM) {
1090 			return;
1091 		}
1092 
1093 		tcp_seq = si->io.pck_rcv;
1094 		tcp_ack = si->io.pck_snd;
1095 		tcp_ctl = 0x14; /* RST,ACK */
1096 
1097 		break;
1098 
1099 	case SWRAP_RECV:
1100 		dest_addr = (const struct sockaddr_in *)si->myname;
1101 		src_addr = (const struct sockaddr_in *)si->peername;
1102 
1103 		tcp_seq = si->io.pck_rcv;
1104 		tcp_ack = si->io.pck_snd;
1105 		tcp_ctl = 0x18; /* PSH,ACK */
1106 
1107 		si->io.pck_rcv += len;
1108 
1109 		break;
1110 
1111 	case SWRAP_RECV_RST:
1112 		dest_addr = (const struct sockaddr_in *)si->myname;
1113 		src_addr = (const struct sockaddr_in *)si->peername;
1114 
1115 		if (si->type == SOCK_DGRAM) {
1116 			return;
1117 		}
1118 
1119 		tcp_seq = si->io.pck_rcv;
1120 		tcp_ack = si->io.pck_snd;
1121 		tcp_ctl = 0x14; /* RST,ACK */
1122 
1123 		break;
1124 
1125 	case SWRAP_SENDTO:
1126 		src_addr = (const struct sockaddr_in *)si->myname;
1127 		dest_addr = (const struct sockaddr_in *)addr;
1128 
1129 		si->io.pck_snd += len;
1130 
1131 		break;
1132 
1133 	case SWRAP_SENDTO_UNREACH:
1134 		dest_addr = (const struct sockaddr_in *)si->myname;
1135 		src_addr = (const struct sockaddr_in *)addr;
1136 
1137 		unreachable = 1;
1138 
1139 		break;
1140 
1141 	case SWRAP_RECVFROM:
1142 		dest_addr = (const struct sockaddr_in *)si->myname;
1143 		src_addr = (const struct sockaddr_in *)addr;
1144 
1145 		si->io.pck_rcv += len;
1146 
1147 		break;
1148 
1149 	case SWRAP_CLOSE_SEND:
1150 		if (si->type != SOCK_STREAM) return;
1151 
1152 		src_addr = (const struct sockaddr_in *)si->myname;
1153 		dest_addr = (const struct sockaddr_in *)si->peername;
1154 
1155 		tcp_seq = si->io.pck_snd;
1156 		tcp_ack = si->io.pck_rcv;
1157 		tcp_ctl = 0x11; /* FIN, ACK */
1158 
1159 		si->io.pck_snd += 1;
1160 
1161 		break;
1162 
1163 	case SWRAP_CLOSE_RECV:
1164 		if (si->type != SOCK_STREAM) return;
1165 
1166 		dest_addr = (const struct sockaddr_in *)si->myname;
1167 		src_addr = (const struct sockaddr_in *)si->peername;
1168 
1169 		tcp_seq = si->io.pck_rcv;
1170 		tcp_ack = si->io.pck_snd;
1171 		tcp_ctl = 0x11; /* FIN,ACK */
1172 
1173 		si->io.pck_rcv += 1;
1174 
1175 		break;
1176 
1177 	case SWRAP_CLOSE_ACK:
1178 		if (si->type != SOCK_STREAM) return;
1179 
1180 		src_addr = (const struct sockaddr_in *)si->myname;
1181 		dest_addr = (const struct sockaddr_in *)si->peername;
1182 
1183 		tcp_seq = si->io.pck_snd;
1184 		tcp_ack = si->io.pck_rcv;
1185 		tcp_ctl = 0x10; /* ACK */
1186 
1187 		break;
1188 	default:
1189 		return;
1190 	}
1191 
1192 	swrapGetTimeOfDay(&tv);
1193 
1194 	packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1195 				   (const unsigned char *)buf, len,
1196 				   tcp_seq, tcp_ack, tcp_ctl, unreachable,
1197 				   &packet_len);
1198 	if (!packet) {
1199 		return;
1200 	}
1201 
1202 	fd = swrap_get_pcap_fd(file_name);
1203 	if (fd != -1) {
1204 		write(fd, packet, packet_len);
1205 	}
1206 
1207 	free(packet);
1208 }
1209 
1210 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1211 {
1212 	struct socket_info *si;
1213 	int fd;
1214 
1215 	if (!socket_wrapper_dir()) {
1216 		return real_socket(family, type, protocol);
1217 	}
1218 
1219 	switch (family) {
1220 	case AF_INET:
1221 #ifdef HAVE_IPV6
1222 	case AF_INET6:
1223 #endif
1224 		break;
1225 	case AF_UNIX:
1226 		return real_socket(family, type, protocol);
1227 	default:
1228 		errno = EAFNOSUPPORT;
1229 		return -1;
1230 	}
1231 
1232 	switch (type) {
1233 	case SOCK_STREAM:
1234 		break;
1235 	case SOCK_DGRAM:
1236 		break;
1237 	default:
1238 		errno = EPROTONOSUPPORT;
1239 		return -1;
1240 	}
1241 
1242 #if 0
1243 	switch (protocol) {
1244 	case 0:
1245 		break;
1246 	default:
1247 		errno = EPROTONOSUPPORT;
1248 		return -1;
1249 	}
1250 #endif
1251 
1252 	fd = real_socket(AF_UNIX, type, 0);
1253 
1254 	if (fd == -1) return -1;
1255 
1256 	si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1257 
1258 	si->family = family;
1259 	si->type = type;
1260 	si->protocol = protocol;
1261 	si->fd = fd;
1262 
1263 	SWRAP_DLIST_ADD(sockets, si);
1264 
1265 	return si->fd;
1266 }
1267 
1268 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1269 {
1270 	struct socket_info *parent_si, *child_si;
1271 	int fd;
1272 	struct sockaddr_un un_addr;
1273 	socklen_t un_addrlen = sizeof(un_addr);
1274 	struct sockaddr_un un_my_addr;
1275 	socklen_t un_my_addrlen = sizeof(un_my_addr);
1276 	struct sockaddr *my_addr;
1277 	socklen_t my_addrlen, len;
1278 	int ret;
1279 
1280 	parent_si = find_socket_info(s);
1281 	if (!parent_si) {
1282 		return real_accept(s, addr, addrlen);
1283 	}
1284 
1285 	/*
1286 	 * assume out sockaddr have the same size as the in parent
1287 	 * socket family
1288 	 */
1289 	my_addrlen = socket_length(parent_si->family);
1290 	if (my_addrlen < 0) {
1291 		errno = EINVAL;
1292 		return -1;
1293 	}
1294 
1295 	my_addr = malloc(my_addrlen);
1296 	if (my_addr == NULL) {
1297 		return -1;
1298 	}
1299 
1300 	memset(&un_addr, 0, sizeof(un_addr));
1301 	memset(&un_my_addr, 0, sizeof(un_my_addr));
1302 
1303 	ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1304 	if (ret == -1) {
1305 		free(my_addr);
1306 		return ret;
1307 	}
1308 
1309 	fd = ret;
1310 
1311 	len = my_addrlen;
1312 	ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1313 				       parent_si->family, my_addr, &len);
1314 	if (ret == -1) {
1315 		free(my_addr);
1316 		close(fd);
1317 		return ret;
1318 	}
1319 
1320 	child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1321 	memset(child_si, 0, sizeof(*child_si));
1322 
1323 	child_si->fd = fd;
1324 	child_si->family = parent_si->family;
1325 	child_si->type = parent_si->type;
1326 	child_si->protocol = parent_si->protocol;
1327 	child_si->bound = 1;
1328 	child_si->is_server = 1;
1329 
1330 	child_si->peername_len = len;
1331 	child_si->peername = sockaddr_dup(my_addr, len);
1332 
1333 	if (addr != NULL && addrlen != NULL) {
1334 	    *addrlen = len;
1335 	    if (*addrlen >= len)
1336 		memcpy(addr, my_addr, len);
1337 	    *addrlen = 0;
1338 	}
1339 
1340 	ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1341 	if (ret == -1) {
1342 		free(child_si);
1343 		close(fd);
1344 		return ret;
1345 	}
1346 
1347 	len = my_addrlen;
1348 	ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1349 				       child_si->family, my_addr, &len);
1350 	if (ret == -1) {
1351 		free(child_si);
1352 		free(my_addr);
1353 		close(fd);
1354 		return ret;
1355 	}
1356 
1357 	child_si->myname_len = len;
1358 	child_si->myname = sockaddr_dup(my_addr, len);
1359 	free(my_addr);
1360 
1361 	SWRAP_DLIST_ADD(sockets, child_si);
1362 
1363 	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1364 	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1365 	swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1366 
1367 	return fd;
1368 }
1369 
1370 static int autobind_start_init;
1371 static int autobind_start;
1372 
1373 /* using sendto() or connect() on an unbound socket would give the
1374    recipient no way to reply, as unlike UDP and TCP, a unix domain
1375    socket can't auto-assign emphemeral port numbers, so we need to
1376    assign it here */
1377 static int swrap_auto_bind(struct socket_info *si)
1378 {
1379 	struct sockaddr_un un_addr;
1380 	int i;
1381 	char type;
1382 	int ret;
1383 	int port;
1384 	struct stat st;
1385 
1386 	if (autobind_start_init != 1) {
1387 		autobind_start_init = 1;
1388 		autobind_start = getpid();
1389 		autobind_start %= 50000;
1390 		autobind_start += 10000;
1391 	}
1392 
1393 	un_addr.sun_family = AF_UNIX;
1394 
1395 	switch (si->family) {
1396 	case AF_INET: {
1397 		struct sockaddr_in in;
1398 
1399 		switch (si->type) {
1400 		case SOCK_STREAM:
1401 			type = SOCKET_TYPE_CHAR_TCP;
1402 			break;
1403 		case SOCK_DGRAM:
1404 		    	type = SOCKET_TYPE_CHAR_UDP;
1405 			break;
1406 		default:
1407 		    errno = ESOCKTNOSUPPORT;
1408 		    return -1;
1409 		}
1410 
1411 		memset(&in, 0, sizeof(in));
1412 		in.sin_family = AF_INET;
1413 		in.sin_addr.s_addr = htonl(127<<24 |
1414 					   socket_wrapper_default_iface());
1415 
1416 		si->myname_len = sizeof(in);
1417 		si->myname = sockaddr_dup(&in, si->myname_len);
1418 		break;
1419 	}
1420 #ifdef HAVE_IPV6
1421 	case AF_INET6: {
1422 		struct sockaddr_in6 in6;
1423 
1424 		switch (si->type) {
1425 		case SOCK_STREAM:
1426 			type = SOCKET_TYPE_CHAR_TCP_V6;
1427 			break;
1428 		case SOCK_DGRAM:
1429 		    	type = SOCKET_TYPE_CHAR_UDP_V6;
1430 			break;
1431 		default:
1432 		    errno = ESOCKTNOSUPPORT;
1433 		    return -1;
1434 		}
1435 
1436 		memset(&in6, 0, sizeof(in6));
1437 		in6.sin6_family = AF_INET6;
1438 		in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
1439 		si->myname_len = sizeof(in6);
1440 		si->myname = sockaddr_dup(&in6, si->myname_len);
1441 		break;
1442 	}
1443 #endif
1444 	default:
1445 		errno = ESOCKTNOSUPPORT;
1446 		return -1;
1447 	}
1448 
1449 	if (autobind_start > 60000) {
1450 		autobind_start = 10000;
1451 	}
1452 
1453 	for (i=0;i<1000;i++) {
1454 		port = autobind_start + i;
1455 		snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1456 			 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1457 			 type, socket_wrapper_default_iface(), port);
1458 		if (stat(un_addr.sun_path, &st) == 0) continue;
1459 
1460 		ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1461 		if (ret == -1) return ret;
1462 
1463 		si->tmp_path = strdup(un_addr.sun_path);
1464 		si->bound = 1;
1465 		autobind_start = port + 1;
1466 		break;
1467 	}
1468 	if (i == 1000) {
1469 		errno = ENFILE;
1470 		return -1;
1471 	}
1472 
1473 	set_port(si->family, port, si->myname);
1474 
1475 	return 0;
1476 }
1477 
1478 
1479 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1480 {
1481 	int ret;
1482 	struct sockaddr_un un_addr;
1483 	struct socket_info *si = find_socket_info(s);
1484 
1485 	if (!si) {
1486 		return real_connect(s, serv_addr, addrlen);
1487 	}
1488 
1489 	if (si->bound == 0) {
1490 		ret = swrap_auto_bind(si);
1491 		if (ret == -1) return -1;
1492 	}
1493 
1494 	if (si->family != serv_addr->sa_family) {
1495 		errno = EINVAL;
1496 		return -1;
1497 	}
1498 
1499 	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1500 	if (ret == -1) return -1;
1501 
1502 	swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1503 
1504 	ret = real_connect(s, (struct sockaddr *)&un_addr,
1505 			   sizeof(struct sockaddr_un));
1506 
1507 	/* to give better errors */
1508 	if (ret == -1 && errno == ENOENT) {
1509 		errno = EHOSTUNREACH;
1510 	}
1511 
1512 	if (ret == 0) {
1513 		si->peername_len = addrlen;
1514 		si->peername = sockaddr_dup(serv_addr, addrlen);
1515 
1516 		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1517 		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1518 	} else {
1519 		swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1520 	}
1521 
1522 	return ret;
1523 }
1524 
1525 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1526 {
1527 	int ret;
1528 	struct sockaddr_un un_addr;
1529 	struct socket_info *si = find_socket_info(s);
1530 
1531 	if (!si) {
1532 		return real_bind(s, myaddr, addrlen);
1533 	}
1534 
1535 	si->myname_len = addrlen;
1536 	si->myname = sockaddr_dup(myaddr, addrlen);
1537 
1538 	ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1539 	if (ret == -1) return -1;
1540 
1541 	unlink(un_addr.sun_path);
1542 
1543 	ret = real_bind(s, (struct sockaddr *)&un_addr,
1544 			sizeof(struct sockaddr_un));
1545 
1546 	if (ret == 0) {
1547 		si->bound = 1;
1548 	}
1549 
1550 	return ret;
1551 }
1552 
1553 _PUBLIC_ int swrap_listen(int s, int backlog)
1554 {
1555 	int ret;
1556 	struct socket_info *si = find_socket_info(s);
1557 
1558 	if (!si) {
1559 		return real_listen(s, backlog);
1560 	}
1561 
1562 	ret = real_listen(s, backlog);
1563 
1564 	return ret;
1565 }
1566 
1567 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1568 {
1569 	struct socket_info *si = find_socket_info(s);
1570 
1571 	if (!si) {
1572 		return real_getpeername(s, name, addrlen);
1573 	}
1574 
1575 	if (!si->peername)
1576 	{
1577 		errno = ENOTCONN;
1578 		return -1;
1579 	}
1580 
1581 	memcpy(name, si->peername, si->peername_len);
1582 	*addrlen = si->peername_len;
1583 
1584 	return 0;
1585 }
1586 
1587 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1588 {
1589 	struct socket_info *si = find_socket_info(s);
1590 
1591 	if (!si) {
1592 		return real_getsockname(s, name, addrlen);
1593 	}
1594 
1595 	memcpy(name, si->myname, si->myname_len);
1596 	*addrlen = si->myname_len;
1597 
1598 	return 0;
1599 }
1600 
1601 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1602 {
1603 	struct socket_info *si = find_socket_info(s);
1604 
1605 	if (!si) {
1606 		return real_getsockopt(s, level, optname, optval, optlen);
1607 	}
1608 
1609 	if (level == SOL_SOCKET) {
1610 		return real_getsockopt(s, level, optname, optval, optlen);
1611 	}
1612 
1613 	errno = ENOPROTOOPT;
1614 	return -1;
1615 }
1616 
1617 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
1618 {
1619 	struct socket_info *si = find_socket_info(s);
1620 
1621 	if (!si) {
1622 		return real_setsockopt(s, level, optname, optval, optlen);
1623 	}
1624 
1625 	if (level == SOL_SOCKET) {
1626 		return real_setsockopt(s, level, optname, optval, optlen);
1627 	}
1628 
1629 	switch (si->family) {
1630 	case AF_INET:
1631 		return 0;
1632 	default:
1633 		errno = ENOPROTOOPT;
1634 		return -1;
1635 	}
1636 }
1637 
1638 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1639 {
1640 	struct sockaddr_un un_addr;
1641 	socklen_t un_addrlen = sizeof(un_addr);
1642 	int ret;
1643 	struct socket_info *si = find_socket_info(s);
1644 
1645 	if (!si) {
1646 		return real_recvfrom(s, buf, len, flags, from, fromlen);
1647 	}
1648 
1649 	/* irix 6.4 forgets to null terminate the sun_path string :-( */
1650 	memset(&un_addr, 0, sizeof(un_addr));
1651 	ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1652 	if (ret == -1)
1653 		return ret;
1654 
1655 	if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1656 				     si->family, from, fromlen) == -1) {
1657 		return -1;
1658 	}
1659 
1660 	swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1661 
1662 	return ret;
1663 }
1664 
1665 
1666 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1667 {
1668 	struct sockaddr_un un_addr;
1669 	int ret;
1670 	struct socket_info *si = find_socket_info(s);
1671 	int bcast = 0;
1672 
1673 	if (!si) {
1674 		return real_sendto(s, buf, len, flags, to, tolen);
1675 	}
1676 
1677 	switch (si->type) {
1678 	case SOCK_STREAM:
1679 		ret = real_send(s, buf, len, flags);
1680 		break;
1681 	case SOCK_DGRAM:
1682 		if (si->bound == 0) {
1683 			ret = swrap_auto_bind(si);
1684 			if (ret == -1) return -1;
1685 		}
1686 
1687 		ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1688 		if (ret == -1) return -1;
1689 
1690 		if (bcast) {
1691 			struct stat st;
1692 			unsigned int iface;
1693 			unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1694 			char type;
1695 
1696 			type = SOCKET_TYPE_CHAR_UDP;
1697 
1698 			for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1699 				snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1700 					 socket_wrapper_dir(), type, iface, prt);
1701 				if (stat(un_addr.sun_path, &st) != 0) continue;
1702 
1703 				/* ignore the any errors in broadcast sends */
1704 				real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1705 			}
1706 
1707 			swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1708 
1709 			return len;
1710 		}
1711 
1712 		ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1713 		break;
1714 	default:
1715 		ret = -1;
1716 		errno = EHOSTUNREACH;
1717 		break;
1718 	}
1719 
1720 	/* to give better errors */
1721 	if (ret == -1 && errno == ENOENT) {
1722 		errno = EHOSTUNREACH;
1723 	}
1724 
1725 	if (ret == -1) {
1726 		swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1727 		swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1728 	} else {
1729 		swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1730 	}
1731 
1732 	return ret;
1733 }
1734 
1735 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1736 {
1737 	int ret;
1738 	struct socket_info *si = find_socket_info(s);
1739 	int value;
1740 
1741 	if (!si) {
1742 		return real_ioctl(s, r, p);
1743 	}
1744 
1745 	ret = real_ioctl(s, r, p);
1746 
1747 	switch (r) {
1748 	case FIONREAD:
1749 		value = *((int *)p);
1750 		if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1751 			swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1752 		} else if (value == 0) { /* END OF FILE */
1753 			swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1754 		}
1755 		break;
1756 	}
1757 
1758 	return ret;
1759 }
1760 
1761 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1762 {
1763 	int ret;
1764 	struct socket_info *si = find_socket_info(s);
1765 
1766 	if (!si) {
1767 		return real_recv(s, buf, len, flags);
1768 	}
1769 
1770 	ret = real_recv(s, buf, len, flags);
1771 	if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1772 		swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1773 	} else if (ret == 0) { /* END OF FILE */
1774 		swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1775 	} else {
1776 		swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1777 	}
1778 
1779 	return ret;
1780 }
1781 
1782 
1783 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1784 {
1785 	int ret;
1786 	struct socket_info *si = find_socket_info(s);
1787 
1788 	if (!si) {
1789 		return real_send(s, buf, len, flags);
1790 	}
1791 
1792 	ret = real_send(s, buf, len, flags);
1793 
1794 	if (ret == -1) {
1795 		swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1796 		swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1797 	} else {
1798 		swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1799 	}
1800 
1801 	return ret;
1802 }
1803 
1804 _PUBLIC_ int swrap_close(int fd)
1805 {
1806 	struct socket_info *si = find_socket_info(fd);
1807 	int ret;
1808 
1809 	if (!si) {
1810 		return real_close(fd);
1811 	}
1812 
1813 	SWRAP_DLIST_REMOVE(sockets, si);
1814 
1815 	if (si->myname && si->peername) {
1816 		swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1817 	}
1818 
1819 	ret = real_close(fd);
1820 
1821 	if (si->myname && si->peername) {
1822 		swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1823 		swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1824 	}
1825 
1826 	if (si->path) free(si->path);
1827 	if (si->myname) free(si->myname);
1828 	if (si->peername) free(si->peername);
1829 	if (si->tmp_path) {
1830 		unlink(si->tmp_path);
1831 		free(si->tmp_path);
1832 	}
1833 	free(si);
1834 
1835 	return ret;
1836 }
1837 
1838 static int
1839 dup_internal(const struct socket_info *si_oldd, int fd)
1840 {
1841 	struct socket_info *si_newd;
1842 
1843 	si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1844 
1845 	si_newd->fd = fd;
1846 
1847 	si_newd->family = si_oldd->family;
1848 	si_newd->type = si_oldd->type;
1849 	si_newd->protocol = si_oldd->protocol;
1850 	si_newd->bound = si_oldd->bound;
1851 	si_newd->bcast = si_oldd->bcast;
1852 	if (si_oldd->path)
1853 		si_newd->path = strdup(si_oldd->path);
1854 	if (si_oldd->tmp_path)
1855 		si_newd->tmp_path = strdup(si_oldd->tmp_path);
1856 	si_newd->myname =
1857 	    sockaddr_dup(si_oldd->myname, si_oldd->myname_len);
1858 	si_newd->myname_len = si_oldd->myname_len;
1859 	si_newd->peername =
1860 	    sockaddr_dup(si_oldd->peername, si_oldd->peername_len);
1861 	si_newd->peername_len = si_oldd->peername_len;
1862 
1863 	si_newd->io = si_oldd->io;
1864 
1865 	SWRAP_DLIST_ADD(sockets, si_newd);
1866 
1867 	return fd;
1868 }
1869 
1870 
1871 _PUBLIC_ int swrap_dup(int oldd)
1872 {
1873 	struct socket_info *si;
1874 	int fd;
1875 
1876 	si = find_socket_info(oldd);
1877 	if (si == NULL)
1878 		return real_dup(oldd);
1879 
1880 	fd = real_dup(si->fd);
1881 	if (fd < 0)
1882 		return fd;
1883 
1884 	return dup_internal(si, fd);
1885 }
1886 
1887 
1888 _PUBLIC_ int swrap_dup2(int oldd, int newd)
1889 {
1890 	struct socket_info *si_newd, *si_oldd;
1891 	int fd;
1892 
1893 	if (newd == oldd)
1894 	    return newd;
1895 
1896 	si_oldd = find_socket_info(oldd);
1897 	si_newd = find_socket_info(newd);
1898 
1899 	if (si_oldd == NULL && si_newd == NULL)
1900 		return real_dup2(oldd, newd);
1901 
1902 	fd = real_dup2(si_oldd->fd, newd);
1903 	if (fd < 0)
1904 		return fd;
1905 
1906 	/* close new socket first */
1907 	if (si_newd)
1908 	       	swrap_close(newd);
1909 
1910 	return dup_internal(si_oldd, fd);
1911 }
1912