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