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