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