RFC2553 just says that sockaddr_storage has to have initial fields
[rsync.git] / socket.c
1 /* -*- c-file-style: "linux" -*-
2    
3    Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
4    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /**
22  * @file socket.c
23  * 
24  * Socket functions used in rsync.
25  **/
26
27 #include "rsync.h"
28
29 /* Establish a proxy connection on an open socket to a web roxy by
30  * using the CONNECT method. */
31 static int establish_proxy_connection(int fd, char *host, int port)
32 {
33         char buffer[1024];
34         char *cp;
35
36         snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
37         if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
38                 rprintf(FERROR, "failed to write to proxy: %s\n",
39                         strerror(errno));
40                 return -1;
41         }
42
43         for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
44                 if (read(fd, cp, 1) != 1) {
45                         rprintf(FERROR, "failed to read from proxy: %s\n",
46                                 strerror(errno));
47                         return -1;
48                 }
49                 if (*cp == '\n')
50                         break;
51         }
52
53         if (*cp != '\n')
54                 cp++;
55         *cp-- = '\0';
56         if (*cp == '\r')
57                 *cp = '\0';
58         if (strncmp(buffer, "HTTP/", 5) != 0) {
59                 rprintf(FERROR, "bad response from proxy - %s\n",
60                         buffer);
61                 return -1;
62         }
63         for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
64                 ;
65         while (*cp == ' ')
66                 cp++;
67         if (*cp != '2') {
68                 rprintf(FERROR, "bad response from proxy - %s\n",
69                         buffer);
70                 return -1;
71         }
72         /* throw away the rest of the HTTP header */
73         while (1) {
74                 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
75                      cp++) {
76                         if (read(fd, cp, 1) != 1) {
77                                 rprintf(FERROR, "failed to read from proxy: %s\n",
78                                         strerror(errno));
79                                 return -1;
80                         }
81                         if (*cp == '\n')
82                                 break;
83                 }
84                 if ((cp > buffer) && (*cp == '\n'))
85                         cp--;
86                 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
87                         break;
88         }
89         return 0;
90 }
91
92
93
94 /**
95  * Open a socket to a tcp remote host with the specified port .
96  *
97  * Based on code from Warren.  Proxy support by Stephen Rothwell.
98  * getaddrinfo() rewrite contributed by KAME.net.
99  *
100  * Now that we support IPv6 we need to look up the remote machine's
101  * address first, using @p af_hint to set a preference for the type
102  * of address.  Then depending on whether it has v4 or v6 addresses we
103  * try to open a connection.
104  *
105  * The loop allows for machines with some addresses which may not be
106  * reachable, perhaps because we can't e.g. route ipv6 to that network
107  * but we can get ip4 packets through.
108  *
109  * @param bind_address Local address to use.  Normally NULL to bind
110  * the wildcard address.
111  *
112  * @param af_hint Address family, e.g. AF_INET or AF_INET6.
113  **/
114 int open_socket_out(char *host, int port, const char *bind_address,
115                     int af_hint)
116 {
117         int type = SOCK_STREAM;
118         int error;
119         int s;
120         int result;
121         struct addrinfo hints, *res0, *res;
122         char portbuf[10];
123         char *h;
124         int proxied = 0;
125         char buffer[1024];
126         char *cp;
127
128         /* if we have a RSYNC_PROXY env variable then redirect our
129          * connetcion via a web proxy at the given address. The format
130          * is hostname:port */
131         h = getenv("RSYNC_PROXY");
132         proxied = (h != NULL) && (*h != '\0');
133
134         if (proxied) {
135                 strlcpy(buffer, h, sizeof(buffer));
136                 cp = strchr(buffer, ':');
137                 if (cp == NULL) {
138                         rprintf(FERROR,
139                                 "invalid proxy specification: should be HOST:PORT\n");
140                         return -1;
141                 }
142                 *cp++ = '\0';
143                 strcpy(portbuf, cp);
144                 h = buffer;
145         } else {
146                 snprintf(portbuf, sizeof(portbuf), "%d", port);
147                 h = host;
148         }
149
150         memset(&hints, 0, sizeof(hints));
151         hints.ai_family = af_hint;
152         hints.ai_socktype = type;
153         error = getaddrinfo(h, portbuf, &hints, &res0);
154         if (error) {
155                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
156                         h, portbuf, gai_strerror(error));
157                 return -1;
158         }
159
160         s = -1;
161         /* Try to connect to all addresses for this machine until we get
162          * through.  It might e.g. be multi-homed, or have both IPv4 and IPv6
163          * addresses.  We need to create a socket for each record, since the
164          * address record tells us what protocol to use to try to connect. */
165         for (res = res0; res; res = res->ai_next) {
166                 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
167                 if (s < 0)
168                         continue;
169
170                 if (bind_address) {
171                         struct addrinfo bhints, *bres;
172
173                         memset(&bhints, 0, sizeof(bhints));
174                         bhints.ai_family = res->ai_family;
175                         bhints.ai_socktype = type;
176                         bhints.ai_flags = AI_PASSIVE;
177                         error = getaddrinfo(bind_address, NULL, &bhints, &bres);
178                         if (error) {
179                                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
180                                         "bind address %s <noport>: %s\n",
181                                         bind_address, gai_strerror(error));
182                                 continue;
183                         }
184                         if (bres->ai_next) {
185                                 /* I'm not at all sure that this is the right
186                                  * response here... -- mbp */
187                                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
188                                         "bind address %s resolved to multiple hosts\n",
189                                         bind_address);
190                                 freeaddrinfo(bres);
191                                 continue;
192                         }
193                         bind(s, bres->ai_addr, bres->ai_addrlen);
194                 }
195
196                 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
197                         close(s);
198                         s = -1;
199                         continue;
200                 }
201                 if (proxied &&
202                     establish_proxy_connection(s, host, port) != 0) {
203                         close(s);
204                         s = -1;
205                         continue;
206                 } else
207                         break;
208         }
209         freeaddrinfo(res0);
210         if (s < 0) {
211                 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
212                         h, strerror(errno));
213                 return -1;
214         }
215         return s;
216 }
217
218
219 /**
220  * Open an outgoing socket, but allow for it to be intercepted by
221  * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
222  * socketpair rather than really opening a socket.
223  *
224  * We use this primarily in testing to detect TCP flow bugs, but not
225  * cause security problems by really opening remote connections.
226  *
227  * This is based on the Samba LIBSMB_PROG feature.
228  *
229  * @param bind_address Local address to use.  Normally NULL to get the stack default.
230  **/
231 int open_socket_out_wrapped (char *host,
232                              int port,
233                              const char *bind_address,
234                              int af_hint)
235 {
236         char *prog;
237
238         if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL) 
239                 return sock_exec (prog);
240         else 
241                 return open_socket_out (host, port, bind_address,
242                                         af_hint);
243 }
244
245
246
247 /**
248  * Open a socket of the specified type, port and address for incoming data
249  *
250  * Try to be better about handling the results of getaddrinfo(): when
251  * opening an inbound socket, we might get several address results,
252  * e.g. for the machine's ipv4 and ipv6 name.  
253  * 
254  * If binding a wildcard, then any one of them should do.  If an address
255  * was specified but it's insufficiently specific then that's not our
256  * fault.  
257  * 
258  * However, some of the advertized addresses may not work because e.g. we
259  * don't have IPv6 support in the kernel.  In that case go on and try all
260  * addresses until one succeeds.
261  * 
262  * @param bind_address Local address to bind, or NULL to allow it to
263  * default.
264  **/
265 static int open_socket_in(int type, int port, const char *bind_address,
266                           int af_hint)
267 {
268         int one=1;
269         int s;
270         struct addrinfo hints, *res, *resp;
271         char portbuf[10];
272         int error;
273
274         memset(&hints, 0, sizeof(hints));
275         hints.ai_family = af_hint;
276         hints.ai_socktype = type;
277         hints.ai_flags = AI_PASSIVE;
278         snprintf(portbuf, sizeof(portbuf), "%d", port);
279         error = getaddrinfo(bind_address, portbuf, &hints, &res);
280         if (error) {
281                 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
282                         bind_address, gai_strerror(error));
283                 return -1;
284         }
285         /* XXX: Do we need to care about getting multiple results
286          * back?  I think probably not; if the user passed
287          * bind_address == NULL and we set AI_PASSIVE then we ought to
288          * get a wildcard result. */
289
290         resp = res;
291         while (1) {
292                 s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
293
294                 if (s >= 0) {
295                         break;  /* got a socket */
296                 } else if ((resp = resp->ai_next)) {
297                         switch (errno) {
298                         case EPROTONOSUPPORT:
299                         case EAFNOSUPPORT:
300                         case EPFNOSUPPORT:
301                                 /* See if there's another address that will work... */
302                                 continue;
303                         }
304                 }
305                 
306                 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
307                         "(dom=%d, type=%d, proto=%d) failed: %s\n",
308                         resp->ai_family, resp->ai_socktype, resp->ai_protocol,
309                         strerror(errno));
310                         goto fail;
311         }
312
313         setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
314
315         /* now we've got a socket - we need to bind it */
316         if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { 
317                 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
318                 close(s);
319                 goto fail;
320         }
321
322         return s;
323
324 fail:
325         freeaddrinfo(res);
326         return -1; 
327 }
328
329
330 /*
331  * Determine if a file descriptor is in fact a socket
332  */
333 int is_a_socket(int fd)
334 {
335         int v;
336         socklen_t l;
337         l = sizeof(int);
338
339         /* Parameters to getsockopt, setsockopt etc are very
340          * unstandardized across platforms, so don't be surprised if
341          * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
342          * It seems they all eventually get the right idea.
343          *
344          * Debian says: ``The fifth argument of getsockopt and
345          * setsockopt is in reality an int [*] (and this is what BSD
346          * 4.* and libc4 and libc5 have).  Some POSIX confusion
347          * resulted in the present socklen_t.  The draft standard has
348          * not been adopted yet, but glibc2 already follows it and
349          * also has socklen_t [*]. See also accept(2).''
350          *
351          * We now return to your regularly scheduled programming.  */
352         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
353 }
354
355
356 void start_accept_loop(int port, int (*fn)(int ))
357 {
358         int s;
359         extern char *bind_address;
360
361         /* open an incoming socket */
362         s = open_socket_in(SOCK_STREAM, port, bind_address,
363                            global_opts.af_hint);
364         if (s == -1)
365                 exit_cleanup(RERR_SOCKETIO);
366
367         /* ready to listen */
368         if (listen(s, 5) == -1) {
369                 close(s);
370                 exit_cleanup(RERR_SOCKETIO);
371         }
372
373
374         /* now accept incoming connections - forking a new process
375            for each incoming connection */
376         while (1) {
377                 fd_set fds;
378                 int fd;
379                 struct sockaddr_storage addr;
380                 int addrlen = sizeof(addr);
381
382                 /* close log file before the potentially very long select so
383                    file can be trimmed by another process instead of growing
384                    forever */
385                 log_close();
386
387                 FD_ZERO(&fds);
388                 FD_SET(s, &fds);
389
390                 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
391                         continue;
392                 }
393
394                 if(!FD_ISSET(s, &fds)) continue;
395
396                 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
397
398                 if (fd == -1) continue;
399
400                 signal(SIGCHLD, SIG_IGN);
401
402                 /* we shouldn't have any children left hanging around
403                    but I have had reports that on Digital Unix zombies
404                    are produced, so this ensures that they are reaped */
405 #ifdef WNOHANG
406                 while (waitpid(-1, NULL, WNOHANG) > 0);
407 #endif
408
409                 if (fork()==0) {
410                         close(s);
411                         /* open log file in child before possibly giving
412                            up privileges  */
413                         log_open();
414                         _exit(fn(fd));
415                 }
416
417                 close(fd);
418         }
419 }
420
421
422 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
423
424 struct
425 {
426   char *name;
427   int level;
428   int option;
429   int value;
430   int opttype;
431 } socket_options[] = {
432   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
433   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
434   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
435 #ifdef TCP_NODELAY
436   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
437 #endif
438 #ifdef IPTOS_LOWDELAY
439   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
440 #endif
441 #ifdef IPTOS_THROUGHPUT
442   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
443 #endif
444 #ifdef SO_SNDBUF
445   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
446 #endif
447 #ifdef SO_RCVBUF
448   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
449 #endif
450 #ifdef SO_SNDLOWAT
451   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
452 #endif
453 #ifdef SO_RCVLOWAT
454   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
455 #endif
456 #ifdef SO_SNDTIMEO
457   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
458 #endif
459 #ifdef SO_RCVTIMEO
460   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
461 #endif
462   {NULL,0,0,0,0}};
463
464         
465
466 /****************************************************************************
467 set user socket options
468 ****************************************************************************/
469 void set_socket_options(int fd, char *options)
470 {
471         char *tok;
472         if (!options || !*options) return;
473
474         options = strdup(options);
475         
476         if (!options) out_of_memory("set_socket_options");
477
478         for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
479                 int ret=0,i;
480                 int value = 1;
481                 char *p;
482                 int got_value = 0;
483
484                 if ((p = strchr(tok,'='))) {
485                         *p = 0;
486                         value = atoi(p+1);
487                         got_value = 1;
488                 }
489
490                 for (i=0;socket_options[i].name;i++)
491                         if (strcmp(socket_options[i].name,tok)==0)
492                                 break;
493
494                 if (!socket_options[i].name) {
495                         rprintf(FERROR,"Unknown socket option %s\n",tok);
496                         continue;
497                 }
498
499                 switch (socket_options[i].opttype) {
500                 case OPT_BOOL:
501                 case OPT_INT:
502                         ret = setsockopt(fd,socket_options[i].level,
503                                          socket_options[i].option,(char *)&value,sizeof(int));
504                         break;
505                         
506                 case OPT_ON:
507                         if (got_value)
508                                 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
509
510                         {
511                                 int on = socket_options[i].value;
512                                 ret = setsockopt(fd,socket_options[i].level,
513                                                  socket_options[i].option,(char *)&on,sizeof(int));
514                         }
515                         break;    
516                 }
517                 
518                 if (ret != 0)
519                         rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
520                                 strerror(errno));
521         }
522
523         free(options);
524 }
525
526 /****************************************************************************
527 become a daemon, discarding the controlling terminal
528 ****************************************************************************/
529 void become_daemon(void)
530 {
531         int i;
532
533         if (fork()) {
534                 _exit(0);
535         }
536
537         /* detach from the terminal */
538 #ifdef HAVE_SETSID
539         setsid();
540 #else
541 #ifdef TIOCNOTTY
542         i = open("/dev/tty", O_RDWR);
543         if (i >= 0) {
544                 ioctl(i, (int) TIOCNOTTY, (char *)0);      
545                 close(i);
546         }
547 #endif /* TIOCNOTTY */
548 #endif
549         /* make sure that stdin, stdout an stderr don't stuff things
550            up (library functions, for example) */
551         for (i=0;i<3;i++) {
552                 close(i); 
553                 open("/dev/null", O_RDWR);
554         }
555 }
556
557 /**
558  * Return the IP addr of the client as a string 
559  **/
560 char *client_addr(int fd)
561 {
562         struct sockaddr_storage ss;
563         int     length = sizeof(ss);
564         static char addr_buf[100];
565         static int initialised;
566
567         if (initialised) return addr_buf;
568
569         initialised = 1;
570
571         if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
572                 exit_cleanup(RERR_SOCKETIO);
573         }
574
575         getnameinfo((struct sockaddr *)&ss, length,
576                 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
577         return addr_buf;
578 }
579
580
581 static sa_family_t get_sockaddr_family(const struct sockaddr_storage *ss)
582 {
583         return ((struct sockaddr *) ss)->sa_family;
584 }
585
586
587 /**
588  * Return the DNS name of the client 
589  **/
590 char *client_name(int fd)
591 {
592         struct sockaddr_storage ss;
593         int     length = sizeof(ss);
594         static char name_buf[100];
595         static char port_buf[100];
596         char *def = "UNKNOWN";
597         static int initialised;
598         struct addrinfo hints, *res, *res0;
599         int error;
600
601         if (initialised) return name_buf;
602
603         initialised = 1;
604
605         strcpy(name_buf,def);
606
607         if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
608                 /* FIXME: Can we really not continue? */
609                 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
610                         fd, strerror(errno));
611                 exit_cleanup(RERR_SOCKETIO);
612         }
613
614 #ifdef INET6
615         if (get_sockaddr_family(&ss) == AF_INET6 && 
616             IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
617                 struct sockaddr_in6 sin6;
618                 struct sockaddr_in *sin;
619
620                 memcpy(&sin6, &ss, sizeof(sin6));
621                 sin = (struct sockaddr_in *)&ss;
622                 memset(sin, 0, sizeof(*sin));
623                 sin->sin_family = AF_INET;
624                 length = sizeof(struct sockaddr_in);
625 #ifdef HAVE_SOCKADDR_LEN
626                 sin->sin_len = length;
627 #endif
628                 sin->sin_port = sin6.sin6_port;
629                 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
630                         sizeof(sin->sin_addr));
631         }
632 #endif
633
634         /* reverse lookup */
635         if (getnameinfo((struct sockaddr *)&ss, length,
636                         name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
637                         NI_NAMEREQD | NI_NUMERICSERV) != 0) {
638                 strcpy(name_buf, def);
639                 rprintf(FERROR, "reverse name lookup failed\n");
640         }
641
642         /* forward lookup */
643         memset(&hints, 0, sizeof(hints));
644         hints.ai_family = PF_UNSPEC;
645         hints.ai_flags = AI_CANONNAME;
646         hints.ai_socktype = SOCK_STREAM;
647         error = getaddrinfo(name_buf, port_buf, &hints, &res0);
648         if (error) {
649                 strcpy(name_buf, def);
650                 rprintf(FERROR,
651                         RSYNC_NAME ": forward name lookup for %s failed: %s\n",
652                         port_buf,
653                         gai_strerror(error));
654                 return name_buf;
655         }
656
657         /* XXX sin6_flowinfo and other fields */
658         for (res = res0; res; res = res->ai_next) {
659                 if (res->ai_family != get_sockaddr_family(&ss))
660                         continue;
661                 if (res->ai_addrlen != length)
662                         continue;
663                 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
664                         break;
665         }
666
667         /* TODO: Do a  forward lookup as well to prevent spoofing */
668
669         if (res == NULL) {
670                 strcpy(name_buf, def);
671                 rprintf(FERROR, RSYNC_NAME ": "
672                         "reverse name lookup mismatch on fd%d - spoofed address?\n",
673                         fd);
674         }
675
676         freeaddrinfo(res0);
677         return name_buf;
678 }
679
680
681 /*******************************************************************
682 this is like socketpair but uses tcp. It is used by the Samba
683 regression test code
684 The function guarantees that nobody else can attach to the socket,
685 or if they do that this function fails and the socket gets closed
686 returns 0 on success, -1 on failure
687 the resulting file descriptors are symmetrical
688  ******************************************************************/
689 static int socketpair_tcp(int fd[2])
690 {
691         int listener;
692         struct sockaddr_in sock;
693         struct sockaddr_in sock2;
694         socklen_t socklen = sizeof(sock);
695         int connect_done = 0;
696         
697         fd[0] = fd[1] = listener = -1;
698
699         memset(&sock, 0, sizeof(sock));
700         
701         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
702
703         memset(&sock2, 0, sizeof(sock2));
704 #ifdef HAVE_SOCK_SIN_LEN
705         sock2.sin_len = sizeof(sock2);
706 #endif
707         sock2.sin_family = PF_INET;
708
709         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
710
711         if (listen(listener, 1) != 0) goto failed;
712
713         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
714
715         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
716
717         set_nonblocking(fd[1]);
718
719         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
720
721         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
722                 if (errno != EINPROGRESS) goto failed;
723         } else {
724                 connect_done = 1;
725         }
726
727         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
728
729         close(listener);
730         if (connect_done == 0) {
731                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
732                     && errno != EISCONN) goto failed;
733         }
734
735         set_blocking (fd[1]);
736
737         /* all OK! */
738         return 0;
739
740  failed:
741         if (fd[0] != -1) close(fd[0]);
742         if (fd[1] != -1) close(fd[1]);
743         if (listener != -1) close(listener);
744         return -1;
745 }
746
747
748 /*******************************************************************
749 run a program on a local tcp socket, this is used to launch smbd
750 when regression testing
751 the return value is a socket which is attached to a subprocess
752 running "prog". stdin and stdout are attached. stderr is left
753 attached to the original stderr
754  ******************************************************************/
755 int sock_exec(const char *prog)
756 {
757         int fd[2];
758         if (socketpair_tcp(fd) != 0) {
759                 rprintf (FERROR, RSYNC_NAME
760                          ": socketpair_tcp failed (%s)\n",
761                          strerror(errno));
762                 return -1;
763         }
764         if (fork() == 0) {
765                 close(fd[0]);
766                 close(0);
767                 close(1);
768                 dup(fd[1]);
769                 dup(fd[1]);
770                 if (verbose > 3)
771                         fprintf (stderr,
772                                  RSYNC_NAME ": execute socket program \"%s\"\n",
773                                  prog);
774                 exit (system (prog));
775         }
776         close (fd[1]);
777         return fd[0];
778 }
779
780
781