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