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