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
176static 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
183static 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
197static 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
212struct 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
240static struct socket_info *sockets;
241
242
243static 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
255static 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
270static 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
340static 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
438static 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
546static 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
557static 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
591static 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
628enum 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
649struct 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
661struct 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
718static 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
769static 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
904static 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
930static 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
1370static int autobind_start_init;
1371static 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 */
1377static 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
1838static int
1839dup_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