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