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