2c2191e1340dab5d616a5e65ff82a24beab52b6e
[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                                 /* 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 /**
582  * Return the DNS name of the client 
583  **/
584 char *client_name(int fd)
585 {
586         struct sockaddr_storage ss;
587         int     length = sizeof(ss);
588         static char name_buf[100];
589         static char port_buf[100];
590         char *def = "UNKNOWN";
591         static int initialised;
592         struct addrinfo hints, *res, *res0;
593         int error;
594
595         if (initialised) return name_buf;
596
597         initialised = 1;
598
599         strcpy(name_buf,def);
600
601         if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
602                 /* FIXME: Can we really not continue? */
603                 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
604                         fd, strerror(errno));
605                 exit_cleanup(RERR_SOCKETIO);
606         }
607
608 #ifdef INET6
609         if (ss.ss_family == AF_INET6 && 
610             IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
611                 struct sockaddr_in6 sin6;
612                 struct sockaddr_in *sin;
613
614                 memcpy(&sin6, &ss, sizeof(sin6));
615                 sin = (struct sockaddr_in *)&ss;
616                 memset(sin, 0, sizeof(*sin));
617                 sin->sin_family = AF_INET;
618                 length = sizeof(struct sockaddr_in);
619 #ifdef HAVE_SOCKADDR_LEN
620                 sin->sin_len = length;
621 #endif
622                 sin->sin_port = sin6.sin6_port;
623                 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
624                         sizeof(sin->sin_addr));
625         }
626 #endif
627
628         /* reverse lookup */
629         if (getnameinfo((struct sockaddr *)&ss, length,
630                         name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
631                         NI_NAMEREQD | NI_NUMERICSERV) != 0) {
632                 strcpy(name_buf, def);
633                 rprintf(FERROR, "reverse name lookup failed\n");
634         }
635
636         /* forward lookup */
637         memset(&hints, 0, sizeof(hints));
638         hints.ai_family = PF_UNSPEC;
639         hints.ai_flags = AI_CANONNAME;
640         hints.ai_socktype = SOCK_STREAM;
641         error = getaddrinfo(name_buf, port_buf, &hints, &res0);
642         if (error) {
643                 strcpy(name_buf, def);
644                 rprintf(FERROR,
645                         RSYNC_NAME ": forward name lookup for %s failed: %s\n",
646                         port_buf,
647                         gai_strerror(error));
648                 return name_buf;
649         }
650
651         /* XXX sin6_flowinfo and other fields */
652         for (res = res0; res; res = res->ai_next) {
653                 if (res->ai_family != ss.ss_family)
654                         continue;
655                 if (res->ai_addrlen != length)
656                         continue;
657                 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
658                         break;
659         }
660
661         /* TODO: Do a  forward lookup as well to prevent spoofing */
662
663         if (res == NULL) {
664                 strcpy(name_buf, def);
665                 rprintf(FERROR, RSYNC_NAME ": "
666                         "reverse name lookup mismatch on fd%d - spoofed address?\n",
667                         fd);
668         }
669
670         freeaddrinfo(res0);
671         return name_buf;
672 }
673
674
675 /*******************************************************************
676 this is like socketpair but uses tcp. It is used by the Samba
677 regression test code
678 The function guarantees that nobody else can attach to the socket,
679 or if they do that this function fails and the socket gets closed
680 returns 0 on success, -1 on failure
681 the resulting file descriptors are symmetrical
682  ******************************************************************/
683 static int socketpair_tcp(int fd[2])
684 {
685         int listener;
686         struct sockaddr_in sock;
687         struct sockaddr_in sock2;
688         socklen_t socklen = sizeof(sock);
689         int connect_done = 0;
690         
691         fd[0] = fd[1] = listener = -1;
692
693         memset(&sock, 0, sizeof(sock));
694         
695         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
696
697         memset(&sock2, 0, sizeof(sock2));
698 #ifdef HAVE_SOCK_SIN_LEN
699         sock2.sin_len = sizeof(sock2);
700 #endif
701         sock2.sin_family = PF_INET;
702
703         bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
704
705         if (listen(listener, 1) != 0) goto failed;
706
707         if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
708
709         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
710
711         set_nonblocking(fd[1]);
712
713         sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
714
715         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
716                 if (errno != EINPROGRESS) goto failed;
717         } else {
718                 connect_done = 1;
719         }
720
721         if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
722
723         close(listener);
724         if (connect_done == 0) {
725                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
726                     && errno != EISCONN) goto failed;
727         }
728
729         set_blocking (fd[1]);
730
731         /* all OK! */
732         return 0;
733
734  failed:
735         if (fd[0] != -1) close(fd[0]);
736         if (fd[1] != -1) close(fd[1]);
737         if (listener != -1) close(listener);
738         return -1;
739 }
740
741
742 /*******************************************************************
743 run a program on a local tcp socket, this is used to launch smbd
744 when regression testing
745 the return value is a socket which is attached to a subprocess
746 running "prog". stdin and stdout are attached. stderr is left
747 attached to the original stderr
748  ******************************************************************/
749 int sock_exec(const char *prog)
750 {
751         int fd[2];
752         if (socketpair_tcp(fd) != 0) {
753                 rprintf (FERROR, RSYNC_NAME
754                          ": socketpair_tcp failed (%s)\n",
755                          strerror(errno));
756                 return -1;
757         }
758         if (fork() == 0) {
759                 close(fd[0]);
760                 close(0);
761                 close(1);
762                 dup(fd[1]);
763                 dup(fd[1]);
764                 if (verbose > 3)
765                         fprintf (stderr,
766                                  RSYNC_NAME ": execute socket program \"%s\"\n",
767                                  prog);
768                 exit (system (prog));
769         }
770         close (fd[1]);
771         return fd[0];
772 }
773
774
775