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