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