tsocket: remove DGRAM support from tsocket_context
[ira/wip.git] / lib / socket_wrapper / socket_wrapper.c
1 /*
2  * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3  * Copyright (C) Stefan Metzmacher 2006-2009 <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 "../replace/replace.h"
46 #include "system/network.h"
47 #include "system/filesys.h"
48 #include "system/time.h"
49
50 #else /* _SAMBA_BUILD_ */
51
52 #include <sys/types.h>
53 #include <sys/time.h>
54 #include <sys/stat.h>
55 #include <sys/socket.h>
56 #include <sys/ioctl.h>
57 #include <sys/filio.h>
58 #include <errno.h>
59 #include <sys/un.h>
60 #include <netinet/in.h>
61 #include <netinet/tcp.h>
62 #include <fcntl.h>
63 #include <stdlib.h>
64 #include <unistd.h>
65 #include <string.h>
66 #include <stdio.h>
67 #include <stdint.h>
68
69 #endif
70
71 #ifndef _PUBLIC_
72 #define _PUBLIC_
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_readv readv
125 #define real_writev writev
126 #define real_socket socket
127 #define real_close close
128 #endif
129
130 #ifdef HAVE_GETTIMEOFDAY_TZ
131 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
132 #else
133 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
134 #endif
135
136 /* we need to use a very terse format here as IRIX 6.4 silently
137    truncates names to 16 chars, so if we use a longer name then we
138    can't tell which port a packet came from with recvfrom() 
139    
140    with this format we have 8 chars left for the directory name
141 */
142 #define SOCKET_FORMAT "%c%02X%04X"
143 #define SOCKET_TYPE_CHAR_TCP            'T'
144 #define SOCKET_TYPE_CHAR_UDP            'U'
145 #define SOCKET_TYPE_CHAR_TCP_V6         'X'
146 #define SOCKET_TYPE_CHAR_UDP_V6         'Y'
147
148 #define MAX_WRAPPED_INTERFACES 16
149
150 #ifdef HAVE_IPV6
151 /*
152  * FD00::5357:5FXX
153  */
154 static const struct in6_addr *swrap_ipv6(void)
155 {
156         static struct in6_addr v;
157         static int initialized;
158         int ret;
159
160         if (initialized) {
161                 return &v;
162         }
163         initialized = 1;
164
165         ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
166         if (ret <= 0) {
167                 abort();
168         }
169
170         return &v;
171 }
172 #endif
173
174 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
175 {
176         struct sockaddr *ret = (struct sockaddr *)malloc(len);
177         memcpy(ret, data, len);
178         return ret;
179 }
180
181 static void set_port(int family, int prt, struct sockaddr *addr)
182 {
183         switch (family) {
184         case AF_INET:
185                 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
186                 break;
187 #ifdef HAVE_IPV6
188         case AF_INET6:
189                 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
190                 break;
191 #endif
192         }
193 }
194
195 static size_t socket_length(int family)
196 {
197         switch (family) {
198         case AF_INET:
199                 return sizeof(struct sockaddr_in);
200 #ifdef HAVE_IPV6
201         case AF_INET6:
202                 return sizeof(struct sockaddr_in6);
203 #endif
204         }
205         return 0;
206 }
207
208
209
210 struct socket_info
211 {
212         int fd;
213
214         int family;
215         int type;
216         int protocol;
217         int bound;
218         int bcast;
219         int is_server;
220         int connected;
221         int defer_connect;
222
223         char *path;
224         char *tmp_path;
225
226         struct sockaddr *myname;
227         socklen_t myname_len;
228
229         struct sockaddr *peername;
230         socklen_t peername_len;
231
232         struct {
233                 unsigned long pck_snd;
234                 unsigned long pck_rcv;
235         } io;
236
237         struct socket_info *prev, *next;
238 };
239
240 static struct socket_info *sockets;
241
242 const char *socket_wrapper_dir(void)
243 {
244         const char *s = getenv("SOCKET_WRAPPER_DIR");
245         if (s == NULL) {
246                 return NULL;
247         }
248         if (strncmp(s, "./", 2) == 0) {
249                 s += 2;
250         }
251         return s;
252 }
253
254 unsigned int socket_wrapper_default_iface(void)
255 {
256         const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
257         if (s) {
258                 unsigned int iface;
259                 if (sscanf(s, "%u", &iface) == 1) {
260                         if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
261                                 return iface;
262                         }
263                 }
264         }
265
266         return 1;/* 127.0.0.1 */
267 }
268
269 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
270 {
271         unsigned int iface;
272         unsigned int prt;
273         const char *p;
274         char type;
275
276         p = strrchr(un->sun_path, '/');
277         if (p) p++; else p = un->sun_path;
278
279         if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
280                 errno = EINVAL;
281                 return -1;
282         }
283
284         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
285                 errno = EINVAL;
286                 return -1;
287         }
288
289         if (prt > 0xFFFF) {
290                 errno = EINVAL;
291                 return -1;
292         }
293
294         switch(type) {
295         case SOCKET_TYPE_CHAR_TCP:
296         case SOCKET_TYPE_CHAR_UDP: {
297                 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
298                 
299                 if ((*len) < sizeof(*in2)) {
300                     errno = EINVAL;
301                     return -1;
302                 }
303
304                 memset(in2, 0, sizeof(*in2));
305                 in2->sin_family = AF_INET;
306                 in2->sin_addr.s_addr = htonl((127<<24) | iface);
307                 in2->sin_port = htons(prt);
308
309                 *len = sizeof(*in2);
310                 break;
311         }
312 #ifdef HAVE_IPV6
313         case SOCKET_TYPE_CHAR_TCP_V6:
314         case SOCKET_TYPE_CHAR_UDP_V6: {
315                 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
316                 
317                 if ((*len) < sizeof(*in2)) {
318                         errno = EINVAL;
319                         return -1;
320                 }
321
322                 memset(in2, 0, sizeof(*in2));
323                 in2->sin6_family = AF_INET6;
324                 in2->sin6_addr = *swrap_ipv6();
325                 in2->sin6_addr.s6_addr[15] = iface;
326                 in2->sin6_port = htons(prt);
327
328                 *len = sizeof(*in2);
329                 break;
330         }
331 #endif
332         default:
333                 errno = EINVAL;
334                 return -1;
335         }
336
337         return 0;
338 }
339
340 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
341                                 int *bcast)
342 {
343         char type = '\0';
344         unsigned int prt;
345         unsigned int iface;
346         int is_bcast = 0;
347
348         if (bcast) *bcast = 0;
349
350         switch (si->family) {
351         case AF_INET: {
352                 const struct sockaddr_in *in = 
353                     (const struct sockaddr_in *)inaddr;
354                 unsigned int addr = ntohl(in->sin_addr.s_addr);
355                 char u_type = '\0';
356                 char b_type = '\0';
357                 char a_type = '\0';
358
359                 switch (si->type) {
360                 case SOCK_STREAM:
361                         u_type = SOCKET_TYPE_CHAR_TCP;
362                         break;
363                 case SOCK_DGRAM:
364                         u_type = SOCKET_TYPE_CHAR_UDP;
365                         a_type = SOCKET_TYPE_CHAR_UDP;
366                         b_type = SOCKET_TYPE_CHAR_UDP;
367                         break;
368                 }
369
370                 prt = ntohs(in->sin_port);
371                 if (a_type && addr == 0xFFFFFFFF) {
372                         /* 255.255.255.255 only udp */
373                         is_bcast = 2;
374                         type = a_type;
375                         iface = socket_wrapper_default_iface();
376                 } else if (b_type && addr == 0x7FFFFFFF) {
377                         /* 127.255.255.255 only udp */
378                         is_bcast = 1;
379                         type = b_type;
380                         iface = socket_wrapper_default_iface();
381                 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
382                         /* 127.0.0.X */
383                         is_bcast = 0;
384                         type = u_type;
385                         iface = (addr & 0x000000FF);
386                 } else {
387                         errno = ENETUNREACH;
388                         return -1;
389                 }
390                 if (bcast) *bcast = is_bcast;
391                 break;
392         }
393 #ifdef HAVE_IPV6
394         case AF_INET6: {
395                 const struct sockaddr_in6 *in = 
396                     (const struct sockaddr_in6 *)inaddr;
397                 struct in6_addr cmp;
398
399                 switch (si->type) {
400                 case SOCK_STREAM:
401                         type = SOCKET_TYPE_CHAR_TCP_V6;
402                         break;
403                 case SOCK_DGRAM:
404                         type = SOCKET_TYPE_CHAR_UDP_V6;
405                         break;
406                 }
407
408                 /* XXX no multicast/broadcast */
409
410                 prt = ntohs(in->sin6_port);
411
412                 cmp = in->sin6_addr;
413                 cmp.s6_addr[15] = 0;
414                 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
415                         iface = in->sin6_addr.s6_addr[15];
416                 } else {
417                         errno = ENETUNREACH;
418                         return -1;
419                 }
420
421                 break;
422         }
423 #endif
424         default:
425                 errno = ENETUNREACH;
426                 return -1;
427         }
428
429         if (prt == 0) {
430                 errno = EINVAL;
431                 return -1;
432         }
433
434         if (is_bcast) {
435                 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
436                          socket_wrapper_dir());
437                 /* the caller need to do more processing */
438                 return 0;
439         }
440
441         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
442                  socket_wrapper_dir(), type, iface, prt);
443
444         return 0;
445 }
446
447 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
448                                int *bcast)
449 {
450         char type = '\0';
451         unsigned int prt;
452         unsigned int iface;
453         struct stat st;
454         int is_bcast = 0;
455
456         if (bcast) *bcast = 0;
457
458         switch (si->family) {
459         case AF_INET: {
460                 const struct sockaddr_in *in = 
461                     (const struct sockaddr_in *)inaddr;
462                 unsigned int addr = ntohl(in->sin_addr.s_addr);
463                 char u_type = '\0';
464                 char d_type = '\0';
465                 char b_type = '\0';
466                 char a_type = '\0';
467
468                 prt = ntohs(in->sin_port);
469
470                 switch (si->type) {
471                 case SOCK_STREAM:
472                         u_type = SOCKET_TYPE_CHAR_TCP;
473                         d_type = SOCKET_TYPE_CHAR_TCP;
474                         break;
475                 case SOCK_DGRAM:
476                         u_type = SOCKET_TYPE_CHAR_UDP;
477                         d_type = SOCKET_TYPE_CHAR_UDP;
478                         a_type = SOCKET_TYPE_CHAR_UDP;
479                         b_type = SOCKET_TYPE_CHAR_UDP;
480                         break;
481                 }
482
483                 if (addr == 0) {
484                         /* 0.0.0.0 */
485                         is_bcast = 0;
486                         type = d_type;
487                         iface = socket_wrapper_default_iface();
488                 } else if (a_type && addr == 0xFFFFFFFF) {
489                         /* 255.255.255.255 only udp */
490                         is_bcast = 2;
491                         type = a_type;
492                         iface = socket_wrapper_default_iface();
493                 } else if (b_type && addr == 0x7FFFFFFF) {
494                         /* 127.255.255.255 only udp */
495                         is_bcast = 1;
496                         type = b_type;
497                         iface = socket_wrapper_default_iface();
498                 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
499                         /* 127.0.0.X */
500                         is_bcast = 0;
501                         type = u_type;
502                         iface = (addr & 0x000000FF);
503                 } else {
504                         errno = EADDRNOTAVAIL;
505                         return -1;
506                 }
507                 break;
508         }
509 #ifdef HAVE_IPV6
510         case AF_INET6: {
511                 const struct sockaddr_in6 *in = 
512                     (const struct sockaddr_in6 *)inaddr;
513                 struct in6_addr cmp;
514
515                 switch (si->type) {
516                 case SOCK_STREAM:
517                         type = SOCKET_TYPE_CHAR_TCP_V6;
518                         break;
519                 case SOCK_DGRAM:
520                         type = SOCKET_TYPE_CHAR_UDP_V6;
521                         break;
522                 }
523
524                 /* XXX no multicast/broadcast */
525
526                 prt = ntohs(in->sin6_port);
527
528                 cmp = in->sin6_addr;
529                 cmp.s6_addr[15] = 0;
530                 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
531                         iface = socket_wrapper_default_iface();
532                 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
533                         iface = in->sin6_addr.s6_addr[15];
534                 } else {
535                         errno = EADDRNOTAVAIL;
536                         return -1;
537                 }
538
539                 break;
540         }
541 #endif
542         default:
543                 errno = EADDRNOTAVAIL;
544                 return -1;
545         }
546
547
548         if (bcast) *bcast = is_bcast;
549
550         if (prt == 0) {
551                 /* handle auto-allocation of ephemeral ports */
552                 for (prt = 5001; prt < 10000; prt++) {
553                         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
554                                  socket_wrapper_dir(), type, iface, prt);
555                         if (stat(un->sun_path, &st) == 0) continue;
556
557                         set_port(si->family, prt, si->myname);
558                         break;
559                 }
560                 if (prt == 10000) {
561                         errno = ENFILE;
562                         return -1;
563                 }
564         }
565
566         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
567                  socket_wrapper_dir(), type, iface, prt);
568         return 0;
569 }
570
571 static struct socket_info *find_socket_info(int fd)
572 {
573         struct socket_info *i;
574         for (i = sockets; i; i = i->next) {
575                 if (i->fd == fd) 
576                         return i;
577         }
578
579         return NULL;
580 }
581
582 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 
583                                   struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
584 {
585         if (!out_addr)
586                 return 0;
587
588         out_addr->sun_family = AF_UNIX;
589
590         switch (in_addr->sa_family) {
591         case AF_INET:
592 #ifdef HAVE_IPV6
593         case AF_INET6:
594 #endif
595                 switch (si->type) {
596                 case SOCK_STREAM:
597                 case SOCK_DGRAM:
598                         break;
599                 default:
600                         errno = ESOCKTNOSUPPORT;
601                         return -1;
602                 }
603                 if (alloc_sock) {
604                         return convert_in_un_alloc(si, in_addr, out_addr, bcast);
605                 } else {
606                         return convert_in_un_remote(si, in_addr, out_addr, bcast);
607                 }
608         default:
609                 break;
610         }
611         
612         errno = EAFNOSUPPORT;
613         return -1;
614 }
615
616 static int sockaddr_convert_from_un(const struct socket_info *si, 
617                                     const struct sockaddr_un *in_addr, 
618                                     socklen_t un_addrlen,
619                                     int family,
620                                     struct sockaddr *out_addr,
621                                     socklen_t *out_addrlen)
622 {
623         if (out_addr == NULL || out_addrlen == NULL) 
624                 return 0;
625
626         if (un_addrlen == 0) {
627                 *out_addrlen = 0;
628                 return 0;
629         }
630
631         switch (family) {
632         case AF_INET:
633 #ifdef HAVE_IPV6
634         case AF_INET6:
635 #endif
636                 switch (si->type) {
637                 case SOCK_STREAM:
638                 case SOCK_DGRAM:
639                         break;
640                 default:
641                         errno = ESOCKTNOSUPPORT;
642                         return -1;
643                 }
644                 return convert_un_in(in_addr, out_addr, out_addrlen);
645         default:
646                 break;
647         }
648
649         errno = EAFNOSUPPORT;
650         return -1;
651 }
652
653 enum swrap_packet_type {
654         SWRAP_CONNECT_SEND,
655         SWRAP_CONNECT_UNREACH,
656         SWRAP_CONNECT_RECV,
657         SWRAP_CONNECT_ACK,
658         SWRAP_ACCEPT_SEND,
659         SWRAP_ACCEPT_RECV,
660         SWRAP_ACCEPT_ACK,
661         SWRAP_RECVFROM,
662         SWRAP_SENDTO,
663         SWRAP_SENDTO_UNREACH,
664         SWRAP_PENDING_RST,
665         SWRAP_RECV,
666         SWRAP_RECV_RST,
667         SWRAP_SEND,
668         SWRAP_SEND_RST,
669         SWRAP_CLOSE_SEND,
670         SWRAP_CLOSE_RECV,
671         SWRAP_CLOSE_ACK
672 };
673
674 struct swrap_file_hdr {
675         uint32_t        magic;
676         uint16_t        version_major;
677         uint16_t        version_minor;
678         int32_t         timezone;
679         uint32_t        sigfigs;
680         uint32_t        frame_max_len;
681 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
682         uint32_t        link_type;
683 };
684 #define SWRAP_FILE_HDR_SIZE 24
685
686 struct swrap_packet_frame {
687         uint32_t seconds;
688         uint32_t micro_seconds;
689         uint32_t recorded_length;
690         uint32_t full_length;
691 };
692 #define SWRAP_PACKET_FRAME_SIZE 16
693
694 union swrap_packet_ip {
695         struct {
696                 uint8_t         ver_hdrlen;
697                 uint8_t         tos;
698                 uint16_t        packet_length;
699                 uint16_t        identification;
700                 uint8_t         flags;
701                 uint8_t         fragment;
702                 uint8_t         ttl;
703                 uint8_t         protocol;
704                 uint16_t        hdr_checksum;
705                 uint32_t        src_addr;
706                 uint32_t        dest_addr;
707         } v4;
708 #define SWRAP_PACKET_IP_V4_SIZE 20
709         struct {
710                 uint8_t         ver_prio;
711                 uint8_t         flow_label_high;
712                 uint16_t        flow_label_low;
713                 uint16_t        payload_length;
714                 uint8_t         next_header;
715                 uint8_t         hop_limit;
716                 uint8_t         src_addr[16];
717                 uint8_t         dest_addr[16];
718         } v6;
719 #define SWRAP_PACKET_IP_V6_SIZE 40
720 };
721 #define SWRAP_PACKET_IP_SIZE 40
722
723 union swrap_packet_payload {
724         struct {
725                 uint16_t        source_port;
726                 uint16_t        dest_port;
727                 uint32_t        seq_num;
728                 uint32_t        ack_num;
729                 uint8_t         hdr_length;
730                 uint8_t         control;
731                 uint16_t        window;
732                 uint16_t        checksum;
733                 uint16_t        urg;
734         } tcp;
735 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
736         struct {
737                 uint16_t        source_port;
738                 uint16_t        dest_port;
739                 uint16_t        length;
740                 uint16_t        checksum;
741         } udp;
742 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
743         struct {
744                 uint8_t         type;
745                 uint8_t         code;
746                 uint16_t        checksum;
747                 uint32_t        unused;
748         } icmp4;
749 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
750         struct {
751                 uint8_t         type;
752                 uint8_t         code;
753                 uint16_t        checksum;
754                 uint32_t        unused;
755         } icmp6;
756 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
757 };
758 #define SWRAP_PACKET_PAYLOAD_SIZE 20
759
760 #define SWRAP_PACKET_MIN_ALLOC \
761         (SWRAP_PACKET_FRAME_SIZE + \
762          SWRAP_PACKET_IP_SIZE + \
763          SWRAP_PACKET_PAYLOAD_SIZE)
764
765 static const char *socket_wrapper_pcap_file(void)
766 {
767         static int initialized = 0;
768         static const char *s = NULL;
769         static const struct swrap_file_hdr h;
770         static const struct swrap_packet_frame f;
771         static const union swrap_packet_ip i;
772         static const union swrap_packet_payload p;
773
774         if (initialized == 1) {
775                 return s;
776         }
777         initialized = 1;
778
779         /*
780          * TODO: don't use the structs use plain buffer offsets
781          *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
782          * 
783          * for now make sure we disable PCAP support
784          * if the struct has alignment!
785          */
786         if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
787                 return NULL;
788         }
789         if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
790                 return NULL;
791         }
792         if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
793                 return NULL;
794         }
795         if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
796                 return NULL;
797         }
798         if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
799                 return NULL;
800         }
801         if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
802                 return NULL;
803         }
804         if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
805                 return NULL;
806         }
807         if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
808                 return NULL;
809         }
810         if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
811                 return NULL;
812         }
813         if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
814                 return NULL;
815         }
816
817         s = getenv("SOCKET_WRAPPER_PCAP_FILE");
818         if (s == NULL) {
819                 return NULL;
820         }
821         if (strncmp(s, "./", 2) == 0) {
822                 s += 2;
823         }
824         return s;
825 }
826
827 static uint8_t *swrap_packet_init(struct timeval *tval,
828                                   const struct sockaddr *src,
829                                   const struct sockaddr *dest,
830                                   int socket_type,
831                                   const uint8_t *payload,
832                                   size_t payload_len,
833                                   unsigned long tcp_seqno,
834                                   unsigned long tcp_ack,
835                                   unsigned char tcp_ctl,
836                                   int unreachable,
837                                   size_t *_packet_len)
838 {
839         uint8_t *base;
840         uint8_t *buf;
841         struct swrap_packet_frame *frame;
842         union swrap_packet_ip *ip;
843         union swrap_packet_payload *pay;
844         size_t packet_len;
845         size_t alloc_len;
846         size_t nonwire_len = sizeof(*frame);
847         size_t wire_hdr_len = 0;
848         size_t wire_len = 0;
849         size_t ip_hdr_len = 0;
850         size_t icmp_hdr_len = 0;
851         size_t icmp_truncate_len = 0;
852         uint8_t protocol = 0, icmp_protocol = 0;
853         const struct sockaddr_in *src_in = NULL;
854         const struct sockaddr_in *dest_in = NULL;
855 #ifdef HAVE_IPV6
856         const struct sockaddr_in6 *src_in6 = NULL;
857         const struct sockaddr_in6 *dest_in6 = NULL;
858 #endif
859         uint16_t src_port;
860         uint16_t dest_port;
861
862         switch (src->sa_family) {
863         case AF_INET:
864                 src_in = (const struct sockaddr_in *)src;
865                 dest_in = (const struct sockaddr_in *)dest;
866                 src_port = src_in->sin_port;
867                 dest_port = dest_in->sin_port;
868                 ip_hdr_len = sizeof(ip->v4);
869                 break;
870 #ifdef HAVE_IPV6
871         case AF_INET6:
872                 src_in6 = (const struct sockaddr_in6 *)src;
873                 dest_in6 = (const struct sockaddr_in6 *)dest;
874                 src_port = src_in6->sin6_port;
875                 dest_port = dest_in6->sin6_port;
876                 ip_hdr_len = sizeof(ip->v6);
877                 break;
878 #endif
879         default:
880                 return NULL;
881         }
882
883         switch (socket_type) {
884         case SOCK_STREAM:
885                 protocol = 0x06; /* TCP */
886                 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
887                 wire_len = wire_hdr_len + payload_len;
888                 break;
889
890         case SOCK_DGRAM:
891                 protocol = 0x11; /* UDP */
892                 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
893                 wire_len = wire_hdr_len + payload_len;
894                 break;
895
896         default:
897                 return NULL;
898         }
899
900         if (unreachable) {
901                 icmp_protocol = protocol;
902                 switch (src->sa_family) {
903                 case AF_INET:
904                         protocol = 0x01; /* ICMPv4 */
905                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
906                         break;
907 #ifdef HAVE_IPV6
908                 case AF_INET6:
909                         protocol = 0x3A; /* ICMPv6 */
910                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
911                         break;
912 #endif
913                 }
914                 if (wire_len > 64 ) {
915                         icmp_truncate_len = wire_len - 64;
916                 }
917                 wire_hdr_len += icmp_hdr_len;
918                 wire_len += icmp_hdr_len;
919         }
920
921         packet_len = nonwire_len + wire_len;
922         alloc_len = packet_len;
923         if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
924                 alloc_len = SWRAP_PACKET_MIN_ALLOC;
925         }
926
927         base = (uint8_t *)malloc(alloc_len);
928         if (!base) return NULL;
929
930         buf = base;
931
932         frame = (struct swrap_packet_frame *)buf;
933         frame->seconds          = tval->tv_sec;
934         frame->micro_seconds    = tval->tv_usec;
935         frame->recorded_length  = wire_len - icmp_truncate_len;
936         frame->full_length      = wire_len - icmp_truncate_len;
937         buf += SWRAP_PACKET_FRAME_SIZE;
938
939         ip = (union swrap_packet_ip *)buf;
940         switch (src->sa_family) {
941         case AF_INET:
942                 ip->v4.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
943                 ip->v4.tos              = 0x00;
944                 ip->v4.packet_length    = htons(wire_len - icmp_truncate_len);
945                 ip->v4.identification   = htons(0xFFFF);
946                 ip->v4.flags            = 0x40; /* BIT 1 set - means don't fraqment */
947                 ip->v4.fragment         = htons(0x0000);
948                 ip->v4.ttl              = 0xFF;
949                 ip->v4.protocol         = protocol;
950                 ip->v4.hdr_checksum     = htons(0x0000);
951                 ip->v4.src_addr         = src_in->sin_addr.s_addr;
952                 ip->v4.dest_addr        = dest_in->sin_addr.s_addr;
953                 buf += SWRAP_PACKET_IP_V4_SIZE;
954                 break;
955 #ifdef HAVE_IPV6
956         case AF_INET6:
957                 ip->v6.ver_prio         = 0x60; /* version 4 and 5 * 32 bit words */
958                 ip->v6.flow_label_high  = 0x00;
959                 ip->v6.flow_label_low   = 0x0000;
960                 ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
961                 ip->v6.next_header      = protocol;
962                 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
963                 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
964                 buf += SWRAP_PACKET_IP_V6_SIZE;
965                 break;
966 #endif
967         }
968
969         if (unreachable) {
970                 pay = (union swrap_packet_payload *)buf;
971                 switch (src->sa_family) {
972                 case AF_INET:
973                         pay->icmp4.type         = 0x03; /* destination unreachable */
974                         pay->icmp4.code         = 0x01; /* host unreachable */
975                         pay->icmp4.checksum     = htons(0x0000);
976                         pay->icmp4.unused       = htonl(0x00000000);
977                         buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
978
979                         /* set the ip header in the ICMP payload */
980                         ip = (union swrap_packet_ip *)buf;
981                         ip->v4.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
982                         ip->v4.tos              = 0x00;
983                         ip->v4.packet_length    = htons(wire_len - icmp_hdr_len);
984                         ip->v4.identification   = htons(0xFFFF);
985                         ip->v4.flags            = 0x40; /* BIT 1 set - means don't fraqment */
986                         ip->v4.fragment         = htons(0x0000);
987                         ip->v4.ttl              = 0xFF;
988                         ip->v4.protocol         = icmp_protocol;
989                         ip->v4.hdr_checksum     = htons(0x0000);
990                         ip->v4.src_addr         = dest_in->sin_addr.s_addr;
991                         ip->v4.dest_addr        = src_in->sin_addr.s_addr;
992                         buf += SWRAP_PACKET_IP_V4_SIZE;
993
994                         src_port = dest_in->sin_port;
995                         dest_port = src_in->sin_port;
996                         break;
997 #ifdef HAVE_IPV6
998                 case AF_INET6:
999                         pay->icmp6.type         = 0x01; /* destination unreachable */
1000                         pay->icmp6.code         = 0x03; /* address unreachable */
1001                         pay->icmp6.checksum     = htons(0x0000);
1002                         pay->icmp6.unused       = htonl(0x00000000);
1003                         buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1004
1005                         /* set the ip header in the ICMP payload */
1006                         ip = (union swrap_packet_ip *)buf;
1007                         ip->v6.ver_prio         = 0x60; /* version 4 and 5 * 32 bit words */
1008                         ip->v6.flow_label_high  = 0x00;
1009                         ip->v6.flow_label_low   = 0x0000;
1010                         ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
1011                         ip->v6.next_header      = protocol;
1012                         memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1013                         memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1014                         buf += SWRAP_PACKET_IP_V6_SIZE;
1015
1016                         src_port = dest_in6->sin6_port;
1017                         dest_port = src_in6->sin6_port;
1018                         break;
1019 #endif
1020                 }
1021         }
1022
1023         pay = (union swrap_packet_payload *)buf;
1024
1025         switch (socket_type) {
1026         case SOCK_STREAM:
1027                 pay->tcp.source_port    = src_port;
1028                 pay->tcp.dest_port      = dest_port;
1029                 pay->tcp.seq_num        = htonl(tcp_seqno);
1030                 pay->tcp.ack_num        = htonl(tcp_ack);
1031                 pay->tcp.hdr_length     = 0x50; /* 5 * 32 bit words */
1032                 pay->tcp.control        = tcp_ctl;
1033                 pay->tcp.window         = htons(0x7FFF);
1034                 pay->tcp.checksum       = htons(0x0000);
1035                 pay->tcp.urg            = htons(0x0000);
1036                 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1037
1038                 break;
1039
1040         case SOCK_DGRAM:
1041                 pay->udp.source_port    = src_port;
1042                 pay->udp.dest_port      = dest_port;
1043                 pay->udp.length         = htons(8 + payload_len);
1044                 pay->udp.checksum       = htons(0x0000);
1045                 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1046
1047                 break;
1048         }
1049
1050         if (payload && payload_len > 0) {
1051                 memcpy(buf, payload, payload_len);
1052         }
1053
1054         *_packet_len = packet_len - icmp_truncate_len;
1055         return base;
1056 }
1057
1058 static int swrap_get_pcap_fd(const char *fname)
1059 {
1060         static int fd = -1;
1061
1062         if (fd != -1) return fd;
1063
1064         fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1065         if (fd != -1) {
1066                 struct swrap_file_hdr file_hdr;
1067                 file_hdr.magic          = 0xA1B2C3D4;
1068                 file_hdr.version_major  = 0x0002;       
1069                 file_hdr.version_minor  = 0x0004;
1070                 file_hdr.timezone       = 0x00000000;
1071                 file_hdr.sigfigs        = 0x00000000;
1072                 file_hdr.frame_max_len  = SWRAP_FRAME_LENGTH_MAX;
1073                 file_hdr.link_type      = 0x0065; /* 101 RAW IP */
1074
1075                 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1076                         close(fd);
1077                         fd = -1;
1078                 }
1079                 return fd;
1080         }
1081
1082         fd = open(fname, O_WRONLY|O_APPEND, 0644);
1083
1084         return fd;
1085 }
1086
1087 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1088                                       const struct sockaddr *addr,
1089                                       enum swrap_packet_type type,
1090                                       const void *buf, size_t len,
1091                                       size_t *packet_len)
1092 {
1093         const struct sockaddr *src_addr;
1094         const struct sockaddr *dest_addr;
1095         unsigned long tcp_seqno = 0;
1096         unsigned long tcp_ack = 0;
1097         unsigned char tcp_ctl = 0;
1098         int unreachable = 0;
1099
1100         struct timeval tv;
1101
1102         switch (si->family) {
1103         case AF_INET:
1104                 break;
1105         case AF_INET6:
1106                 break;
1107         default:
1108                 return NULL;
1109         }
1110
1111         switch (type) {
1112         case SWRAP_CONNECT_SEND:
1113                 if (si->type != SOCK_STREAM) return NULL;
1114
1115                 src_addr = si->myname;
1116                 dest_addr = addr;
1117
1118                 tcp_seqno = si->io.pck_snd;
1119                 tcp_ack = si->io.pck_rcv;
1120                 tcp_ctl = 0x02; /* SYN */
1121
1122                 si->io.pck_snd += 1;
1123
1124                 break;
1125
1126         case SWRAP_CONNECT_RECV:
1127                 if (si->type != SOCK_STREAM) return NULL;
1128
1129                 dest_addr = si->myname;
1130                 src_addr = addr;
1131
1132                 tcp_seqno = si->io.pck_rcv;
1133                 tcp_ack = si->io.pck_snd;
1134                 tcp_ctl = 0x12; /** SYN,ACK */
1135
1136                 si->io.pck_rcv += 1;
1137
1138                 break;
1139
1140         case SWRAP_CONNECT_UNREACH:
1141                 if (si->type != SOCK_STREAM) return NULL;
1142
1143                 dest_addr = si->myname;
1144                 src_addr = addr;
1145
1146                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1147                 tcp_seqno = si->io.pck_snd - 1;
1148                 tcp_ack = si->io.pck_rcv;
1149                 tcp_ctl = 0x02; /* SYN */
1150                 unreachable = 1;
1151
1152                 break;
1153
1154         case SWRAP_CONNECT_ACK:
1155                 if (si->type != SOCK_STREAM) return NULL;
1156
1157                 src_addr = si->myname;
1158                 dest_addr = addr;
1159
1160                 tcp_seqno = si->io.pck_snd;
1161                 tcp_ack = si->io.pck_rcv;
1162                 tcp_ctl = 0x10; /* ACK */
1163
1164                 break;
1165
1166         case SWRAP_ACCEPT_SEND:
1167                 if (si->type != SOCK_STREAM) return NULL;
1168
1169                 dest_addr = si->myname;
1170                 src_addr = addr;
1171
1172                 tcp_seqno = si->io.pck_rcv;
1173                 tcp_ack = si->io.pck_snd;
1174                 tcp_ctl = 0x02; /* SYN */
1175
1176                 si->io.pck_rcv += 1;
1177
1178                 break;
1179
1180         case SWRAP_ACCEPT_RECV:
1181                 if (si->type != SOCK_STREAM) return NULL;
1182
1183                 src_addr = si->myname;
1184                 dest_addr = addr;
1185
1186                 tcp_seqno = si->io.pck_snd;
1187                 tcp_ack = si->io.pck_rcv;
1188                 tcp_ctl = 0x12; /* SYN,ACK */
1189
1190                 si->io.pck_snd += 1;
1191
1192                 break;
1193
1194         case SWRAP_ACCEPT_ACK:
1195                 if (si->type != SOCK_STREAM) return NULL;
1196
1197                 dest_addr = si->myname;
1198                 src_addr = addr;
1199
1200                 tcp_seqno = si->io.pck_rcv;
1201                 tcp_ack = si->io.pck_snd;
1202                 tcp_ctl = 0x10; /* ACK */
1203
1204                 break;
1205
1206         case SWRAP_SEND:
1207                 src_addr = si->myname;
1208                 dest_addr = si->peername;
1209
1210                 tcp_seqno = si->io.pck_snd;
1211                 tcp_ack = si->io.pck_rcv;
1212                 tcp_ctl = 0x18; /* PSH,ACK */
1213
1214                 si->io.pck_snd += len;
1215
1216                 break;
1217
1218         case SWRAP_SEND_RST:
1219                 dest_addr = si->myname;
1220                 src_addr = si->peername;
1221
1222                 if (si->type == SOCK_DGRAM) {
1223                         return swrap_marshall_packet(si, si->peername,
1224                                           SWRAP_SENDTO_UNREACH,
1225                                           buf, len, packet_len);
1226                 }
1227
1228                 tcp_seqno = si->io.pck_rcv;
1229                 tcp_ack = si->io.pck_snd;
1230                 tcp_ctl = 0x14; /** RST,ACK */
1231
1232                 break;
1233
1234         case SWRAP_PENDING_RST:
1235                 dest_addr = si->myname;
1236                 src_addr = si->peername;
1237
1238                 if (si->type == SOCK_DGRAM) {
1239                         return NULL;
1240                 }
1241
1242                 tcp_seqno = si->io.pck_rcv;
1243                 tcp_ack = si->io.pck_snd;
1244                 tcp_ctl = 0x14; /* RST,ACK */
1245
1246                 break;
1247
1248         case SWRAP_RECV:
1249                 dest_addr = si->myname;
1250                 src_addr = si->peername;
1251
1252                 tcp_seqno = si->io.pck_rcv;
1253                 tcp_ack = si->io.pck_snd;
1254                 tcp_ctl = 0x18; /* PSH,ACK */
1255
1256                 si->io.pck_rcv += len;
1257
1258                 break;
1259
1260         case SWRAP_RECV_RST:
1261                 dest_addr = si->myname;
1262                 src_addr = si->peername;
1263
1264                 if (si->type == SOCK_DGRAM) {
1265                         return NULL;
1266                 }
1267
1268                 tcp_seqno = si->io.pck_rcv;
1269                 tcp_ack = si->io.pck_snd;
1270                 tcp_ctl = 0x14; /* RST,ACK */
1271
1272                 break;
1273
1274         case SWRAP_SENDTO:
1275                 src_addr = si->myname;
1276                 dest_addr = addr;
1277
1278                 si->io.pck_snd += len;
1279
1280                 break;
1281
1282         case SWRAP_SENDTO_UNREACH:
1283                 dest_addr = si->myname;
1284                 src_addr = addr;
1285
1286                 unreachable = 1;
1287
1288                 break;
1289
1290         case SWRAP_RECVFROM:
1291                 dest_addr = si->myname;
1292                 src_addr = addr;
1293
1294                 si->io.pck_rcv += len;
1295
1296                 break;
1297
1298         case SWRAP_CLOSE_SEND:
1299                 if (si->type != SOCK_STREAM) return NULL;
1300
1301                 src_addr = si->myname;
1302                 dest_addr = si->peername;
1303
1304                 tcp_seqno = si->io.pck_snd;
1305                 tcp_ack = si->io.pck_rcv;
1306                 tcp_ctl = 0x11; /* FIN, ACK */
1307
1308                 si->io.pck_snd += 1;
1309
1310                 break;
1311
1312         case SWRAP_CLOSE_RECV:
1313                 if (si->type != SOCK_STREAM) return NULL;
1314
1315                 dest_addr = si->myname;
1316                 src_addr = si->peername;
1317
1318                 tcp_seqno = si->io.pck_rcv;
1319                 tcp_ack = si->io.pck_snd;
1320                 tcp_ctl = 0x11; /* FIN,ACK */
1321
1322                 si->io.pck_rcv += 1;
1323
1324                 break;
1325
1326         case SWRAP_CLOSE_ACK:
1327                 if (si->type != SOCK_STREAM) return NULL;
1328
1329                 src_addr = si->myname;
1330                 dest_addr = si->peername;
1331
1332                 tcp_seqno = si->io.pck_snd;
1333                 tcp_ack = si->io.pck_rcv;
1334                 tcp_ctl = 0x10; /* ACK */
1335
1336                 break;
1337         default:
1338                 return NULL;
1339         }
1340
1341         swrapGetTimeOfDay(&tv);
1342
1343         return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1344                                  (const uint8_t *)buf, len,
1345                                  tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1346                                  packet_len);
1347 }
1348
1349 static void swrap_dump_packet(struct socket_info *si,
1350                               const struct sockaddr *addr,
1351                               enum swrap_packet_type type,
1352                               const void *buf, size_t len)
1353 {
1354         const char *file_name;
1355         uint8_t *packet;
1356         size_t packet_len = 0;
1357         int fd;
1358
1359         file_name = socket_wrapper_pcap_file();
1360         if (!file_name) {
1361                 return;
1362         }
1363
1364         packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1365         if (!packet) {
1366                 return;
1367         }
1368
1369         fd = swrap_get_pcap_fd(file_name);
1370         if (fd != -1) {
1371                 if (write(fd, packet, packet_len) != packet_len) {
1372                         free(packet);
1373                         return;
1374                 }
1375         }
1376
1377         free(packet);
1378 }
1379
1380 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1381 {
1382         struct socket_info *si;
1383         int fd;
1384
1385         if (!socket_wrapper_dir()) {
1386                 return real_socket(family, type, protocol);
1387         }
1388
1389         switch (family) {
1390         case AF_INET:
1391 #ifdef HAVE_IPV6
1392         case AF_INET6:
1393 #endif
1394                 break;
1395         case AF_UNIX:
1396                 return real_socket(family, type, protocol);
1397         default:
1398                 errno = EAFNOSUPPORT;
1399                 return -1;
1400         }
1401
1402         switch (type) {
1403         case SOCK_STREAM:
1404                 break;
1405         case SOCK_DGRAM:
1406                 break;
1407         default:
1408                 errno = EPROTONOSUPPORT;
1409                 return -1;
1410         }
1411
1412         switch (protocol) {
1413         case 0:
1414                 break;
1415         case 6:
1416                 if (type == SOCK_STREAM) {
1417                         break;
1418                 }
1419                 /*fall through*/
1420         case 17:
1421                 if (type == SOCK_DGRAM) {
1422                         break;
1423                 }
1424                 /*fall through*/
1425         default:
1426                 errno = EPROTONOSUPPORT;
1427                 return -1;
1428         }
1429
1430         fd = real_socket(AF_UNIX, type, 0);
1431
1432         if (fd == -1) return -1;
1433
1434         si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1435
1436         si->family = family;
1437         si->type = type;
1438         si->protocol = protocol;
1439         si->fd = fd;
1440
1441         SWRAP_DLIST_ADD(sockets, si);
1442
1443         return si->fd;
1444 }
1445
1446 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1447 {
1448         struct socket_info *parent_si, *child_si;
1449         int fd;
1450         struct sockaddr_un un_addr;
1451         socklen_t un_addrlen = sizeof(un_addr);
1452         struct sockaddr_un un_my_addr;
1453         socklen_t un_my_addrlen = sizeof(un_my_addr);
1454         struct sockaddr *my_addr;
1455         socklen_t my_addrlen, len;
1456         int ret;
1457
1458         parent_si = find_socket_info(s);
1459         if (!parent_si) {
1460                 return real_accept(s, addr, addrlen);
1461         }
1462
1463         /* 
1464          * assume out sockaddr have the same size as the in parent
1465          * socket family
1466          */
1467         my_addrlen = socket_length(parent_si->family);
1468         if (my_addrlen <= 0) {
1469                 errno = EINVAL;
1470                 return -1;
1471         }
1472
1473         my_addr = (struct sockaddr *)malloc(my_addrlen);
1474         if (my_addr == NULL) {
1475                 return -1;
1476         }
1477
1478         memset(&un_addr, 0, sizeof(un_addr));
1479         memset(&un_my_addr, 0, sizeof(un_my_addr));
1480
1481         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1482         if (ret == -1) {
1483                 free(my_addr);
1484                 return ret;
1485         }
1486
1487         fd = ret;
1488
1489         len = my_addrlen;
1490         ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1491                                        parent_si->family, my_addr, &len);
1492         if (ret == -1) {
1493                 free(my_addr);
1494                 close(fd);
1495                 return ret;
1496         }
1497
1498         child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1499         memset(child_si, 0, sizeof(*child_si));
1500
1501         child_si->fd = fd;
1502         child_si->family = parent_si->family;
1503         child_si->type = parent_si->type;
1504         child_si->protocol = parent_si->protocol;
1505         child_si->bound = 1;
1506         child_si->is_server = 1;
1507         child_si->connected = 1;
1508
1509         child_si->peername_len = len;
1510         child_si->peername = sockaddr_dup(my_addr, len);
1511
1512         if (addr != NULL && addrlen != NULL) {
1513             *addrlen = len;
1514             if (*addrlen >= len)
1515                 memcpy(addr, my_addr, len);
1516             *addrlen = 0;
1517         }
1518
1519         ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1520         if (ret == -1) {
1521                 free(child_si);
1522                 close(fd);
1523                 return ret;
1524         }
1525
1526         len = my_addrlen;
1527         ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1528                                        child_si->family, my_addr, &len);
1529         if (ret == -1) {
1530                 free(child_si);
1531                 free(my_addr);
1532                 close(fd);
1533                 return ret;
1534         }
1535
1536         child_si->myname_len = len;
1537         child_si->myname = sockaddr_dup(my_addr, len);
1538         free(my_addr);
1539
1540         SWRAP_DLIST_ADD(sockets, child_si);
1541
1542         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1543         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1544         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1545
1546         return fd;
1547 }
1548
1549 static int autobind_start_init;
1550 static int autobind_start;
1551
1552 /* using sendto() or connect() on an unbound socket would give the
1553    recipient no way to reply, as unlike UDP and TCP, a unix domain
1554    socket can't auto-assign emphemeral port numbers, so we need to
1555    assign it here.
1556    Note: this might change the family from ipv6 to ipv4
1557 */
1558 static int swrap_auto_bind(struct socket_info *si, int family)
1559 {
1560         struct sockaddr_un un_addr;
1561         int i;
1562         char type;
1563         int ret;
1564         int port;
1565         struct stat st;
1566
1567         if (autobind_start_init != 1) {
1568                 autobind_start_init = 1;
1569                 autobind_start = getpid();
1570                 autobind_start %= 50000;
1571                 autobind_start += 10000;
1572         }
1573
1574         un_addr.sun_family = AF_UNIX;
1575
1576         switch (family) {
1577         case AF_INET: {
1578                 struct sockaddr_in in;
1579
1580                 switch (si->type) {
1581                 case SOCK_STREAM:
1582                         type = SOCKET_TYPE_CHAR_TCP;
1583                         break;
1584                 case SOCK_DGRAM:
1585                         type = SOCKET_TYPE_CHAR_UDP;
1586                         break;
1587                 default:
1588                     errno = ESOCKTNOSUPPORT;
1589                     return -1;
1590                 }
1591
1592                 memset(&in, 0, sizeof(in));
1593                 in.sin_family = AF_INET;
1594                 in.sin_addr.s_addr = htonl(127<<24 | 
1595                                            socket_wrapper_default_iface());
1596
1597                 si->myname_len = sizeof(in);
1598                 si->myname = sockaddr_dup(&in, si->myname_len);
1599                 break;
1600         }
1601 #ifdef HAVE_IPV6
1602         case AF_INET6: {
1603                 struct sockaddr_in6 in6;
1604
1605                 if (si->family != family) {
1606                         errno = ENETUNREACH;
1607                         return -1;
1608                 }
1609
1610                 switch (si->type) {
1611                 case SOCK_STREAM:
1612                         type = SOCKET_TYPE_CHAR_TCP_V6;
1613                         break;
1614                 case SOCK_DGRAM:
1615                         type = SOCKET_TYPE_CHAR_UDP_V6;
1616                         break;
1617                 default:
1618                         errno = ESOCKTNOSUPPORT;
1619                         return -1;
1620                 }
1621
1622                 memset(&in6, 0, sizeof(in6));
1623                 in6.sin6_family = AF_INET6;
1624                 in6.sin6_addr = *swrap_ipv6();
1625                 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1626                 si->myname_len = sizeof(in6);
1627                 si->myname = sockaddr_dup(&in6, si->myname_len);
1628                 break;
1629         }
1630 #endif
1631         default:
1632                 errno = ESOCKTNOSUPPORT;
1633                 return -1;
1634         }
1635
1636         if (autobind_start > 60000) {
1637                 autobind_start = 10000;
1638         }
1639
1640         for (i=0;i<1000;i++) {
1641                 port = autobind_start + i;
1642                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
1643                          "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1644                          type, socket_wrapper_default_iface(), port);
1645                 if (stat(un_addr.sun_path, &st) == 0) continue;
1646                 
1647                 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1648                 if (ret == -1) return ret;
1649
1650                 si->tmp_path = strdup(un_addr.sun_path);
1651                 si->bound = 1;
1652                 autobind_start = port + 1;
1653                 break;
1654         }
1655         if (i == 1000) {
1656                 errno = ENFILE;
1657                 return -1;
1658         }
1659
1660         si->family = family;
1661         set_port(si->family, port, si->myname);
1662
1663         return 0;
1664 }
1665
1666
1667 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1668 {
1669         int ret;
1670         struct sockaddr_un un_addr;
1671         struct socket_info *si = find_socket_info(s);
1672
1673         if (!si) {
1674                 return real_connect(s, serv_addr, addrlen);
1675         }
1676
1677         if (si->bound == 0) {
1678                 ret = swrap_auto_bind(si, serv_addr->sa_family);
1679                 if (ret == -1) return -1;
1680         }
1681
1682         if (si->family != serv_addr->sa_family) {
1683                 errno = EINVAL;
1684                 return -1;
1685         }
1686
1687         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1688         if (ret == -1) return -1;
1689
1690         if (si->type == SOCK_DGRAM) {
1691                 si->defer_connect = 1;
1692                 ret = 0;
1693         } else {
1694                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1695
1696                 ret = real_connect(s, (struct sockaddr *)&un_addr,
1697                                    sizeof(struct sockaddr_un));
1698         }
1699
1700         /* to give better errors */
1701         if (ret == -1 && errno == ENOENT) {
1702                 errno = EHOSTUNREACH;
1703         }
1704
1705         if (ret == 0) {
1706                 si->peername_len = addrlen;
1707                 si->peername = sockaddr_dup(serv_addr, addrlen);
1708                 si->connected = 1;
1709
1710                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1711                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1712         } else {
1713                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1714         }
1715
1716         return ret;
1717 }
1718
1719 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1720 {
1721         int ret;
1722         struct sockaddr_un un_addr;
1723         struct socket_info *si = find_socket_info(s);
1724
1725         if (!si) {
1726                 return real_bind(s, myaddr, addrlen);
1727         }
1728
1729         si->myname_len = addrlen;
1730         si->myname = sockaddr_dup(myaddr, addrlen);
1731
1732         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1733         if (ret == -1) return -1;
1734
1735         unlink(un_addr.sun_path);
1736
1737         ret = real_bind(s, (struct sockaddr *)&un_addr,
1738                         sizeof(struct sockaddr_un));
1739
1740         if (ret == 0) {
1741                 si->bound = 1;
1742         }
1743
1744         return ret;
1745 }
1746
1747 _PUBLIC_ int swrap_listen(int s, int backlog)
1748 {
1749         int ret;
1750         struct socket_info *si = find_socket_info(s);
1751
1752         if (!si) {
1753                 return real_listen(s, backlog);
1754         }
1755
1756         ret = real_listen(s, backlog);
1757
1758         return ret;
1759 }
1760
1761 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1762 {
1763         struct socket_info *si = find_socket_info(s);
1764
1765         if (!si) {
1766                 return real_getpeername(s, name, addrlen);
1767         }
1768
1769         if (!si->peername)
1770         {
1771                 errno = ENOTCONN;
1772                 return -1;
1773         }
1774
1775         memcpy(name, si->peername, si->peername_len);
1776         *addrlen = si->peername_len;
1777
1778         return 0;
1779 }
1780
1781 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1782 {
1783         struct socket_info *si = find_socket_info(s);
1784
1785         if (!si) {
1786                 return real_getsockname(s, name, addrlen);
1787         }
1788
1789         memcpy(name, si->myname, si->myname_len);
1790         *addrlen = si->myname_len;
1791
1792         return 0;
1793 }
1794
1795 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1796 {
1797         struct socket_info *si = find_socket_info(s);
1798
1799         if (!si) {
1800                 return real_getsockopt(s, level, optname, optval, optlen);
1801         }
1802
1803         if (level == SOL_SOCKET) {
1804                 return real_getsockopt(s, level, optname, optval, optlen);
1805         } 
1806
1807         errno = ENOPROTOOPT;
1808         return -1;
1809 }
1810
1811 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
1812 {
1813         struct socket_info *si = find_socket_info(s);
1814
1815         if (!si) {
1816                 return real_setsockopt(s, level, optname, optval, optlen);
1817         }
1818
1819         if (level == SOL_SOCKET) {
1820                 return real_setsockopt(s, level, optname, optval, optlen);
1821         }
1822
1823         switch (si->family) {
1824         case AF_INET:
1825                 return 0;
1826         default:
1827                 errno = ENOPROTOOPT;
1828                 return -1;
1829         }
1830 }
1831
1832 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1833 {
1834         struct sockaddr_un un_addr;
1835         socklen_t un_addrlen = sizeof(un_addr);
1836         int ret;
1837         struct socket_info *si = find_socket_info(s);
1838         struct sockaddr_storage ss;
1839         socklen_t ss_len = sizeof(ss);
1840
1841         if (!si) {
1842                 return real_recvfrom(s, buf, len, flags, from, fromlen);
1843         }
1844
1845         if (!from) {
1846                 from = (struct sockaddr *)&ss;
1847                 fromlen = &ss_len;
1848         }
1849
1850         len = MIN(len, 1500);
1851
1852         /* irix 6.4 forgets to null terminate the sun_path string :-( */
1853         memset(&un_addr, 0, sizeof(un_addr));
1854         ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1855         if (ret == -1) 
1856                 return ret;
1857
1858         if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1859                                      si->family, from, fromlen) == -1) {
1860                 return -1;
1861         }
1862
1863         swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1864
1865         return ret;
1866 }
1867
1868
1869 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1870 {
1871         struct sockaddr_un un_addr;
1872         int ret;
1873         struct socket_info *si = find_socket_info(s);
1874         int bcast = 0;
1875
1876         if (!si) {
1877                 return real_sendto(s, buf, len, flags, to, tolen);
1878         }
1879
1880         if (si->connected) {
1881                 if (to) {
1882                         errno = EISCONN;
1883                         return -1;
1884                 }
1885
1886                 to = si->peername;
1887                 tolen = si->peername_len;
1888         }
1889
1890         len = MIN(len, 1500);
1891
1892         switch (si->type) {
1893         case SOCK_STREAM:
1894                 ret = real_send(s, buf, len, flags);
1895                 break;
1896         case SOCK_DGRAM:
1897                 if (si->bound == 0) {
1898                         ret = swrap_auto_bind(si, si->family);
1899                         if (ret == -1) return -1;
1900                 }
1901                 
1902                 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1903                 if (ret == -1) return -1;
1904                 
1905                 if (bcast) {
1906                         struct stat st;
1907                         unsigned int iface;
1908                         unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1909                         char type;
1910                         
1911                         type = SOCKET_TYPE_CHAR_UDP;
1912                         
1913                         for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1914                                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
1915                                          socket_wrapper_dir(), type, iface, prt);
1916                                 if (stat(un_addr.sun_path, &st) != 0) continue;
1917                                 
1918                                 /* ignore the any errors in broadcast sends */
1919                                 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1920                         }
1921                         
1922                         swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1923                         
1924                         return len;
1925                 }
1926
1927                 if (si->defer_connect) {
1928                         ret = real_connect(s, (struct sockaddr *)&un_addr,
1929                                            sizeof(un_addr));
1930
1931                         /* to give better errors */
1932                         if (ret == -1 && errno == ENOENT) {
1933                                 errno = EHOSTUNREACH;
1934                         }
1935
1936                         if (ret == -1) {
1937                                 return ret;
1938                         }
1939                         si->defer_connect = 0;
1940                 }
1941
1942                 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1943                 break;
1944         default:
1945                 ret = -1;
1946                 errno = EHOSTUNREACH;
1947                 break;
1948         }
1949                 
1950         /* to give better errors */
1951         if (ret == -1 && errno == ENOENT) {
1952                 errno = EHOSTUNREACH;
1953         }
1954
1955         if (ret == -1) {
1956                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1957                 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1958         } else {
1959                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1960         }
1961
1962         return ret;
1963 }
1964
1965 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1966 {
1967         int ret;
1968         struct socket_info *si = find_socket_info(s);
1969         int value;
1970
1971         if (!si) {
1972                 return real_ioctl(s, r, p);
1973         }
1974
1975         ret = real_ioctl(s, r, p);
1976
1977         switch (r) {
1978         case FIONREAD:
1979                 value = *((int *)p);
1980                 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1981                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1982                 } else if (value == 0) { /* END OF FILE */
1983                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1984                 }
1985                 break;
1986         }
1987
1988         return ret;
1989 }
1990
1991 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1992 {
1993         int ret;
1994         struct socket_info *si = find_socket_info(s);
1995
1996         if (!si) {
1997                 return real_recv(s, buf, len, flags);
1998         }
1999
2000         len = MIN(len, 1500);
2001
2002         ret = real_recv(s, buf, len, flags);
2003         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2004                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2005         } else if (ret == 0) { /* END OF FILE */
2006                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2007         } else if (ret > 0) {
2008                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2009         }
2010
2011         return ret;
2012 }
2013
2014
2015 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2016 {
2017         int ret;
2018         struct socket_info *si = find_socket_info(s);
2019
2020         if (!si) {
2021                 return real_send(s, buf, len, flags);
2022         }
2023
2024         len = MIN(len, 1500);
2025
2026         if (si->defer_connect) {
2027                 struct sockaddr_un un_addr;
2028                 int bcast = 0;
2029
2030                 if (si->bound == 0) {
2031                         ret = swrap_auto_bind(si, si->family);
2032                         if (ret == -1) return -1;
2033                 }
2034
2035                 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2036                                              &un_addr, 0, &bcast);
2037                 if (ret == -1) return -1;
2038
2039                 ret = real_connect(s, (struct sockaddr *)&un_addr,
2040                                    sizeof(un_addr));
2041
2042                 /* to give better errors */
2043                 if (ret == -1 && errno == ENOENT) {
2044                         errno = EHOSTUNREACH;
2045                 }
2046
2047                 if (ret == -1) {
2048                         return ret;
2049                 }
2050                 si->defer_connect = 0;
2051         }
2052
2053         ret = real_send(s, buf, len, flags);
2054
2055         if (ret == -1) {
2056                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2057                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2058         } else {
2059                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2060         }
2061
2062         return ret;
2063 }
2064
2065 int swrap_readv(int s, const struct iovec *vector, size_t count)
2066 {
2067         int ret;
2068         struct socket_info *si = find_socket_info(s);
2069         struct iovec v;
2070
2071         if (!si) {
2072                 return real_readv(s, vector, count);
2073         }
2074
2075         /* we read 1500 bytes as maximum */
2076         if (count > 0) {
2077                 size_t i, len = 0;
2078
2079                 for (i=0; i < count; i++) {
2080                         size_t nlen;
2081                         nlen = len + vector[i].iov_len;
2082                         if (nlen > 1500) {
2083                                 break;
2084                         }
2085                 }
2086                 count = i;
2087                 if (count == 0) {
2088                         v = vector[0];
2089                         v.iov_len = MIN(v.iov_len, 1500);
2090                         vector = &v;
2091                         count = 1;
2092                 }
2093         }
2094
2095         ret = real_readv(s, vector, count);
2096         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2097                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2098         } else if (ret == 0) { /* END OF FILE */
2099                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2100         } else if (ret > 0) {
2101                 uint8_t *buf;
2102                 off_t ofs = 0;
2103                 size_t i;
2104
2105                 /* we capture it as one single packet */
2106                 buf = (uint8_t *)malloc(ret);
2107                 if (!buf) {
2108                         /* we just not capture the packet */
2109                         errno = 0;
2110                         return ret;
2111                 }
2112
2113                 for (i=0; i < count; i++) {
2114                         memcpy(buf + ofs,
2115                                vector[i].iov_base,
2116                                vector[i].iov_len);
2117                         ofs += vector[i].iov_len;
2118                 }
2119
2120                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2121                 free(buf);
2122         }
2123
2124         return ret;
2125 }
2126
2127 int swrap_writev(int s, const struct iovec *vector, size_t count)
2128 {
2129         int ret;
2130         struct socket_info *si = find_socket_info(s);
2131         struct iovec v;
2132
2133         if (!si) {
2134                 return real_writev(s, vector, count);
2135         }
2136
2137         /* we write 1500 bytes as maximum */
2138         if (count > 0) {
2139                 size_t i, len = 0;
2140
2141                 for (i=0; i < count; i++) {
2142                         size_t nlen;
2143                         nlen = len + vector[i].iov_len;
2144                         if (nlen > 1500) {
2145                                 break;
2146                         }
2147                 }
2148                 count = i;
2149                 if (count == 0) {
2150                         v = vector[0];
2151                         v.iov_len = MIN(v.iov_len, 1500);
2152                         vector = &v;
2153                         count = 1;
2154                 }
2155         }
2156
2157         ret = real_writev(s, vector, count);
2158         if (ret == -1) {
2159                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2160         } else {
2161                 uint8_t *buf;
2162                 off_t ofs = 0;
2163                 size_t i;
2164
2165                 /* we capture it as one single packet */
2166                 buf = (uint8_t *)malloc(ret);
2167                 if (!buf) {
2168                         /* we just not capture the packet */
2169                         errno = 0;
2170                         return ret;
2171                 }
2172
2173                 for (i=0; i < count; i++) {
2174                         memcpy(buf + ofs,
2175                                vector[i].iov_base,
2176                                vector[i].iov_len);
2177                         ofs += vector[i].iov_len;
2178                 }
2179
2180                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2181                 free(buf);
2182         }
2183
2184         return ret;
2185 }
2186
2187 _PUBLIC_ int swrap_close(int fd)
2188 {
2189         struct socket_info *si = find_socket_info(fd);
2190         int ret;
2191
2192         if (!si) {
2193                 return real_close(fd);
2194         }
2195
2196         SWRAP_DLIST_REMOVE(sockets, si);
2197
2198         if (si->myname && si->peername) {
2199                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2200         }
2201
2202         ret = real_close(fd);
2203
2204         if (si->myname && si->peername) {
2205                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2206                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2207         }
2208
2209         if (si->path) free(si->path);
2210         if (si->myname) free(si->myname);
2211         if (si->peername) free(si->peername);
2212         if (si->tmp_path) {
2213                 unlink(si->tmp_path);
2214                 free(si->tmp_path);
2215         }
2216         free(si);
2217
2218         return ret;
2219 }