1 /* -*- c-file-style: "linux" -*-
3 rsync -- fast file replication program
5 Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
6 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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.
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.
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.
26 * Socket functions used in rsync.
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.
38 * Establish a proxy connection on an open socket to a web proxy by
39 * using the HTTP CONNECT method.
41 static int establish_proxy_connection(int fd
, char *host
, int port
)
46 snprintf(buffer
, sizeof(buffer
), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host
, port
);
47 if (write(fd
, buffer
, strlen(buffer
)) != (int) strlen(buffer
)) {
48 rprintf(FERROR
, "failed to write to proxy: %s\n",
53 for (cp
= buffer
; cp
< &buffer
[sizeof(buffer
) - 1]; cp
++) {
54 if (read(fd
, cp
, 1) != 1) {
55 rprintf(FERROR
, "failed to read from proxy: %s\n",
68 if (strncmp(buffer
, "HTTP/", 5) != 0) {
69 rprintf(FERROR
, "bad response from proxy - %s\n",
73 for (cp
= &buffer
[5]; isdigit(* (unsigned char *) cp
) || (*cp
== '.'); cp
++)
78 rprintf(FERROR
, "bad response from proxy - %s\n",
82 /* throw away the rest of the HTTP header */
84 for (cp
= buffer
; cp
< &buffer
[sizeof(buffer
) - 1];
86 if (read(fd
, cp
, 1) != 1) {
87 rprintf(FERROR
, "failed to read from proxy: %s\n",
94 if ((cp
> buffer
) && (*cp
== '\n'))
96 if ((cp
== buffer
) && ((*cp
== '\n') || (*cp
== '\r')))
104 * Try to set the local address for a newly-created socket. Return -1
107 int try_bind_local(int s
,
108 int ai_family
, int ai_socktype
,
109 const char *bind_address
)
112 struct addrinfo bhints
, *bres_all
, *r
;
114 memset(&bhints
, 0, sizeof(bhints
));
115 bhints
.ai_family
= ai_family
;
116 bhints
.ai_socktype
= ai_socktype
;
117 bhints
.ai_flags
= AI_PASSIVE
;
118 if ((error
= getaddrinfo(bind_address
, NULL
, &bhints
, &bres_all
))) {
119 rprintf(FERROR
, RSYNC_NAME
": getaddrinfo %s: %s\n",
120 bind_address
, gai_strerror(error
));
124 for (r
= bres_all
; r
; r
= r
->ai_next
) {
125 if (bind(s
, r
->ai_addr
, r
->ai_addrlen
) == -1)
127 freeaddrinfo(bres_all
);
131 /* no error message; there might be some problem that allows
132 * creation of the socket but not binding, perhaps if the
133 * machine has no ipv6 address of this name. */
134 freeaddrinfo(bres_all
);
140 * Open a socket to a tcp remote host with the specified port .
142 * Based on code from Warren. Proxy support by Stephen Rothwell.
143 * getaddrinfo() rewrite contributed by KAME.net.
145 * Now that we support IPv6 we need to look up the remote machine's
146 * address first, using @p af_hint to set a preference for the type
147 * of address. Then depending on whether it has v4 or v6 addresses we
148 * try to open a connection.
150 * The loop allows for machines with some addresses which may not be
151 * reachable, perhaps because we can't e.g. route ipv6 to that network
152 * but we can get ip4 packets through.
154 * @param bind_address Local address to use. Normally NULL to bind
155 * the wildcard address.
157 * @param af_hint Address family, e.g. AF_INET or AF_INET6.
159 int open_socket_out(char *host
, int port
, const char *bind_address
,
162 int type
= SOCK_STREAM
;
165 struct addrinfo hints
, *res0
, *res
;
172 /* if we have a RSYNC_PROXY env variable then redirect our
173 * connetcion via a web proxy at the given address. The format
174 * is hostname:port */
175 h
= getenv("RSYNC_PROXY");
176 proxied
= (h
!= NULL
) && (*h
!= '\0');
179 strlcpy(buffer
, h
, sizeof(buffer
));
180 cp
= strchr(buffer
, ':');
183 "invalid proxy specification: should be HOST:PORT\n");
190 rprintf(FINFO
, "connection via http proxy %s port %s\n",
194 snprintf(portbuf
, sizeof(portbuf
), "%d", port
);
198 memset(&hints
, 0, sizeof(hints
));
199 hints
.ai_family
= af_hint
;
200 hints
.ai_socktype
= type
;
201 error
= getaddrinfo(h
, portbuf
, &hints
, &res0
);
203 rprintf(FERROR
, RSYNC_NAME
": getaddrinfo: %s %s: %s\n",
204 h
, portbuf
, gai_strerror(error
));
209 /* Try to connect to all addresses for this machine until we get
210 * through. It might e.g. be multi-homed, or have both IPv4 and IPv6
211 * addresses. We need to create a socket for each record, since the
212 * address record tells us what protocol to use to try to connect. */
213 for (res
= res0
; res
; res
= res
->ai_next
) {
214 s
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
219 if (try_bind_local(s
, res
->ai_family
, type
,
220 bind_address
) == -1) {
226 if (connect(s
, res
->ai_addr
, res
->ai_addrlen
) < 0) {
232 establish_proxy_connection(s
, host
, port
) != 0) {
241 rprintf(FERROR
, RSYNC_NAME
": failed to connect to %s: %s\n",
250 * Open an outgoing socket, but allow for it to be intercepted by
251 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
252 * socketpair rather than really opening a socket.
254 * We use this primarily in testing to detect TCP flow bugs, but not
255 * cause security problems by really opening remote connections.
257 * This is based on the Samba LIBSMB_PROG feature.
259 * @param bind_address Local address to use. Normally NULL to get the stack default.
261 int open_socket_out_wrapped (char *host
,
263 const char *bind_address
,
268 if ((prog
= getenv ("RSYNC_CONNECT_PROG")) != NULL
)
269 return sock_exec (prog
);
271 return open_socket_out (host
, port
, bind_address
,
278 * Open a socket of the specified type, port and address for incoming data
280 * Try to be better about handling the results of getaddrinfo(): when
281 * opening an inbound socket, we might get several address results,
282 * e.g. for the machine's ipv4 and ipv6 name.
284 * If binding a wildcard, then any one of them should do. If an address
285 * was specified but it's insufficiently specific then that's not our
288 * However, some of the advertized addresses may not work because e.g. we
289 * don't have IPv6 support in the kernel. In that case go on and try all
290 * addresses until one succeeds.
292 * @param bind_address Local address to bind, or NULL to allow it to
295 static int open_socket_in(int type
, int port
, const char *bind_address
,
300 struct addrinfo hints
, *all_ai
, *resp
;
304 memset(&hints
, 0, sizeof(hints
));
305 hints
.ai_family
= af_hint
;
306 hints
.ai_socktype
= type
;
307 hints
.ai_flags
= AI_PASSIVE
;
308 snprintf(portbuf
, sizeof(portbuf
), "%d", port
);
309 error
= getaddrinfo(bind_address
, portbuf
, &hints
, &all_ai
);
311 rprintf(FERROR
, RSYNC_NAME
": getaddrinfo: bind address %s: %s\n",
312 bind_address
, gai_strerror(error
));
316 /* We may not be able to create the socket, if for example the
317 * machine knows about IPv6 in the C library, but not in the
319 for (resp
= all_ai
; resp
; resp
= resp
->ai_next
) {
320 s
= socket(resp
->ai_family
, resp
->ai_socktype
,
324 /* See if there's another address that will work... */
327 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
328 (char *)&one
, sizeof one
);
330 /* now we've got a socket - we need to bind it */
331 if (bind(s
, all_ai
->ai_addr
, all_ai
->ai_addrlen
) < 0) {
332 /* Nope, try another */
337 freeaddrinfo(all_ai
);
341 rprintf(FERROR
, RSYNC_NAME
": open inbound socket on port %d failed: "
346 freeaddrinfo(all_ai
);
352 * Determine if a file descriptor is in fact a socket
354 int is_a_socket(int fd
)
360 /* Parameters to getsockopt, setsockopt etc are very
361 * unstandardized across platforms, so don't be surprised if
362 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
363 * It seems they all eventually get the right idea.
365 * Debian says: ``The fifth argument of getsockopt and
366 * setsockopt is in reality an int [*] (and this is what BSD
367 * 4.* and libc4 and libc5 have). Some POSIX confusion
368 * resulted in the present socklen_t. The draft standard has
369 * not been adopted yet, but glibc2 already follows it and
370 * also has socklen_t [*]. See also accept(2).''
372 * We now return to your regularly scheduled programming. */
373 return(getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, (char *)&v
, &l
) == 0);
377 static RETSIGTYPE
sigchld_handler(UNUSED(int val
))
379 signal(SIGCHLD
, sigchld_handler
);
381 while (waitpid(-1, NULL
, WNOHANG
) > 0) {}
386 void start_accept_loop(int port
, int (*fn
)(int, int))
389 extern char *bind_address
;
390 extern int default_af_hint
;
392 /* open an incoming socket */
393 s
= open_socket_in(SOCK_STREAM
, port
, bind_address
, default_af_hint
);
395 exit_cleanup(RERR_SOCKETIO
);
397 /* ready to listen */
398 if (listen(s
, 5) == -1) {
400 exit_cleanup(RERR_SOCKETIO
);
404 /* now accept incoming connections - forking a new process
405 for each incoming connection */
410 struct sockaddr_storage addr
;
411 socklen_t addrlen
= sizeof addr
;
413 /* close log file before the potentially very long select so
414 file can be trimmed by another process instead of growing
421 if (select(s
+1, &fds
, NULL
, NULL
, NULL
) != 1) {
425 if(!FD_ISSET(s
, &fds
)) continue;
427 fd
= accept(s
,(struct sockaddr
*)&addr
,&addrlen
);
429 if (fd
== -1) continue;
431 signal(SIGCHLD
, sigchld_handler
);
433 if ((pid
= fork()) == 0) {
436 /* open log file in child before possibly giving
442 } else if (pid
< 0) {
445 ": could not create child server process: %s\n",
448 /* This might have happened because we're
449 * overloaded. Sleep briefly before trying to
453 /* Parent doesn't need this fd anymore. */
460 enum SOCK_OPT_TYPES
{OPT_BOOL
,OPT_INT
,OPT_ON
};
469 } socket_options
[] = {
470 {"SO_KEEPALIVE", SOL_SOCKET
, SO_KEEPALIVE
, 0, OPT_BOOL
},
471 {"SO_REUSEADDR", SOL_SOCKET
, SO_REUSEADDR
, 0, OPT_BOOL
},
472 {"SO_BROADCAST", SOL_SOCKET
, SO_BROADCAST
, 0, OPT_BOOL
},
474 {"TCP_NODELAY", IPPROTO_TCP
, TCP_NODELAY
, 0, OPT_BOOL
},
476 #ifdef IPTOS_LOWDELAY
477 {"IPTOS_LOWDELAY", IPPROTO_IP
, IP_TOS
, IPTOS_LOWDELAY
, OPT_ON
},
479 #ifdef IPTOS_THROUGHPUT
480 {"IPTOS_THROUGHPUT", IPPROTO_IP
, IP_TOS
, IPTOS_THROUGHPUT
, OPT_ON
},
483 {"SO_SNDBUF", SOL_SOCKET
, SO_SNDBUF
, 0, OPT_INT
},
486 {"SO_RCVBUF", SOL_SOCKET
, SO_RCVBUF
, 0, OPT_INT
},
489 {"SO_SNDLOWAT", SOL_SOCKET
, SO_SNDLOWAT
, 0, OPT_INT
},
492 {"SO_RCVLOWAT", SOL_SOCKET
, SO_RCVLOWAT
, 0, OPT_INT
},
495 {"SO_SNDTIMEO", SOL_SOCKET
, SO_SNDTIMEO
, 0, OPT_INT
},
498 {"SO_RCVTIMEO", SOL_SOCKET
, SO_RCVTIMEO
, 0, OPT_INT
},
505 * Set user socket options
507 void set_socket_options(int fd
, char *options
)
510 if (!options
|| !*options
) return;
512 options
= strdup(options
);
514 if (!options
) out_of_memory("set_socket_options");
516 for (tok
=strtok(options
, " \t,"); tok
; tok
=strtok(NULL
," \t,")) {
522 if ((p
= strchr(tok
,'='))) {
528 for (i
=0;socket_options
[i
].name
;i
++)
529 if (strcmp(socket_options
[i
].name
,tok
)==0)
532 if (!socket_options
[i
].name
) {
533 rprintf(FERROR
,"Unknown socket option %s\n",tok
);
537 switch (socket_options
[i
].opttype
) {
540 ret
= setsockopt(fd
,socket_options
[i
].level
,
541 socket_options
[i
].option
,(char *)&value
,sizeof(int));
546 rprintf(FERROR
,"syntax error - %s does not take a value\n",tok
);
549 int on
= socket_options
[i
].value
;
550 ret
= setsockopt(fd
,socket_options
[i
].level
,
551 socket_options
[i
].option
,(char *)&on
,sizeof(int));
557 rprintf(FERROR
, "failed to set socket option %s: %s\n", tok
,
565 * Become a daemon, discarding the controlling terminal
567 void become_daemon(void)
575 /* detach from the terminal */
580 i
= open("/dev/tty", O_RDWR
);
582 ioctl(i
, (int) TIOCNOTTY
, (char *)0);
585 #endif /* TIOCNOTTY */
587 /* make sure that stdin, stdout an stderr don't stuff things
588 up (library functions, for example) */
591 open("/dev/null", O_RDWR
);
597 * This is like socketpair but uses tcp. It is used by the Samba
598 * regression test code.
600 * The function guarantees that nobody else can attach to the socket,
601 * or if they do that this function fails and the socket gets closed
602 * returns 0 on success, -1 on failure the resulting file descriptors
605 static int socketpair_tcp(int fd
[2])
608 struct sockaddr_in sock
;
609 struct sockaddr_in sock2
;
610 socklen_t socklen
= sizeof(sock
);
611 int connect_done
= 0;
613 fd
[0] = fd
[1] = listener
= -1;
615 memset(&sock
, 0, sizeof(sock
));
617 if ((listener
= socket(PF_INET
, SOCK_STREAM
, 0)) == -1) goto failed
;
619 memset(&sock2
, 0, sizeof(sock2
));
620 #ifdef HAVE_SOCKADDR_LEN
621 sock2
.sin_len
= sizeof(sock2
);
623 sock2
.sin_family
= PF_INET
;
625 bind(listener
, (struct sockaddr
*)&sock2
, sizeof(sock2
));
627 if (listen(listener
, 1) != 0) goto failed
;
629 if (getsockname(listener
, (struct sockaddr
*)&sock
, &socklen
) != 0) goto failed
;
631 if ((fd
[1] = socket(PF_INET
, SOCK_STREAM
, 0)) == -1) goto failed
;
633 set_nonblocking(fd
[1]);
635 sock
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
637 if (connect(fd
[1],(struct sockaddr
*)&sock
,sizeof(sock
)) == -1) {
638 if (errno
!= EINPROGRESS
) goto failed
;
643 if ((fd
[0] = accept(listener
, (struct sockaddr
*)&sock
, &socklen
)) == -1) goto failed
;
646 if (connect_done
== 0) {
647 if (connect(fd
[1],(struct sockaddr
*)&sock
,sizeof(sock
)) != 0
648 && errno
!= EISCONN
) goto failed
;
651 set_blocking (fd
[1]);
657 if (fd
[0] != -1) close(fd
[0]);
658 if (fd
[1] != -1) close(fd
[1]);
659 if (listener
!= -1) close(listener
);
666 * Run a program on a local tcp socket, so that we can talk to it's
667 * stdin and stdout. This is used to fake a connection to a daemon
668 * for testing -- not for the normal case of running SSH.
670 * @return a socket which is attached to a subprocess running
671 * "prog". stdin and stdout are attached. stderr is left attached to
672 * the original stderr
674 int sock_exec(const char *prog
)
678 if (socketpair_tcp(fd
) != 0) {
679 rprintf (FERROR
, RSYNC_NAME
680 ": socketpair_tcp failed (%s)\n",
691 /* Can't use rprintf because we've forked. */
693 RSYNC_NAME
": execute socket program \"%s\"\n",
696 exit (system (prog
));