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