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