Note rsyncd-over-ssh and documentation TODOs.
[rsync/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                         case EINVAL:
302                                 /* See if there's another address that will work... */
303                                 continue;
304                         }
305                 }
306                 
307                 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
308                         "(dom=%d, type=%d, proto=%d) failed: %s\n",
309                         resp->ai_family, resp->ai_socktype, resp->ai_protocol,
310                         strerror(errno));
311                         goto fail;
312         }
313
314         setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
315
316         /* now we've got a socket - we need to bind it */
317         if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { 
318                 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
319                 close(s);
320                 goto fail;
321         }
322
323         return s;
324
325 fail:
326         freeaddrinfo(res);
327         return -1; 
328 }
329
330
331 /*
332  * Determine if a file descriptor is in fact a socket
333  */
334 int is_a_socket(int fd)
335 {
336         int v;
337         socklen_t l;
338         l = sizeof(int);
339
340         /* Parameters to getsockopt, setsockopt etc are very
341          * unstandardized across platforms, so don't be surprised if
342          * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
343          * It seems they all eventually get the right idea.
344          *
345          * Debian says: ``The fifth argument of getsockopt and
346          * setsockopt is in reality an int [*] (and this is what BSD
347          * 4.* and libc4 and libc5 have).  Some POSIX confusion
348          * resulted in the present socklen_t.  The draft standard has
349          * not been adopted yet, but glibc2 already follows it and
350          * also has socklen_t [*]. See also accept(2).''
351          *
352          * We now return to your regularly scheduled programming.  */
353         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
354 }
355
356
357 void start_accept_loop(int port, int (*fn)(int ))
358 {
359         int s;
360         extern char *bind_address;
361
362         /* open an incoming socket */
363         s = open_socket_in(SOCK_STREAM, port, bind_address,
364                            global_opts.af_hint);
365         if (s == -1)
366                 exit_cleanup(RERR_SOCKETIO);
367
368         /* ready to listen */
369         if (listen(s, 5) == -1) {
370                 close(s);
371                 exit_cleanup(RERR_SOCKETIO);
372         }
373
374
375         /* now accept incoming connections - forking a new process
376            for each incoming connection */
377         while (1) {
378                 fd_set fds;
379                 int fd;
380                 struct sockaddr_storage addr;
381                 int addrlen = sizeof(addr);
382
383                 /* close log file before the potentially very long select so
384                    file can be trimmed by another process instead of growing
385                    forever */
386                 log_close();
387
388                 FD_ZERO(&fds);
389                 FD_SET(s, &fds);
390
391                 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
392                         continue;
393                 }
394
395                 if(!FD_ISSET(s, &fds)) continue;
396
397                 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
398
399                 if (fd == -1) continue;
400
401                 signal(SIGCHLD, SIG_IGN);
402
403                 /* we shouldn't have any children left hanging around
404                    but I have had reports that on Digital Unix zombies
405                    are produced, so this ensures that they are reaped */
406 #ifdef WNOHANG
407                 while (waitpid(-1, NULL, WNOHANG) > 0);
408 #endif
409
410                 if (fork()==0) {
411                         close(s);
412                         /* open log file in child before possibly giving
413                            up privileges  */
414                         log_open();
415                         _exit(fn(fd));
416                 }
417
418                 close(fd);
419         }
420 }
421
422
423 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
424
425 struct
426 {
427   char *name;
428   int level;
429   int option;
430   int value;
431   int opttype;
432 } socket_options[] = {
433   {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
434   {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
435   {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
436 #ifdef TCP_NODELAY
437   {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
438 #endif
439 #ifdef IPTOS_LOWDELAY
440   {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
441 #endif
442 #ifdef IPTOS_THROUGHPUT
443   {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
444 #endif
445 #ifdef SO_SNDBUF
446   {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
447 #endif
448 #ifdef SO_RCVBUF
449   {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
450 #endif
451 #ifdef SO_SNDLOWAT
452   {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
453 #endif
454 #ifdef SO_RCVLOWAT
455   {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
456 #endif
457 #ifdef SO_SNDTIMEO
458   {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
459 #endif
460 #ifdef SO_RCVTIMEO
461   {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
462 #endif
463   {NULL,0,0,0,0}};
464
465         
466
467 /****************************************************************************
468 set user socket options
469 ****************************************************************************/
470 void set_socket_options(int fd, char *options)
471 {
472         char *tok;
473         if (!options || !*options) return;
474
475         options = strdup(options);
476         
477         if (!options) out_of_memory("set_socket_options");
478
479         for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
480                 int ret=0,i;
481                 int value = 1;
482                 char *p;
483                 int got_value = 0;
484
485                 if ((p = strchr(tok,'='))) {
486                         *p = 0;
487                         value = atoi(p+1);
488                         got_value = 1;
489                 }
490
491                 for (i=0;socket_options[i].name;i++)
492                         if (strcmp(socket_options[i].name,tok)==0)
493                                 break;
494
495                 if (!socket_options[i].name) {
496                         rprintf(FERROR,"Unknown socket option %s\n",tok);
497                         continue;
498                 }
499
500                 switch (socket_options[i].opttype) {
501                 case OPT_BOOL:
502                 case OPT_INT:
503                         ret = setsockopt(fd,socket_options[i].level,
504                                          socket_options[i].option,(char *)&value,sizeof(int));
505                         break;
506                         
507                 case OPT_ON:
508                         if (got_value)
509                                 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
510
511                         {
512                                 int on = socket_options[i].value;
513                                 ret = setsockopt(fd,socket_options[i].level,
514                                                  socket_options[i].option,(char *)&on,sizeof(int));
515                         }
516                         break;    
517                 }
518                 
519                 if (ret != 0)
520                         rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
521                                 strerror(errno));
522         }
523
524         free(options);
525 }
526
527 /****************************************************************************
528 become a daemon, discarding the controlling terminal
529 ****************************************************************************/
530 void become_daemon(void)
531 {
532         int i;
533
534         if (fork()) {
535                 _exit(0);
536         }
537
538         /* detach from the terminal */
539 #ifdef HAVE_SETSID
540         setsid();
541 #else
542 #ifdef TIOCNOTTY
543         i = open("/dev/tty", O_RDWR);
544         if (i >= 0) {
545                 ioctl(i, (int) TIOCNOTTY, (char *)0);      
546                 close(i);
547         }
548 #endif /* TIOCNOTTY */
549 #endif
550         /* make sure that stdin, stdout an stderr don't stuff things
551            up (library functions, for example) */
552         for (i=0;i<3;i++) {
553                 close(i); 
554                 open("/dev/null", O_RDWR);
555         }
556 }
557
558 /**
559  * Return the IP addr of the client as a string 
560  **/
561 char *client_addr(int fd)
562 {
563         struct sockaddr_storage ss;
564         int     length = sizeof(ss);
565         static char addr_buf[100];
566         static int initialised;
567
568         if (initialised) return addr_buf;
569
570         initialised = 1;
571
572         if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
573                 exit_cleanup(RERR_SOCKETIO);
574         }
575
576         getnameinfo((struct sockaddr *)&ss, length,
577                 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
578         return addr_buf;
579 }
580
581
582 static int get_sockaddr_family(const struct sockaddr_storage *ss)
583 {
584         return ((struct sockaddr *) ss)->sa_family;
585 }
586
587
588 /**
589  * Return the DNS name of the client 
590  **/
591 char *client_name(int fd)
592 {
593         struct sockaddr_storage ss;
594         int     length = sizeof(ss);
595         static char name_buf[100];
596         static char port_buf[100];
597         char *def = "UNKNOWN";
598         static int initialised;
599         struct addrinfo hints, *res, *res0;
600         int error;
601
602         if (initialised) return name_buf;
603
604         initialised = 1;
605
606         strcpy(name_buf,def);
607
608         if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
609                 /* FIXME: Can we really not continue? */
610                 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
611                         fd, strerror(errno));
612                 exit_cleanup(RERR_SOCKETIO);
613         }
614
615 #ifdef INET6
616         if (get_sockaddr_family(&ss) == AF_INET6 && 
617             IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
618                 struct sockaddr_in6 sin6;
619                 struct sockaddr_in *sin;
620
621                 memcpy(&sin6, &ss, sizeof(sin6));
622                 sin = (struct sockaddr_in *)&ss;
623                 memset(sin, 0, sizeof(*sin));
624                 sin->sin_family = AF_INET;
625                 length = sizeof(struct sockaddr_in);
626 #ifdef HAVE_SOCKADDR_LEN
627                 sin->sin_len = length;
628 #endif
629                 sin->sin_port = sin6.sin6_port;
630                 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
631                         sizeof(sin->sin_addr));
632         }
633 #endif
634
635         /* reverse lookup */
636         if (getnameinfo((struct sockaddr *)&ss, length,
637                         name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
638                         NI_NAMEREQD | NI_NUMERICSERV) != 0) {
639                 strcpy(name_buf, def);
640                 rprintf(FERROR, "reverse name lookup failed\n");
641         }
642
643         /* forward lookup */
644         memset(&hints, 0, sizeof(hints));
645         hints.ai_family = PF_UNSPEC;
646         hints.ai_flags = AI_CANONNAME;
647         hints.ai_socktype = SOCK_STREAM;
648         error = getaddrinfo(name_buf, port_buf, &hints, &res0);
649         if (error) {
650                 strcpy(name_buf, def);
651                 rprintf(FERROR,
652                         RSYNC_NAME ": forward name lookup for %s failed: %s\n",
653                         port_buf,
654                         gai_strerror(error));
655                 return name_buf;
656         }
657
658         /* XXX sin6_flowinfo and other fields */
659         for (res = res0; res; res = res->ai_next) {
660                 if (res->ai_family != get_sockaddr_family(&ss))
661                         continue;
662                 if (res->ai_addrlen != length)
663                         continue;
664                 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
665                         break;
666         }
667
668         /* TODO: Do a  forward lookup as well to prevent spoofing */
669
670         if (res == NULL) {
671                 strcpy(name_buf, def);
672                 rprintf(FERROR, RSYNC_NAME ": "
673                         "reverse name lookup mismatch on fd%d - spoofed address?\n",
674                         fd);
675         }
676
677         freeaddrinfo(res0);
678         return name_buf;
679 }
680
681
682 /*******************************************************************
683 this is like socketpair but uses tcp. It is used by the Samba
684 regression test code
685 The function guarantees that nobody else can attach to the socket,
686 or if they do that this function fails and the socket gets closed
687 returns 0 on success, -1 on failure
688 the resulting file descriptors are symmetrical
689  ******************************************************************/
690 static int socketpair_tcp(int fd[2])
691 {
692         int listener;
693         struct sockaddr_in sock;
694         struct sockaddr_in sock2;
695         socklen_t socklen = sizeof(sock);
696         int connect_done = 0;
697         
698         fd[0] = fd[1] = listener = -1;
699
700         memset(&sock, 0, sizeof(sock));
701         
702         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
703
704         memset(&sock2, 0, sizeof(sock2));
705 #ifdef HAVE_SOCK_SIN_LEN
706         sock2.sin_len = sizeof(sock2);
707 #endif
708         sock2.sin_family = PF_INET;
709
710         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
711
712         if (listen(listener, 1) != 0) goto failed;
713
714         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
715
716         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
717
718         set_nonblocking(fd[1]);
719
720         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
721
722         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
723                 if (errno != EINPROGRESS) goto failed;
724         } else {
725                 connect_done = 1;
726         }
727
728         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
729
730         close(listener);
731         if (connect_done == 0) {
732                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
733                     && errno != EISCONN) goto failed;
734         }
735
736         set_blocking (fd[1]);
737
738         /* all OK! */
739         return 0;
740
741  failed:
742         if (fd[0] != -1) close(fd[0]);
743         if (fd[1] != -1) close(fd[1]);
744         if (listener != -1) close(listener);
745         return -1;
746 }
747
748
749 /*******************************************************************
750 run a program on a local tcp socket, this is used to launch smbd
751 when regression testing
752 the return value is a socket which is attached to a subprocess
753 running "prog". stdin and stdout are attached. stderr is left
754 attached to the original stderr
755  ******************************************************************/
756 int sock_exec(const char *prog)
757 {
758         int fd[2];
759         if (socketpair_tcp(fd) != 0) {
760                 rprintf (FERROR, RSYNC_NAME
761                          ": socketpair_tcp failed (%s)\n",
762                          strerror(errno));
763                 return -1;
764         }
765         if (fork() == 0) {
766                 close(fd[0]);
767                 close(0);
768                 close(1);
769                 dup(fd[1]);
770                 dup(fd[1]);
771                 if (verbose > 3)
772                         fprintf (stderr,
773                                  RSYNC_NAME ": execute socket program \"%s\"\n",
774                                  prog);
775                 exit (system (prog));
776         }
777         close (fd[1]);
778         return fd[0];
779 }
780
781
782