r19084: make socket_wrapper more portable (standalone) and not use uintX_t
[kai/samba.git] / source4 / lib / socket_wrapper / socket_wrapper.c
1 /* 
2    Socket wrapper library. Passes all socket communication over 
3    unix domain sockets if the environment variable SOCKET_WRAPPER_DIR 
4    is set.
5    Copyright (C) Jelmer Vernooij 2005
6    Copyright (C) Stefan Metzmacher 2006
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef _SAMBA_BUILD_
24
25 #define SOCKET_WRAPPER_NOT_REPLACE
26 #include "includes.h"
27 #include "system/network.h"
28 #include "system/filesys.h"
29
30 #ifndef _DLINKLIST_H
31 #include "lib/util/dlinklist.h"
32 #endif
33
34 #ifdef malloc
35 #undef malloc
36 #endif
37 #ifdef calloc
38 #undef calloc
39 #endif
40 #ifdef strdup
41 #undef strdup
42 #endif
43
44 #else /* _SAMBA_BUILD_ */
45
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <errno.h>
50 #include <sys/un.h>
51 #include <netinet/in.h>
52 #include <netinet/tcp.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <string.h>
56 #include <stdio.h>
57
58 #error "dlinklist.h missing"
59
60 #endif
61
62 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
63  * for now */
64 #define REWRITE_CALLS 
65
66 #ifdef REWRITE_CALLS
67 #define real_accept accept
68 #define real_connect connect
69 #define real_bind bind
70 #define real_listen listen
71 #define real_getpeername getpeername
72 #define real_getsockname getsockname
73 #define real_getsockopt getsockopt
74 #define real_setsockopt setsockopt
75 #define real_recvfrom recvfrom
76 #define real_sendto sendto
77 #define real_ioctl ioctl
78 #define real_recv recv
79 #define real_send send
80 #define real_socket socket
81 #define real_close close
82 #endif
83
84 /* we need to use a very terse format here as IRIX 6.4 silently
85    truncates names to 16 chars, so if we use a longer name then we
86    can't tell which port a packet came from with recvfrom() 
87    
88    with this format we have 8 chars left for the directory name
89 */
90 #define SOCKET_FORMAT "%c%02X%04X"
91 #define SOCKET_TYPE_CHAR_TCP            'T'
92 #define SOCKET_TYPE_CHAR_UDP            'U'
93
94 #define MAX_WRAPPED_INTERFACES 16
95
96 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
97 {
98         struct sockaddr *ret = (struct sockaddr *)malloc(len);
99         memcpy(ret, data, len);
100         return ret;
101 }
102
103 struct socket_info
104 {
105         int fd;
106
107         int family;
108         int type;
109         int protocol;
110         int bound;
111         int bcast;
112         int is_server;
113
114         char *path;
115         char *tmp_path;
116
117         struct sockaddr *myname;
118         socklen_t myname_len;
119
120         struct sockaddr *peername;
121         socklen_t peername_len;
122
123         struct {
124                 unsigned long pck_snd;
125                 unsigned long pck_rcv;
126         } io;
127
128         struct socket_info *prev, *next;
129 };
130
131 static struct socket_info *sockets;
132
133
134 static const char *socket_wrapper_dir(void)
135 {
136         const char *s = getenv("SOCKET_WRAPPER_DIR");
137         if (s == NULL) {
138                 return NULL;
139         }
140         if (strncmp(s, "./", 2) == 0) {
141                 s += 2;
142         }
143         return s;
144 }
145
146 static const char *socket_wrapper_pcap_file(void)
147 {
148         const char *s = getenv("SOCKET_WRAPPER_PCAP_FILE");
149
150         if (s == NULL) {
151                 return NULL;
152         }
153         if (strncmp(s, "./", 2) == 0) {
154                 s += 2;
155         }
156         return s;
157 }
158
159 static unsigned int socket_wrapper_default_iface(void)
160 {
161         const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
162         if (s) {
163                 unsigned int iface;
164                 if (sscanf(s, "%u", &iface) == 1) {
165                         if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
166                                 return iface;
167                         }
168                 }
169         }
170
171         return 1;/* 127.0.0.1 */
172 }
173
174 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
175 {
176         unsigned int iface;
177         unsigned int prt;
178         const char *p;
179         char type;
180
181         if ((*len) < sizeof(struct sockaddr_in)) {
182                 return 0;
183         }
184
185         p = strrchr(un->sun_path, '/');
186         if (p) p++; else p = un->sun_path;
187
188         if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
189                 errno = EINVAL;
190                 return -1;
191         }
192
193         if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
194                 errno = EINVAL;
195                 return -1;
196         }
197
198         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
199                 errno = EINVAL;
200                 return -1;
201         }
202
203         if (prt > 0xFFFF) {
204                 errno = EINVAL;
205                 return -1;
206         }
207
208         in->sin_family = AF_INET;
209         in->sin_addr.s_addr = htonl((127<<24) | iface);
210         in->sin_port = htons(prt);
211
212         *len = sizeof(struct sockaddr_in);
213         return 0;
214 }
215
216 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
217                                 int *bcast)
218 {
219         char u_type = '\0';
220         char b_type = '\0';
221         char a_type = '\0';
222         char type = '\0';
223         unsigned int addr= ntohl(in->sin_addr.s_addr);
224         unsigned int prt = ntohs(in->sin_port);
225         unsigned int iface;
226         int is_bcast = 0;
227
228         if (bcast) *bcast = 0;
229
230         if (prt == 0) {
231                 errno = EINVAL;
232                 return -1;
233         }
234
235         switch (si->type) {
236         case SOCK_STREAM:
237                 u_type = SOCKET_TYPE_CHAR_TCP;
238                 break;
239         case SOCK_DGRAM:
240                 u_type = SOCKET_TYPE_CHAR_UDP;
241                 a_type = SOCKET_TYPE_CHAR_UDP;
242                 b_type = SOCKET_TYPE_CHAR_UDP;
243                 break;
244         }
245
246         if (a_type && addr == 0xFFFFFFFF) {
247                 /* 255.255.255.255 only udp */
248                 is_bcast = 2;
249                 type = a_type;
250                 iface = socket_wrapper_default_iface();
251         } else if (b_type && addr == 0x7FFFFFFF) {
252                 /* 127.255.255.255 only udp */
253                 is_bcast = 1;
254                 type = b_type;
255                 iface = socket_wrapper_default_iface();
256         } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
257                 /* 127.0.0.X */
258                 is_bcast = 0;
259                 type = u_type;
260                 iface = (addr & 0x000000FF);
261         } else {
262                 errno = ENETUNREACH;
263                 return -1;
264         }
265
266         if (bcast) *bcast = is_bcast;
267
268         if (is_bcast) {
269                 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
270                          socket_wrapper_dir());
271                 /* the caller need to do more processing */
272                 return 0;
273         }
274
275         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
276                  socket_wrapper_dir(), type, iface, prt);
277
278         return 0;
279 }
280
281 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
282                                int *bcast)
283 {
284         char u_type = '\0';
285         char d_type = '\0';
286         char b_type = '\0';
287         char a_type = '\0';
288         char type = '\0';
289         unsigned int addr= ntohl(in->sin_addr.s_addr);
290         unsigned int prt = ntohs(in->sin_port);
291         unsigned int iface;
292         struct stat st;
293         int is_bcast = 0;
294
295         if (bcast) *bcast = 0;
296
297         switch (si->type) {
298         case SOCK_STREAM:
299                 u_type = SOCKET_TYPE_CHAR_TCP;
300                 d_type = SOCKET_TYPE_CHAR_TCP;
301                 break;
302         case SOCK_DGRAM:
303                 u_type = SOCKET_TYPE_CHAR_UDP;
304                 d_type = SOCKET_TYPE_CHAR_UDP;
305                 a_type = SOCKET_TYPE_CHAR_UDP;
306                 b_type = SOCKET_TYPE_CHAR_UDP;
307                 break;
308         }
309
310         if (addr == 0) {
311                 /* 0.0.0.0 */
312                 is_bcast = 0;
313                 type = d_type;
314                 iface = socket_wrapper_default_iface();
315         } else if (a_type && addr == 0xFFFFFFFF) {
316                 /* 255.255.255.255 only udp */
317                 is_bcast = 2;
318                 type = a_type;
319                 iface = socket_wrapper_default_iface();
320         } else if (b_type && addr == 0x7FFFFFFF) {
321                 /* 127.255.255.255 only udp */
322                 is_bcast = 1;
323                 type = b_type;
324                 iface = socket_wrapper_default_iface();
325         } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
326                 /* 127.0.0.X */
327                 is_bcast = 0;
328                 type = u_type;
329                 iface = (addr & 0x000000FF);
330         } else {
331                 errno = EADDRNOTAVAIL;
332                 return -1;
333         }
334
335         if (bcast) *bcast = is_bcast;
336
337         if (prt == 0) {
338                 /* handle auto-allocation of ephemeral ports */
339                 for (prt = 5001; prt < 10000; prt++) {
340                         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
341                                  socket_wrapper_dir(), type, iface, prt);
342                         if (stat(un->sun_path, &st) == 0) continue;
343
344                         ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
345                         return 0;
346                 }
347                 errno = ENFILE;
348                 return -1;
349         }
350
351         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
352                  socket_wrapper_dir(), type, iface, prt);
353         return 0;
354 }
355
356 static struct socket_info *find_socket_info(int fd)
357 {
358         struct socket_info *i;
359         for (i = sockets; i; i = i->next) {
360                 if (i->fd == fd) 
361                         return i;
362         }
363
364         return NULL;
365 }
366
367 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 
368                                   struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
369 {
370         if (!out_addr)
371                 return 0;
372
373         out_addr->sun_family = AF_UNIX;
374
375         switch (in_addr->sa_family) {
376         case AF_INET:
377                 switch (si->type) {
378                 case SOCK_STREAM:
379                 case SOCK_DGRAM:
380                         break;
381                 default:
382                         errno = ESOCKTNOSUPPORT;
383                         return -1;
384                 }
385                 if (alloc_sock) {
386                         return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
387                 } else {
388                         return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
389                 }
390         default:
391                 break;
392         }
393         
394         errno = EAFNOSUPPORT;
395         return -1;
396 }
397
398 static int sockaddr_convert_from_un(const struct socket_info *si, 
399                                     const struct sockaddr_un *in_addr, 
400                                     socklen_t un_addrlen,
401                                     int family,
402                                     struct sockaddr *out_addr,
403                                     socklen_t *_out_addrlen)
404 {
405         socklen_t out_addrlen;
406
407         if (out_addr == NULL || _out_addrlen == NULL) 
408                 return 0;
409
410         if (un_addrlen == 0) {
411                 *_out_addrlen = 0;
412                 return 0;
413         }
414
415         out_addrlen = *_out_addrlen;
416         if (out_addrlen > un_addrlen) {
417                 out_addrlen = un_addrlen;
418         }
419
420         switch (family) {
421         case AF_INET:
422                 switch (si->type) {
423                 case SOCK_STREAM:
424                 case SOCK_DGRAM:
425                         break;
426                 default:
427                         errno = ESOCKTNOSUPPORT;
428                         return -1;
429                 }
430                 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
431         default:
432                 break;
433         }
434
435         errno = EAFNOSUPPORT;
436         return -1;
437 }
438
439 enum swrap_packet_type {
440         SWRAP_CONNECT_SEND,
441         SWRAP_CONNECT_UNREACH,
442         SWRAP_CONNECT_RECV,
443         SWRAP_CONNECT_ACK,
444         SWRAP_ACCEPT_SEND,
445         SWRAP_ACCEPT_RECV,
446         SWRAP_ACCEPT_ACK,
447         SWRAP_RECVFROM,
448         SWRAP_SENDTO,
449         SWRAP_SENDTO_UNREACH,
450         SWRAP_PENDING_RST,
451         SWRAP_RECV,
452         SWRAP_RECV_RST,
453         SWRAP_SEND,
454         SWRAP_SEND_RST,
455         SWRAP_CLOSE_SEND,
456         SWRAP_CLOSE_RECV,
457         SWRAP_CLOSE_ACK
458 };
459
460 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
461                               enum swrap_packet_type type,
462                               const void *buf, size_t len)
463 {
464         const struct sockaddr_in *src_addr;
465         const struct sockaddr_in *dest_addr;
466         const char *file_name;
467         unsigned long tcp_seq = 0;
468         unsigned long tcp_ack = 0;
469         unsigned char tcp_ctl = 0;
470         int unreachable = 0;
471
472         file_name = socket_wrapper_pcap_file();
473         if (!file_name) {
474                 return;
475         }
476
477         if (si->family != AF_INET) {
478                 return;
479         }
480
481         switch (type) {
482         case SWRAP_CONNECT_SEND:
483                 if (si->type != SOCK_STREAM) return;
484
485                 src_addr = (const struct sockaddr_in *)si->myname;
486                 dest_addr = (const struct sockaddr_in *)addr;
487
488                 tcp_seq = si->io.pck_snd;
489                 tcp_ack = si->io.pck_rcv;
490                 tcp_ctl = 0x02; /* SYN */
491
492                 si->io.pck_snd += 1;
493
494                 break;
495
496         case SWRAP_CONNECT_RECV:
497                 if (si->type != SOCK_STREAM) return;
498
499                 dest_addr = (const struct sockaddr_in *)si->myname;
500                 src_addr = (const struct sockaddr_in *)addr;
501
502                 tcp_seq = si->io.pck_rcv;
503                 tcp_ack = si->io.pck_snd;
504                 tcp_ctl = 0x12; /** SYN,ACK */
505
506                 si->io.pck_rcv += 1;
507
508                 break;
509
510         case SWRAP_CONNECT_UNREACH:
511                 if (si->type != SOCK_STREAM) return;
512
513                 dest_addr = (const struct sockaddr_in *)si->myname;
514                 src_addr = (const struct sockaddr_in *)addr;
515
516                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
517                 tcp_seq = si->io.pck_snd - 1;
518                 tcp_ack = si->io.pck_rcv;
519                 tcp_ctl = 0x02; /* SYN */
520                 unreachable = 1;
521
522                 break;
523
524         case SWRAP_CONNECT_ACK:
525                 if (si->type != SOCK_STREAM) return;
526
527                 src_addr = (const struct sockaddr_in *)si->myname;
528                 dest_addr = (const struct sockaddr_in *)addr;
529
530                 tcp_seq = si->io.pck_snd;
531                 tcp_ack = si->io.pck_rcv;
532                 tcp_ctl = 0x10; /* ACK */
533
534                 break;
535
536         case SWRAP_ACCEPT_SEND:
537                 if (si->type != SOCK_STREAM) return;
538
539                 dest_addr = (const struct sockaddr_in *)si->myname;
540                 src_addr = (const struct sockaddr_in *)addr;
541
542                 tcp_seq = si->io.pck_rcv;
543                 tcp_ack = si->io.pck_snd;
544                 tcp_ctl = 0x02; /* SYN */
545
546                 si->io.pck_rcv += 1;
547
548                 break;
549
550         case SWRAP_ACCEPT_RECV:
551                 if (si->type != SOCK_STREAM) return;
552
553                 src_addr = (const struct sockaddr_in *)si->myname;
554                 dest_addr = (const struct sockaddr_in *)addr;
555
556                 tcp_seq = si->io.pck_snd;
557                 tcp_ack = si->io.pck_rcv;
558                 tcp_ctl = 0x12; /* SYN,ACK */
559
560                 si->io.pck_snd += 1;
561
562                 break;
563
564         case SWRAP_ACCEPT_ACK:
565                 if (si->type != SOCK_STREAM) return;
566
567                 dest_addr = (const struct sockaddr_in *)si->myname;
568                 src_addr = (const struct sockaddr_in *)addr;
569
570                 tcp_seq = si->io.pck_rcv;
571                 tcp_ack = si->io.pck_snd;
572                 tcp_ctl = 0x10; /* ACK */
573
574                 break;
575
576         case SWRAP_SEND:
577                 src_addr = (const struct sockaddr_in *)si->myname;
578                 dest_addr = (const struct sockaddr_in *)si->peername;
579
580                 tcp_seq = si->io.pck_snd;
581                 tcp_ack = si->io.pck_rcv;
582                 tcp_ctl = 0x18; /* PSH,ACK */
583
584                 si->io.pck_snd += len;
585
586                 break;
587
588         case SWRAP_SEND_RST:
589                 dest_addr = (const struct sockaddr_in *)si->myname;
590                 src_addr = (const struct sockaddr_in *)si->peername;
591
592                 if (si->type == SOCK_DGRAM) {
593                         swrap_dump_packet(si, si->peername,
594                                           SWRAP_SENDTO_UNREACH,
595                                           buf, len);
596                         return;
597                 }
598
599                 tcp_seq = si->io.pck_rcv;
600                 tcp_ack = si->io.pck_snd;
601                 tcp_ctl = 0x14; /** RST,ACK */
602
603                 break;
604
605         case SWRAP_PENDING_RST:
606                 dest_addr = (const struct sockaddr_in *)si->myname;
607                 src_addr = (const struct sockaddr_in *)si->peername;
608
609                 if (si->type == SOCK_DGRAM) {
610                         return;
611                 }
612
613                 tcp_seq = si->io.pck_rcv;
614                 tcp_ack = si->io.pck_snd;
615                 tcp_ctl = 0x14; /* RST,ACK */
616
617                 break;
618
619         case SWRAP_RECV:
620                 dest_addr = (const struct sockaddr_in *)si->myname;
621                 src_addr = (const struct sockaddr_in *)si->peername;
622
623                 tcp_seq = si->io.pck_rcv;
624                 tcp_ack = si->io.pck_snd;
625                 tcp_ctl = 0x18; /* PSH,ACK */
626
627                 si->io.pck_rcv += len;
628
629                 break;
630
631         case SWRAP_RECV_RST:
632                 dest_addr = (const struct sockaddr_in *)si->myname;
633                 src_addr = (const struct sockaddr_in *)si->peername;
634
635                 if (si->type == SOCK_DGRAM) {
636                         return;
637                 }
638
639                 tcp_seq = si->io.pck_rcv;
640                 tcp_ack = si->io.pck_snd;
641                 tcp_ctl = 0x14; /* RST,ACK */
642
643                 break;
644
645         case SWRAP_SENDTO:
646                 src_addr = (const struct sockaddr_in *)si->myname;
647                 dest_addr = (const struct sockaddr_in *)addr;
648
649                 si->io.pck_snd += len;
650
651                 break;
652
653         case SWRAP_SENDTO_UNREACH:
654                 dest_addr = (const struct sockaddr_in *)si->myname;
655                 src_addr = (const struct sockaddr_in *)addr;
656
657                 unreachable = 1;
658
659                 break;
660
661         case SWRAP_RECVFROM:
662                 dest_addr = (const struct sockaddr_in *)si->myname;
663                 src_addr = (const struct sockaddr_in *)addr;
664
665                 si->io.pck_rcv += len;
666
667                 break;
668
669         case SWRAP_CLOSE_SEND:
670                 if (si->type != SOCK_STREAM) return;
671
672                 src_addr = (const struct sockaddr_in *)si->myname;
673                 dest_addr = (const struct sockaddr_in *)si->peername;
674
675                 tcp_seq = si->io.pck_snd;
676                 tcp_ack = si->io.pck_rcv;
677                 tcp_ctl = 0x11; /* FIN, ACK */
678
679                 si->io.pck_snd += 1;
680
681                 break;
682
683         case SWRAP_CLOSE_RECV:
684                 if (si->type != SOCK_STREAM) return;
685
686                 dest_addr = (const struct sockaddr_in *)si->myname;
687                 src_addr = (const struct sockaddr_in *)si->peername;
688
689                 tcp_seq = si->io.pck_rcv;
690                 tcp_ack = si->io.pck_snd;
691                 tcp_ctl = 0x11; /* FIN,ACK */
692
693                 si->io.pck_rcv += 1;
694
695                 break;
696
697         case SWRAP_CLOSE_ACK:
698                 if (si->type != SOCK_STREAM) return;
699
700                 src_addr = (const struct sockaddr_in *)si->myname;
701                 dest_addr = (const struct sockaddr_in *)si->peername;
702
703                 tcp_seq = si->io.pck_snd;
704                 tcp_ack = si->io.pck_rcv;
705                 tcp_ctl = 0x10; /* ACK */
706
707                 break;
708         }
709
710         /* TODO: contruct the blob and write to the file */
711 }
712
713 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
714 {
715         struct socket_info *si;
716         int fd;
717
718         if (!socket_wrapper_dir()) {
719                 return real_socket(family, type, protocol);
720         }
721
722         switch (family) {
723         case AF_INET:
724                 break;
725         case AF_UNIX:
726                 return real_socket(family, type, protocol);
727         default:
728                 errno = EAFNOSUPPORT;
729                 return -1;
730         }
731
732         switch (type) {
733         case SOCK_STREAM:
734                 break;
735         case SOCK_DGRAM:
736                 break;
737         default:
738                 errno = EPROTONOSUPPORT;
739                 return -1;
740         }
741
742         switch (protocol) {
743         case 0:
744                 break;
745         default:
746                 errno = EPROTONOSUPPORT;
747                 return -1;
748         }
749
750         fd = real_socket(AF_UNIX, type, 0);
751
752         if (fd == -1) return -1;
753
754         si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
755
756         si->family = family;
757         si->type = type;
758         si->protocol = protocol;
759         si->fd = fd;
760
761         DLIST_ADD(sockets, si);
762
763         return si->fd;
764 }
765
766 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
767 {
768         struct socket_info *parent_si, *child_si;
769         int fd;
770         struct sockaddr_un un_addr;
771         socklen_t un_addrlen = sizeof(un_addr);
772         struct sockaddr_un un_my_addr;
773         socklen_t un_my_addrlen = sizeof(un_my_addr);
774         struct sockaddr my_addr;
775         socklen_t my_addrlen = sizeof(my_addr);
776         int ret;
777
778         parent_si = find_socket_info(s);
779         if (!parent_si) {
780                 return real_accept(s, addr, addrlen);
781         }
782
783         memset(&un_addr, 0, sizeof(un_addr));
784         memset(&un_my_addr, 0, sizeof(un_my_addr));
785         memset(&my_addr, 0, sizeof(my_addr));
786
787         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
788         if (ret == -1) return ret;
789
790         fd = ret;
791
792         ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
793                                        parent_si->family, addr, addrlen);
794         if (ret == -1) {
795                 close(fd);
796                 return ret;
797         }
798
799         child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
800         memset(child_si, 0, sizeof(*child_si));
801
802         child_si->fd = fd;
803         child_si->family = parent_si->family;
804         child_si->type = parent_si->type;
805         child_si->protocol = parent_si->protocol;
806         child_si->bound = 1;
807         child_si->is_server = 1;
808
809         ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
810         if (ret == -1) {
811                 free(child_si);
812                 close(fd);
813                 return ret;
814         }
815
816         ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
817                                        child_si->family, &my_addr, &my_addrlen);
818         if (ret == -1) {
819                 free(child_si);
820                 close(fd);
821                 return ret;
822         }
823
824         child_si->myname_len = my_addrlen;
825         child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
826
827         child_si->peername_len = *addrlen;
828         child_si->peername = sockaddr_dup(addr, *addrlen);
829
830         DLIST_ADD(sockets, child_si);
831
832         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
833         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
834         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
835
836         return fd;
837 }
838
839 static int autobind_start_init;
840 static int autobind_start;
841
842 /* using sendto() or connect() on an unbound socket would give the
843    recipient no way to reply, as unlike UDP and TCP, a unix domain
844    socket can't auto-assign emphemeral port numbers, so we need to
845    assign it here */
846 static int swrap_auto_bind(struct socket_info *si)
847 {
848         struct sockaddr_un un_addr;
849         struct sockaddr_in in;
850         int i;
851         char type;
852         int ret;
853         int port;
854         struct stat st;
855
856         if (autobind_start_init != 1) {
857                 autobind_start_init = 1;
858                 autobind_start = getpid();
859                 autobind_start %= 50000;
860                 autobind_start += 10000;
861         }
862
863         un_addr.sun_family = AF_UNIX;
864
865         switch (si->type) {
866         case SOCK_STREAM:
867                 type = SOCKET_TYPE_CHAR_TCP;
868                 break;
869         case SOCK_DGRAM:
870                 type = SOCKET_TYPE_CHAR_UDP;
871                 break;
872         default:
873                 errno = ESOCKTNOSUPPORT;
874                 return -1;
875         }
876
877         if (autobind_start > 60000) {
878                 autobind_start = 10000;
879         }
880
881         for (i=0;i<1000;i++) {
882                 port = autobind_start + i;
883                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
884                          "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
885                          type, socket_wrapper_default_iface(), port);
886                 if (stat(un_addr.sun_path, &st) == 0) continue;
887                 
888                 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
889                 if (ret == -1) return ret;
890
891                 si->tmp_path = strdup(un_addr.sun_path);
892                 si->bound = 1;
893                 autobind_start = port + 1;
894                 break;
895         }
896         if (i == 1000) {
897                 errno = ENFILE;
898                 return -1;
899         }
900
901         memset(&in, 0, sizeof(in));
902         in.sin_family = AF_INET;
903         in.sin_port   = htons(port);
904         in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
905         
906         si->myname_len = sizeof(in);
907         si->myname = sockaddr_dup(&in, si->myname_len);
908         return 0;
909 }
910
911
912 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
913 {
914         int ret;
915         struct sockaddr_un un_addr;
916         struct socket_info *si = find_socket_info(s);
917
918         if (!si) {
919                 return real_connect(s, serv_addr, addrlen);
920         }
921
922         if (si->bound == 0) {
923                 ret = swrap_auto_bind(si);
924                 if (ret == -1) return -1;
925         }
926
927         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
928         if (ret == -1) return -1;
929
930         swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
931
932         ret = real_connect(s, (struct sockaddr *)&un_addr, 
933                            sizeof(struct sockaddr_un));
934
935         /* to give better errors */
936         if (ret == -1 && errno == ENOENT) {
937                 errno = EHOSTUNREACH;
938         }
939
940         if (ret == 0) {
941                 si->peername_len = addrlen;
942                 si->peername = sockaddr_dup(serv_addr, addrlen);
943
944                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
945                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
946         } else {
947                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
948         }
949
950         return ret;
951 }
952
953 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
954 {
955         int ret;
956         struct sockaddr_un un_addr;
957         struct socket_info *si = find_socket_info(s);
958
959         if (!si) {
960                 return real_bind(s, myaddr, addrlen);
961         }
962
963         si->myname_len = addrlen;
964         si->myname = sockaddr_dup(myaddr, addrlen);
965
966         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
967         if (ret == -1) return -1;
968
969         unlink(un_addr.sun_path);
970
971         ret = real_bind(s, (struct sockaddr *)&un_addr,
972                         sizeof(struct sockaddr_un));
973
974         if (ret == 0) {
975                 si->bound = 1;
976         }
977
978         return ret;
979 }
980
981 _PUBLIC_ int swrap_listen(int s, int backlog)
982 {
983         int ret;
984         struct socket_info *si = find_socket_info(s);
985
986         if (!si) {
987                 return real_listen(s, backlog);
988         }
989
990         ret = real_listen(s, backlog);
991
992         return ret;
993 }
994
995 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
996 {
997         struct socket_info *si = find_socket_info(s);
998
999         if (!si) {
1000                 return real_getpeername(s, name, addrlen);
1001         }
1002
1003         if (!si->peername)
1004         {
1005                 errno = ENOTCONN;
1006                 return -1;
1007         }
1008
1009         memcpy(name, si->peername, si->peername_len);
1010         *addrlen = si->peername_len;
1011
1012         return 0;
1013 }
1014
1015 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1016 {
1017         struct socket_info *si = find_socket_info(s);
1018
1019         if (!si) {
1020                 return real_getsockname(s, name, addrlen);
1021         }
1022
1023         memcpy(name, si->myname, si->myname_len);
1024         *addrlen = si->myname_len;
1025
1026         return 0;
1027 }
1028
1029 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1030 {
1031         struct socket_info *si = find_socket_info(s);
1032
1033         if (!si) {
1034                 return real_getsockopt(s, level, optname, optval, optlen);
1035         }
1036
1037         if (level == SOL_SOCKET) {
1038                 return real_getsockopt(s, level, optname, optval, optlen);
1039         } 
1040
1041         errno = ENOPROTOOPT;
1042         return -1;
1043 }
1044
1045 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
1046 {
1047         struct socket_info *si = find_socket_info(s);
1048
1049         if (!si) {
1050                 return real_setsockopt(s, level, optname, optval, optlen);
1051         }
1052
1053         if (level == SOL_SOCKET) {
1054                 return real_setsockopt(s, level, optname, optval, optlen);
1055         }
1056
1057         switch (si->family) {
1058         case AF_INET:
1059                 return 0;
1060         default:
1061                 errno = ENOPROTOOPT;
1062                 return -1;
1063         }
1064 }
1065
1066 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1067 {
1068         struct sockaddr_un un_addr;
1069         socklen_t un_addrlen = sizeof(un_addr);
1070         int ret;
1071         struct socket_info *si = find_socket_info(s);
1072
1073         if (!si) {
1074                 return real_recvfrom(s, buf, len, flags, from, fromlen);
1075         }
1076
1077         /* irix 6.4 forgets to null terminate the sun_path string :-( */
1078         memset(&un_addr, 0, sizeof(un_addr));
1079         ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1080         if (ret == -1) 
1081                 return ret;
1082
1083         if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1084                                      si->family, from, fromlen) == -1) {
1085                 return -1;
1086         }
1087
1088         swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1089
1090         return ret;
1091 }
1092
1093
1094 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1095 {
1096         struct sockaddr_un un_addr;
1097         int ret;
1098         struct socket_info *si = find_socket_info(s);
1099         int bcast = 0;
1100
1101         if (!si) {
1102                 return real_sendto(s, buf, len, flags, to, tolen);
1103         }
1104
1105         if (si->bound == 0) {
1106                 ret = swrap_auto_bind(si);
1107                 if (ret == -1) return -1;
1108         }
1109
1110         ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1111         if (ret == -1) return -1;
1112
1113         if (bcast) {
1114                 struct stat st;
1115                 unsigned int iface;
1116                 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1117                 char type;
1118
1119                 type = SOCKET_TYPE_CHAR_UDP;
1120
1121                 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1122                         snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
1123                                  socket_wrapper_dir(), type, iface, prt);
1124                         if (stat(un_addr.sun_path, &st) != 0) continue;
1125
1126                         /* ignore the any errors in broadcast sends */
1127                         real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1128                 }
1129
1130                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1131
1132                 return len;
1133         }
1134
1135         ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1136
1137         /* to give better errors */
1138         if (ret == -1 && errno == ENOENT) {
1139                 errno = EHOSTUNREACH;
1140         }
1141
1142         if (ret == -1) {
1143                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1144                 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1145         } else {
1146                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1147         }
1148
1149         return ret;
1150 }
1151
1152 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1153 {
1154         int ret;
1155         struct socket_info *si = find_socket_info(s);
1156         int value;
1157
1158         if (!si) {
1159                 return real_ioctl(s, r, p);
1160         }
1161
1162         ret = real_ioctl(s, r, p);
1163
1164         switch (r) {
1165         case FIONREAD:
1166                 value = *((int *)p);
1167                 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1168                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1169                 } else if (value == 0) { /* END OF FILE */
1170                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1171                 }
1172                 break;
1173         }
1174
1175         return ret;
1176 }
1177
1178 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1179 {
1180         int ret;
1181         struct socket_info *si = find_socket_info(s);
1182
1183         if (!si) {
1184                 return real_recv(s, buf, len, flags);
1185         }
1186
1187         ret = real_recv(s, buf, len, flags);
1188         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1189                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1190         } else if (ret == 0) { /* END OF FILE */
1191                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1192         } else {
1193                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1194         }
1195
1196         return ret;
1197 }
1198
1199
1200 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1201 {
1202         int ret;
1203         struct socket_info *si = find_socket_info(s);
1204
1205         if (!si) {
1206                 return real_send(s, buf, len, flags);
1207         }
1208
1209         ret = real_send(s, buf, len, flags);
1210
1211         if (ret == -1) {
1212                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1213                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1214         } else {
1215                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1216         }
1217
1218         return ret;
1219 }
1220
1221 _PUBLIC_ int swrap_close(int fd)
1222 {
1223         struct socket_info *si = find_socket_info(fd);
1224         int ret;
1225
1226         if (!si) {
1227                 return real_close(fd);
1228         }
1229
1230         DLIST_REMOVE(sockets, si);
1231
1232         if (si->myname && si->peername) {
1233                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1234         }
1235
1236         ret = real_close(fd);
1237
1238         if (si->myname && si->peername) {
1239                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1240                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1241         }
1242
1243         if (si->path) free(si->path);
1244         if (si->myname) free(si->myname);
1245         if (si->peername) free(si->peername);
1246         if (si->tmp_path) {
1247                 unlink(si->tmp_path);
1248                 free(si->tmp_path);
1249         }
1250         free(si);
1251
1252         return ret;
1253 }