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