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