Merge branch 'master' of ssh://git.samba.org/data/git/samba into libcli-auth-merge...
[sfrench/samba-autobuild/.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 #ifdef HAVE_IPV6
1106         case AF_INET6:
1107                 break;
1108 #endif
1109         default:
1110                 return NULL;
1111         }
1112
1113         switch (type) {
1114         case SWRAP_CONNECT_SEND:
1115                 if (si->type != SOCK_STREAM) return NULL;
1116
1117                 src_addr = si->myname;
1118                 dest_addr = addr;
1119
1120                 tcp_seqno = si->io.pck_snd;
1121                 tcp_ack = si->io.pck_rcv;
1122                 tcp_ctl = 0x02; /* SYN */
1123
1124                 si->io.pck_snd += 1;
1125
1126                 break;
1127
1128         case SWRAP_CONNECT_RECV:
1129                 if (si->type != SOCK_STREAM) return NULL;
1130
1131                 dest_addr = si->myname;
1132                 src_addr = addr;
1133
1134                 tcp_seqno = si->io.pck_rcv;
1135                 tcp_ack = si->io.pck_snd;
1136                 tcp_ctl = 0x12; /** SYN,ACK */
1137
1138                 si->io.pck_rcv += 1;
1139
1140                 break;
1141
1142         case SWRAP_CONNECT_UNREACH:
1143                 if (si->type != SOCK_STREAM) return NULL;
1144
1145                 dest_addr = si->myname;
1146                 src_addr = addr;
1147
1148                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1149                 tcp_seqno = si->io.pck_snd - 1;
1150                 tcp_ack = si->io.pck_rcv;
1151                 tcp_ctl = 0x02; /* SYN */
1152                 unreachable = 1;
1153
1154                 break;
1155
1156         case SWRAP_CONNECT_ACK:
1157                 if (si->type != SOCK_STREAM) return NULL;
1158
1159                 src_addr = si->myname;
1160                 dest_addr = addr;
1161
1162                 tcp_seqno = si->io.pck_snd;
1163                 tcp_ack = si->io.pck_rcv;
1164                 tcp_ctl = 0x10; /* ACK */
1165
1166                 break;
1167
1168         case SWRAP_ACCEPT_SEND:
1169                 if (si->type != SOCK_STREAM) return NULL;
1170
1171                 dest_addr = si->myname;
1172                 src_addr = addr;
1173
1174                 tcp_seqno = si->io.pck_rcv;
1175                 tcp_ack = si->io.pck_snd;
1176                 tcp_ctl = 0x02; /* SYN */
1177
1178                 si->io.pck_rcv += 1;
1179
1180                 break;
1181
1182         case SWRAP_ACCEPT_RECV:
1183                 if (si->type != SOCK_STREAM) return NULL;
1184
1185                 src_addr = si->myname;
1186                 dest_addr = addr;
1187
1188                 tcp_seqno = si->io.pck_snd;
1189                 tcp_ack = si->io.pck_rcv;
1190                 tcp_ctl = 0x12; /* SYN,ACK */
1191
1192                 si->io.pck_snd += 1;
1193
1194                 break;
1195
1196         case SWRAP_ACCEPT_ACK:
1197                 if (si->type != SOCK_STREAM) return NULL;
1198
1199                 dest_addr = si->myname;
1200                 src_addr = addr;
1201
1202                 tcp_seqno = si->io.pck_rcv;
1203                 tcp_ack = si->io.pck_snd;
1204                 tcp_ctl = 0x10; /* ACK */
1205
1206                 break;
1207
1208         case SWRAP_SEND:
1209                 src_addr = si->myname;
1210                 dest_addr = si->peername;
1211
1212                 tcp_seqno = si->io.pck_snd;
1213                 tcp_ack = si->io.pck_rcv;
1214                 tcp_ctl = 0x18; /* PSH,ACK */
1215
1216                 si->io.pck_snd += len;
1217
1218                 break;
1219
1220         case SWRAP_SEND_RST:
1221                 dest_addr = si->myname;
1222                 src_addr = si->peername;
1223
1224                 if (si->type == SOCK_DGRAM) {
1225                         return swrap_marshall_packet(si, si->peername,
1226                                           SWRAP_SENDTO_UNREACH,
1227                                           buf, len, packet_len);
1228                 }
1229
1230                 tcp_seqno = si->io.pck_rcv;
1231                 tcp_ack = si->io.pck_snd;
1232                 tcp_ctl = 0x14; /** RST,ACK */
1233
1234                 break;
1235
1236         case SWRAP_PENDING_RST:
1237                 dest_addr = si->myname;
1238                 src_addr = si->peername;
1239
1240                 if (si->type == SOCK_DGRAM) {
1241                         return NULL;
1242                 }
1243
1244                 tcp_seqno = si->io.pck_rcv;
1245                 tcp_ack = si->io.pck_snd;
1246                 tcp_ctl = 0x14; /* RST,ACK */
1247
1248                 break;
1249
1250         case SWRAP_RECV:
1251                 dest_addr = si->myname;
1252                 src_addr = si->peername;
1253
1254                 tcp_seqno = si->io.pck_rcv;
1255                 tcp_ack = si->io.pck_snd;
1256                 tcp_ctl = 0x18; /* PSH,ACK */
1257
1258                 si->io.pck_rcv += len;
1259
1260                 break;
1261
1262         case SWRAP_RECV_RST:
1263                 dest_addr = si->myname;
1264                 src_addr = si->peername;
1265
1266                 if (si->type == SOCK_DGRAM) {
1267                         return NULL;
1268                 }
1269
1270                 tcp_seqno = si->io.pck_rcv;
1271                 tcp_ack = si->io.pck_snd;
1272                 tcp_ctl = 0x14; /* RST,ACK */
1273
1274                 break;
1275
1276         case SWRAP_SENDTO:
1277                 src_addr = si->myname;
1278                 dest_addr = addr;
1279
1280                 si->io.pck_snd += len;
1281
1282                 break;
1283
1284         case SWRAP_SENDTO_UNREACH:
1285                 dest_addr = si->myname;
1286                 src_addr = addr;
1287
1288                 unreachable = 1;
1289
1290                 break;
1291
1292         case SWRAP_RECVFROM:
1293                 dest_addr = si->myname;
1294                 src_addr = addr;
1295
1296                 si->io.pck_rcv += len;
1297
1298                 break;
1299
1300         case SWRAP_CLOSE_SEND:
1301                 if (si->type != SOCK_STREAM) return NULL;
1302
1303                 src_addr = si->myname;
1304                 dest_addr = si->peername;
1305
1306                 tcp_seqno = si->io.pck_snd;
1307                 tcp_ack = si->io.pck_rcv;
1308                 tcp_ctl = 0x11; /* FIN, ACK */
1309
1310                 si->io.pck_snd += 1;
1311
1312                 break;
1313
1314         case SWRAP_CLOSE_RECV:
1315                 if (si->type != SOCK_STREAM) return NULL;
1316
1317                 dest_addr = si->myname;
1318                 src_addr = si->peername;
1319
1320                 tcp_seqno = si->io.pck_rcv;
1321                 tcp_ack = si->io.pck_snd;
1322                 tcp_ctl = 0x11; /* FIN,ACK */
1323
1324                 si->io.pck_rcv += 1;
1325
1326                 break;
1327
1328         case SWRAP_CLOSE_ACK:
1329                 if (si->type != SOCK_STREAM) return NULL;
1330
1331                 src_addr = si->myname;
1332                 dest_addr = si->peername;
1333
1334                 tcp_seqno = si->io.pck_snd;
1335                 tcp_ack = si->io.pck_rcv;
1336                 tcp_ctl = 0x10; /* ACK */
1337
1338                 break;
1339         default:
1340                 return NULL;
1341         }
1342
1343         swrapGetTimeOfDay(&tv);
1344
1345         return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1346                                  (const uint8_t *)buf, len,
1347                                  tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1348                                  packet_len);
1349 }
1350
1351 static void swrap_dump_packet(struct socket_info *si,
1352                               const struct sockaddr *addr,
1353                               enum swrap_packet_type type,
1354                               const void *buf, size_t len)
1355 {
1356         const char *file_name;
1357         uint8_t *packet;
1358         size_t packet_len = 0;
1359         int fd;
1360
1361         file_name = socket_wrapper_pcap_file();
1362         if (!file_name) {
1363                 return;
1364         }
1365
1366         packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1367         if (!packet) {
1368                 return;
1369         }
1370
1371         fd = swrap_get_pcap_fd(file_name);
1372         if (fd != -1) {
1373                 if (write(fd, packet, packet_len) != packet_len) {
1374                         free(packet);
1375                         return;
1376                 }
1377         }
1378
1379         free(packet);
1380 }
1381
1382 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1383 {
1384         struct socket_info *si;
1385         int fd;
1386
1387         if (!socket_wrapper_dir()) {
1388                 return real_socket(family, type, protocol);
1389         }
1390
1391         switch (family) {
1392         case AF_INET:
1393 #ifdef HAVE_IPV6
1394         case AF_INET6:
1395 #endif
1396                 break;
1397         case AF_UNIX:
1398                 return real_socket(family, type, protocol);
1399         default:
1400                 errno = EAFNOSUPPORT;
1401                 return -1;
1402         }
1403
1404         switch (type) {
1405         case SOCK_STREAM:
1406                 break;
1407         case SOCK_DGRAM:
1408                 break;
1409         default:
1410                 errno = EPROTONOSUPPORT;
1411                 return -1;
1412         }
1413
1414         switch (protocol) {
1415         case 0:
1416                 break;
1417         case 6:
1418                 if (type == SOCK_STREAM) {
1419                         break;
1420                 }
1421                 /*fall through*/
1422         case 17:
1423                 if (type == SOCK_DGRAM) {
1424                         break;
1425                 }
1426                 /*fall through*/
1427         default:
1428                 errno = EPROTONOSUPPORT;
1429                 return -1;
1430         }
1431
1432         fd = real_socket(AF_UNIX, type, 0);
1433
1434         if (fd == -1) return -1;
1435
1436         si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1437
1438         si->family = family;
1439         si->type = type;
1440         si->protocol = protocol;
1441         si->fd = fd;
1442
1443         SWRAP_DLIST_ADD(sockets, si);
1444
1445         return si->fd;
1446 }
1447
1448 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1449 {
1450         struct socket_info *parent_si, *child_si;
1451         int fd;
1452         struct sockaddr_un un_addr;
1453         socklen_t un_addrlen = sizeof(un_addr);
1454         struct sockaddr_un un_my_addr;
1455         socklen_t un_my_addrlen = sizeof(un_my_addr);
1456         struct sockaddr *my_addr;
1457         socklen_t my_addrlen, len;
1458         int ret;
1459
1460         parent_si = find_socket_info(s);
1461         if (!parent_si) {
1462                 return real_accept(s, addr, addrlen);
1463         }
1464
1465         /* 
1466          * assume out sockaddr have the same size as the in parent
1467          * socket family
1468          */
1469         my_addrlen = socket_length(parent_si->family);
1470         if (my_addrlen <= 0) {
1471                 errno = EINVAL;
1472                 return -1;
1473         }
1474
1475         my_addr = (struct sockaddr *)malloc(my_addrlen);
1476         if (my_addr == NULL) {
1477                 return -1;
1478         }
1479
1480         memset(&un_addr, 0, sizeof(un_addr));
1481         memset(&un_my_addr, 0, sizeof(un_my_addr));
1482
1483         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1484         if (ret == -1) {
1485                 free(my_addr);
1486                 return ret;
1487         }
1488
1489         fd = ret;
1490
1491         len = my_addrlen;
1492         ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1493                                        parent_si->family, my_addr, &len);
1494         if (ret == -1) {
1495                 free(my_addr);
1496                 close(fd);
1497                 return ret;
1498         }
1499
1500         child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1501         memset(child_si, 0, sizeof(*child_si));
1502
1503         child_si->fd = fd;
1504         child_si->family = parent_si->family;
1505         child_si->type = parent_si->type;
1506         child_si->protocol = parent_si->protocol;
1507         child_si->bound = 1;
1508         child_si->is_server = 1;
1509         child_si->connected = 1;
1510
1511         child_si->peername_len = len;
1512         child_si->peername = sockaddr_dup(my_addr, len);
1513
1514         if (addr != NULL && addrlen != NULL) {
1515             *addrlen = len;
1516             if (*addrlen >= len)
1517                 memcpy(addr, my_addr, len);
1518             *addrlen = 0;
1519         }
1520
1521         ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1522         if (ret == -1) {
1523                 free(child_si);
1524                 close(fd);
1525                 return ret;
1526         }
1527
1528         len = my_addrlen;
1529         ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1530                                        child_si->family, my_addr, &len);
1531         if (ret == -1) {
1532                 free(child_si);
1533                 free(my_addr);
1534                 close(fd);
1535                 return ret;
1536         }
1537
1538         child_si->myname_len = len;
1539         child_si->myname = sockaddr_dup(my_addr, len);
1540         free(my_addr);
1541
1542         SWRAP_DLIST_ADD(sockets, child_si);
1543
1544         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1545         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1546         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1547
1548         return fd;
1549 }
1550
1551 static int autobind_start_init;
1552 static int autobind_start;
1553
1554 /* using sendto() or connect() on an unbound socket would give the
1555    recipient no way to reply, as unlike UDP and TCP, a unix domain
1556    socket can't auto-assign emphemeral port numbers, so we need to
1557    assign it here.
1558    Note: this might change the family from ipv6 to ipv4
1559 */
1560 static int swrap_auto_bind(struct socket_info *si, int family)
1561 {
1562         struct sockaddr_un un_addr;
1563         int i;
1564         char type;
1565         int ret;
1566         int port;
1567         struct stat st;
1568
1569         if (autobind_start_init != 1) {
1570                 autobind_start_init = 1;
1571                 autobind_start = getpid();
1572                 autobind_start %= 50000;
1573                 autobind_start += 10000;
1574         }
1575
1576         un_addr.sun_family = AF_UNIX;
1577
1578         switch (family) {
1579         case AF_INET: {
1580                 struct sockaddr_in in;
1581
1582                 switch (si->type) {
1583                 case SOCK_STREAM:
1584                         type = SOCKET_TYPE_CHAR_TCP;
1585                         break;
1586                 case SOCK_DGRAM:
1587                         type = SOCKET_TYPE_CHAR_UDP;
1588                         break;
1589                 default:
1590                     errno = ESOCKTNOSUPPORT;
1591                     return -1;
1592                 }
1593
1594                 memset(&in, 0, sizeof(in));
1595                 in.sin_family = AF_INET;
1596                 in.sin_addr.s_addr = htonl(127<<24 | 
1597                                            socket_wrapper_default_iface());
1598
1599                 si->myname_len = sizeof(in);
1600                 si->myname = sockaddr_dup(&in, si->myname_len);
1601                 break;
1602         }
1603 #ifdef HAVE_IPV6
1604         case AF_INET6: {
1605                 struct sockaddr_in6 in6;
1606
1607                 if (si->family != family) {
1608                         errno = ENETUNREACH;
1609                         return -1;
1610                 }
1611
1612                 switch (si->type) {
1613                 case SOCK_STREAM:
1614                         type = SOCKET_TYPE_CHAR_TCP_V6;
1615                         break;
1616                 case SOCK_DGRAM:
1617                         type = SOCKET_TYPE_CHAR_UDP_V6;
1618                         break;
1619                 default:
1620                         errno = ESOCKTNOSUPPORT;
1621                         return -1;
1622                 }
1623
1624                 memset(&in6, 0, sizeof(in6));
1625                 in6.sin6_family = AF_INET6;
1626                 in6.sin6_addr = *swrap_ipv6();
1627                 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1628                 si->myname_len = sizeof(in6);
1629                 si->myname = sockaddr_dup(&in6, si->myname_len);
1630                 break;
1631         }
1632 #endif
1633         default:
1634                 errno = ESOCKTNOSUPPORT;
1635                 return -1;
1636         }
1637
1638         if (autobind_start > 60000) {
1639                 autobind_start = 10000;
1640         }
1641
1642         for (i=0;i<1000;i++) {
1643                 port = autobind_start + i;
1644                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
1645                          "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1646                          type, socket_wrapper_default_iface(), port);
1647                 if (stat(un_addr.sun_path, &st) == 0) continue;
1648                 
1649                 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1650                 if (ret == -1) return ret;
1651
1652                 si->tmp_path = strdup(un_addr.sun_path);
1653                 si->bound = 1;
1654                 autobind_start = port + 1;
1655                 break;
1656         }
1657         if (i == 1000) {
1658                 errno = ENFILE;
1659                 return -1;
1660         }
1661
1662         si->family = family;
1663         set_port(si->family, port, si->myname);
1664
1665         return 0;
1666 }
1667
1668
1669 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1670 {
1671         int ret;
1672         struct sockaddr_un un_addr;
1673         struct socket_info *si = find_socket_info(s);
1674
1675         if (!si) {
1676                 return real_connect(s, serv_addr, addrlen);
1677         }
1678
1679         if (si->bound == 0) {
1680                 ret = swrap_auto_bind(si, serv_addr->sa_family);
1681                 if (ret == -1) return -1;
1682         }
1683
1684         if (si->family != serv_addr->sa_family) {
1685                 errno = EINVAL;
1686                 return -1;
1687         }
1688
1689         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1690         if (ret == -1) return -1;
1691
1692         if (si->type == SOCK_DGRAM) {
1693                 si->defer_connect = 1;
1694                 ret = 0;
1695         } else {
1696                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1697
1698                 ret = real_connect(s, (struct sockaddr *)&un_addr,
1699                                    sizeof(struct sockaddr_un));
1700         }
1701
1702         /* to give better errors */
1703         if (ret == -1 && errno == ENOENT) {
1704                 errno = EHOSTUNREACH;
1705         }
1706
1707         if (ret == 0) {
1708                 si->peername_len = addrlen;
1709                 si->peername = sockaddr_dup(serv_addr, addrlen);
1710                 si->connected = 1;
1711
1712                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1713                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1714         } else {
1715                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1716         }
1717
1718         return ret;
1719 }
1720
1721 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1722 {
1723         int ret;
1724         struct sockaddr_un un_addr;
1725         struct socket_info *si = find_socket_info(s);
1726
1727         if (!si) {
1728                 return real_bind(s, myaddr, addrlen);
1729         }
1730
1731         si->myname_len = addrlen;
1732         si->myname = sockaddr_dup(myaddr, addrlen);
1733
1734         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1735         if (ret == -1) return -1;
1736
1737         unlink(un_addr.sun_path);
1738
1739         ret = real_bind(s, (struct sockaddr *)&un_addr,
1740                         sizeof(struct sockaddr_un));
1741
1742         if (ret == 0) {
1743                 si->bound = 1;
1744         }
1745
1746         return ret;
1747 }
1748
1749 _PUBLIC_ int swrap_listen(int s, int backlog)
1750 {
1751         int ret;
1752         struct socket_info *si = find_socket_info(s);
1753
1754         if (!si) {
1755                 return real_listen(s, backlog);
1756         }
1757
1758         ret = real_listen(s, backlog);
1759
1760         return ret;
1761 }
1762
1763 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1764 {
1765         struct socket_info *si = find_socket_info(s);
1766
1767         if (!si) {
1768                 return real_getpeername(s, name, addrlen);
1769         }
1770
1771         if (!si->peername)
1772         {
1773                 errno = ENOTCONN;
1774                 return -1;
1775         }
1776
1777         memcpy(name, si->peername, si->peername_len);
1778         *addrlen = si->peername_len;
1779
1780         return 0;
1781 }
1782
1783 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1784 {
1785         struct socket_info *si = find_socket_info(s);
1786
1787         if (!si) {
1788                 return real_getsockname(s, name, addrlen);
1789         }
1790
1791         memcpy(name, si->myname, si->myname_len);
1792         *addrlen = si->myname_len;
1793
1794         return 0;
1795 }
1796
1797 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1798 {
1799         struct socket_info *si = find_socket_info(s);
1800
1801         if (!si) {
1802                 return real_getsockopt(s, level, optname, optval, optlen);
1803         }
1804
1805         if (level == SOL_SOCKET) {
1806                 return real_getsockopt(s, level, optname, optval, optlen);
1807         } 
1808
1809         errno = ENOPROTOOPT;
1810         return -1;
1811 }
1812
1813 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
1814 {
1815         struct socket_info *si = find_socket_info(s);
1816
1817         if (!si) {
1818                 return real_setsockopt(s, level, optname, optval, optlen);
1819         }
1820
1821         if (level == SOL_SOCKET) {
1822                 return real_setsockopt(s, level, optname, optval, optlen);
1823         }
1824
1825         switch (si->family) {
1826         case AF_INET:
1827                 return 0;
1828         default:
1829                 errno = ENOPROTOOPT;
1830                 return -1;
1831         }
1832 }
1833
1834 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1835 {
1836         struct sockaddr_un un_addr;
1837         socklen_t un_addrlen = sizeof(un_addr);
1838         int ret;
1839         struct socket_info *si = find_socket_info(s);
1840         struct sockaddr_storage ss;
1841         socklen_t ss_len = sizeof(ss);
1842
1843         if (!si) {
1844                 return real_recvfrom(s, buf, len, flags, from, fromlen);
1845         }
1846
1847         if (!from) {
1848                 from = (struct sockaddr *)&ss;
1849                 fromlen = &ss_len;
1850         }
1851
1852         len = MIN(len, 1500);
1853
1854         /* irix 6.4 forgets to null terminate the sun_path string :-( */
1855         memset(&un_addr, 0, sizeof(un_addr));
1856         ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1857         if (ret == -1) 
1858                 return ret;
1859
1860         if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1861                                      si->family, from, fromlen) == -1) {
1862                 return -1;
1863         }
1864
1865         swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1866
1867         return ret;
1868 }
1869
1870
1871 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1872 {
1873         struct sockaddr_un un_addr;
1874         int ret;
1875         struct socket_info *si = find_socket_info(s);
1876         int bcast = 0;
1877
1878         if (!si) {
1879                 return real_sendto(s, buf, len, flags, to, tolen);
1880         }
1881
1882         if (si->connected) {
1883                 if (to) {
1884                         errno = EISCONN;
1885                         return -1;
1886                 }
1887
1888                 to = si->peername;
1889                 tolen = si->peername_len;
1890         }
1891
1892         len = MIN(len, 1500);
1893
1894         switch (si->type) {
1895         case SOCK_STREAM:
1896                 ret = real_send(s, buf, len, flags);
1897                 break;
1898         case SOCK_DGRAM:
1899                 if (si->bound == 0) {
1900                         ret = swrap_auto_bind(si, si->family);
1901                         if (ret == -1) return -1;
1902                 }
1903                 
1904                 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1905                 if (ret == -1) return -1;
1906                 
1907                 if (bcast) {
1908                         struct stat st;
1909                         unsigned int iface;
1910                         unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1911                         char type;
1912                         
1913                         type = SOCKET_TYPE_CHAR_UDP;
1914                         
1915                         for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1916                                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
1917                                          socket_wrapper_dir(), type, iface, prt);
1918                                 if (stat(un_addr.sun_path, &st) != 0) continue;
1919                                 
1920                                 /* ignore the any errors in broadcast sends */
1921                                 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1922                         }
1923                         
1924                         swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1925                         
1926                         return len;
1927                 }
1928
1929                 if (si->defer_connect) {
1930                         ret = real_connect(s, (struct sockaddr *)&un_addr,
1931                                            sizeof(un_addr));
1932
1933                         /* to give better errors */
1934                         if (ret == -1 && errno == ENOENT) {
1935                                 errno = EHOSTUNREACH;
1936                         }
1937
1938                         if (ret == -1) {
1939                                 return ret;
1940                         }
1941                         si->defer_connect = 0;
1942                 }
1943
1944                 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1945                 break;
1946         default:
1947                 ret = -1;
1948                 errno = EHOSTUNREACH;
1949                 break;
1950         }
1951                 
1952         /* to give better errors */
1953         if (ret == -1 && errno == ENOENT) {
1954                 errno = EHOSTUNREACH;
1955         }
1956
1957         if (ret == -1) {
1958                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1959                 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1960         } else {
1961                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1962         }
1963
1964         return ret;
1965 }
1966
1967 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1968 {
1969         int ret;
1970         struct socket_info *si = find_socket_info(s);
1971         int value;
1972
1973         if (!si) {
1974                 return real_ioctl(s, r, p);
1975         }
1976
1977         ret = real_ioctl(s, r, p);
1978
1979         switch (r) {
1980         case FIONREAD:
1981                 value = *((int *)p);
1982                 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1983                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1984                 } else if (value == 0) { /* END OF FILE */
1985                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1986                 }
1987                 break;
1988         }
1989
1990         return ret;
1991 }
1992
1993 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1994 {
1995         int ret;
1996         struct socket_info *si = find_socket_info(s);
1997
1998         if (!si) {
1999                 return real_recv(s, buf, len, flags);
2000         }
2001
2002         len = MIN(len, 1500);
2003
2004         ret = real_recv(s, buf, len, flags);
2005         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2006                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2007         } else if (ret == 0) { /* END OF FILE */
2008                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2009         } else if (ret > 0) {
2010                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2011         }
2012
2013         return ret;
2014 }
2015
2016
2017 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
2018 {
2019         int ret;
2020         struct socket_info *si = find_socket_info(s);
2021
2022         if (!si) {
2023                 return real_send(s, buf, len, flags);
2024         }
2025
2026         len = MIN(len, 1500);
2027
2028         if (si->defer_connect) {
2029                 struct sockaddr_un un_addr;
2030                 int bcast = 0;
2031
2032                 if (si->bound == 0) {
2033                         ret = swrap_auto_bind(si, si->family);
2034                         if (ret == -1) return -1;
2035                 }
2036
2037                 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2038                                              &un_addr, 0, &bcast);
2039                 if (ret == -1) return -1;
2040
2041                 ret = real_connect(s, (struct sockaddr *)&un_addr,
2042                                    sizeof(un_addr));
2043
2044                 /* to give better errors */
2045                 if (ret == -1 && errno == ENOENT) {
2046                         errno = EHOSTUNREACH;
2047                 }
2048
2049                 if (ret == -1) {
2050                         return ret;
2051                 }
2052                 si->defer_connect = 0;
2053         }
2054
2055         ret = real_send(s, buf, len, flags);
2056
2057         if (ret == -1) {
2058                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2059                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2060         } else {
2061                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2062         }
2063
2064         return ret;
2065 }
2066
2067 int swrap_readv(int s, const struct iovec *vector, size_t count)
2068 {
2069         int ret;
2070         struct socket_info *si = find_socket_info(s);
2071         struct iovec v;
2072
2073         if (!si) {
2074                 return real_readv(s, vector, count);
2075         }
2076
2077         /* we read 1500 bytes as maximum */
2078         if (count > 0) {
2079                 size_t i, len = 0;
2080
2081                 for (i=0; i < count; i++) {
2082                         size_t nlen;
2083                         nlen = len + vector[i].iov_len;
2084                         if (nlen > 1500) {
2085                                 break;
2086                         }
2087                 }
2088                 count = i;
2089                 if (count == 0) {
2090                         v = vector[0];
2091                         v.iov_len = MIN(v.iov_len, 1500);
2092                         vector = &v;
2093                         count = 1;
2094                 }
2095         }
2096
2097         ret = real_readv(s, vector, count);
2098         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2099                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2100         } else if (ret == 0) { /* END OF FILE */
2101                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2102         } else if (ret > 0) {
2103                 uint8_t *buf;
2104                 off_t ofs = 0;
2105                 size_t i;
2106                 size_t remain = ret;
2107
2108                 /* we capture it as one single packet */
2109                 buf = (uint8_t *)malloc(ret);
2110                 if (!buf) {
2111                         /* we just not capture the packet */
2112                         errno = 0;
2113                         return ret;
2114                 }
2115
2116                 for (i=0; i < count; i++) {
2117                         size_t this_time = MIN(remain, vector[i].iov_len);
2118                         memcpy(buf + ofs,
2119                                vector[i].iov_base,
2120                                this_time);
2121                         ofs += this_time;
2122                         remain -= this_time;
2123                 }
2124
2125                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2126                 free(buf);
2127         }
2128
2129         return ret;
2130 }
2131
2132 int swrap_writev(int s, const struct iovec *vector, size_t count)
2133 {
2134         int ret;
2135         struct socket_info *si = find_socket_info(s);
2136         struct iovec v;
2137
2138         if (!si) {
2139                 return real_writev(s, vector, count);
2140         }
2141
2142         /* we write 1500 bytes as maximum */
2143         if (count > 0) {
2144                 size_t i, len = 0;
2145
2146                 for (i=0; i < count; i++) {
2147                         size_t nlen;
2148                         nlen = len + vector[i].iov_len;
2149                         if (nlen > 1500) {
2150                                 break;
2151                         }
2152                 }
2153                 count = i;
2154                 if (count == 0) {
2155                         v = vector[0];
2156                         v.iov_len = MIN(v.iov_len, 1500);
2157                         vector = &v;
2158                         count = 1;
2159                 }
2160         }
2161
2162         ret = real_writev(s, vector, count);
2163         if (ret == -1) {
2164                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2165         } else {
2166                 uint8_t *buf;
2167                 off_t ofs = 0;
2168                 size_t i;
2169                 size_t remain = ret;
2170
2171                 /* we capture it as one single packet */
2172                 buf = (uint8_t *)malloc(ret);
2173                 if (!buf) {
2174                         /* we just not capture the packet */
2175                         errno = 0;
2176                         return ret;
2177                 }
2178
2179                 for (i=0; i < count; i++) {
2180                         size_t this_time = MIN(remain, vector[i].iov_len);
2181                         memcpy(buf + ofs,
2182                                vector[i].iov_base,
2183                                this_time);
2184                         ofs += this_time;
2185                         remain -= this_time;
2186                 }
2187
2188                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2189                 free(buf);
2190         }
2191
2192         return ret;
2193 }
2194
2195 _PUBLIC_ int swrap_close(int fd)
2196 {
2197         struct socket_info *si = find_socket_info(fd);
2198         int ret;
2199
2200         if (!si) {
2201                 return real_close(fd);
2202         }
2203
2204         SWRAP_DLIST_REMOVE(sockets, si);
2205
2206         if (si->myname && si->peername) {
2207                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2208         }
2209
2210         ret = real_close(fd);
2211
2212         if (si->myname && si->peername) {
2213                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2214                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2215         }
2216
2217         if (si->path) free(si->path);
2218         if (si->myname) free(si->myname);
2219         if (si->peername) free(si->peername);
2220         if (si->tmp_path) {
2221                 unlink(si->tmp_path);
2222                 free(si->tmp_path);
2223         }
2224         free(si);
2225
2226         return ret;
2227 }