1 /* -*- c-file-style: "linux" -*-
3 Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
4 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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.
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.
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.
24 * Socket functions used in rsync.
29 #ifndef HAVE_GETADDRINFO
30 #include "lib/addrinfo.h"
33 /* Establish a proxy connection on an open socket to a web roxy by
34 * using the CONNECT method. */
35 static int establish_proxy_connection(int fd, char *host, int port)
40 snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
41 if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
42 rprintf(FERROR, "failed to write to proxy: %s\n",
47 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
48 if (read(fd, cp, 1) != 1) {
49 rprintf(FERROR, "failed to read from proxy: %s\n",
62 if (strncmp(buffer, "HTTP/", 5) != 0) {
63 rprintf(FERROR, "bad response from proxy - %s\n",
67 for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
72 rprintf(FERROR, "bad response from proxy - %s\n",
76 /* throw away the rest of the HTTP header */
78 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
80 if (read(fd, cp, 1) != 1) {
81 rprintf(FERROR, "failed to read from proxy: %s\n",
88 if ((cp > buffer) && (*cp == '\n'))
90 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
99 * Open a socket to a tcp remote host with the specified port .
101 * Based on code from Warren. Proxy support by Stephen Rothwell.
102 * getaddrinfo() rewrite contributed by KAME.net.
104 * Now that we support IPv6 we need to look up the remote machine's
105 * address first, using @p af_hint to set a preference for the type
106 * of address. Then depending on whether it has v4 or v6 addresses we
107 * try to open a connection.
109 * The loop allows for machines with some addresses which may not be
110 * reachable, perhaps because we can't e.g. route ipv6 to that network
111 * but we can get ip4 packets through.
113 * @param bind_address Local address to use. Normally NULL to bind
114 * the wildcard address.
116 * @param af_hint Address family, e.g. AF_INET or AF_INET6.
118 int open_socket_out(char *host, int port, const char *bind_address,
121 int type = SOCK_STREAM;
125 struct addrinfo hints, *res0, *res;
132 /* if we have a RSYNC_PROXY env variable then redirect our
133 * connetcion via a web proxy at the given address. The format
134 * is hostname:port */
135 h = getenv("RSYNC_PROXY");
136 proxied = (h != NULL) && (*h != '\0');
139 strlcpy(buffer, h, sizeof(buffer));
140 cp = strchr(buffer, ':');
143 "invalid proxy specification: should be HOST:PORT\n");
150 snprintf(portbuf, sizeof(portbuf), "%d", port);
154 memset(&hints, 0, sizeof(hints));
155 hints.ai_family = af_hint;
156 hints.ai_socktype = type;
157 error = getaddrinfo(h, portbuf, &hints, &res0);
159 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
160 h, portbuf, gai_strerror(error));
165 /* Try to connect to all addresses for this machine until we get
166 * through. It might e.g. be multi-homed, or have both IPv4 and IPv6
167 * addresses. We need to create a socket for each record, since the
168 * address record tells us what protocol to use to try to connect. */
169 for (res = res0; res; res = res->ai_next) {
170 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
175 struct addrinfo bhints, *bres;
177 memset(&bhints, 0, sizeof(bhints));
178 bhints.ai_family = res->ai_family;
179 bhints.ai_socktype = type;
180 bhints.ai_flags = AI_PASSIVE;
181 error = getaddrinfo(bind_address, NULL, &bhints, &bres);
183 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
184 "bind address %s <noport>: %s\n",
185 bind_address, gai_strerror(error));
189 /* I'm not at all sure that this is the right
190 * response here... -- mbp */
191 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
192 "bind address %s resolved to multiple hosts\n",
197 bind(s, bres->ai_addr, bres->ai_addrlen);
200 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
206 establish_proxy_connection(s, host, port) != 0) {
215 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
224 * Open an outgoing socket, but allow for it to be intercepted by
225 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
226 * socketpair rather than really opening a socket.
228 * We use this primarily in testing to detect TCP flow bugs, but not
229 * cause security problems by really opening remote connections.
231 * This is based on the Samba LIBSMB_PROG feature.
233 * @param bind_address Local address to use. Normally NULL to get the stack default.
235 int open_socket_out_wrapped (char *host,
237 const char *bind_address,
242 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
243 return sock_exec (prog);
245 return open_socket_out (host, port, bind_address,
252 * Open a socket of the specified type, port and address for incoming data
254 * Try to be better about handling the results of getaddrinfo(): when
255 * opening an inbound socket, we might get several address results,
256 * e.g. for the machine's ipv4 and ipv6 name.
258 * If binding a wildcard, then any one of them should do. If an address
259 * was specified but it's insufficiently specific then that's not our
262 * However, some of the advertized addresses may not work because e.g. we
263 * don't have IPv6 support in the kernel. In that case go on and try all
264 * addresses until one succeeds.
266 * @param bind_address Local address to bind, or NULL to allow it to
269 static int open_socket_in(int type, int port, const char *bind_address,
274 struct addrinfo hints, *res, *resp;
278 memset(&hints, 0, sizeof(hints));
279 hints.ai_family = af_hint;
280 hints.ai_socktype = type;
281 hints.ai_flags = AI_PASSIVE;
282 snprintf(portbuf, sizeof(portbuf), "%d", port);
283 error = getaddrinfo(bind_address, portbuf, &hints, &res);
285 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
286 bind_address, gai_strerror(error));
289 /* XXX: Do we need to care about getting multiple results
290 * back? I think probably not; if the user passed
291 * bind_address == NULL and we set AI_PASSIVE then we ought to
292 * get a wildcard result. */
296 s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
299 break; /* got a socket */
300 } else if ((resp = resp->ai_next)) {
302 case EPROTONOSUPPORT:
305 /* See if there's another address that will work... */
310 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
311 "(dom=%d, type=%d, proto=%d) failed: %s\n",
312 resp->ai_family, resp->ai_socktype, resp->ai_protocol,
317 setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
319 /* now we've got a socket - we need to bind it */
320 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
321 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
335 * Determine if a file descriptor is in fact a socket
337 int is_a_socket(int fd)
343 /* Parameters to getsockopt, setsockopt etc are very
344 * unstandardized across platforms, so don't be surprised if
345 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
346 * It seems they all eventually get the right idea.
348 * Debian says: ``The fifth argument of getsockopt and
349 * setsockopt is in reality an int [*] (and this is what BSD
350 * 4.* and libc4 and libc5 have). Some POSIX confusion
351 * resulted in the present socklen_t. The draft standard has
352 * not been adopted yet, but glibc2 already follows it and
353 * also has socklen_t [*]. See also accept(2).''
355 * We now return to your regularly scheduled programming. */
356 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
360 void start_accept_loop(int port, int (*fn)(int ))
363 extern char *bind_address;
365 /* open an incoming socket */
366 s = open_socket_in(SOCK_STREAM, port, bind_address,
367 global_opts.af_hint);
369 exit_cleanup(RERR_SOCKETIO);
371 /* ready to listen */
372 if (listen(s, 5) == -1) {
374 exit_cleanup(RERR_SOCKETIO);
378 /* now accept incoming connections - forking a new process
379 for each incoming connection */
383 struct sockaddr_storage addr;
384 int addrlen = sizeof(addr);
386 /* close log file before the potentially very long select so
387 file can be trimmed by another process instead of growing
394 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
398 if(!FD_ISSET(s, &fds)) continue;
400 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
402 if (fd == -1) continue;
404 signal(SIGCHLD, SIG_IGN);
406 /* we shouldn't have any children left hanging around
407 but I have had reports that on Digital Unix zombies
408 are produced, so this ensures that they are reaped */
410 while (waitpid(-1, NULL, WNOHANG) > 0);
415 /* open log file in child before possibly giving
426 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
435 } socket_options[] = {
436 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
437 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
438 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
440 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
442 #ifdef IPTOS_LOWDELAY
443 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
445 #ifdef IPTOS_THROUGHPUT
446 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
449 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
452 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
455 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
458 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
461 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
464 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
470 /****************************************************************************
471 set user socket options
472 ****************************************************************************/
473 void set_socket_options(int fd, char *options)
476 if (!options || !*options) return;
478 options = strdup(options);
480 if (!options) out_of_memory("set_socket_options");
482 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
488 if ((p = strchr(tok,'='))) {
494 for (i=0;socket_options[i].name;i++)
495 if (strcmp(socket_options[i].name,tok)==0)
498 if (!socket_options[i].name) {
499 rprintf(FERROR,"Unknown socket option %s\n",tok);
503 switch (socket_options[i].opttype) {
506 ret = setsockopt(fd,socket_options[i].level,
507 socket_options[i].option,(char *)&value,sizeof(int));
512 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
515 int on = socket_options[i].value;
516 ret = setsockopt(fd,socket_options[i].level,
517 socket_options[i].option,(char *)&on,sizeof(int));
523 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
530 /****************************************************************************
531 become a daemon, discarding the controlling terminal
532 ****************************************************************************/
533 void become_daemon(void)
541 /* detach from the terminal */
546 i = open("/dev/tty", O_RDWR);
548 ioctl(i, (int) TIOCNOTTY, (char *)0);
551 #endif /* TIOCNOTTY */
553 /* make sure that stdin, stdout an stderr don't stuff things
554 up (library functions, for example) */
557 open("/dev/null", O_RDWR);
562 * Return the IP addr of the client as a string
564 char *client_addr(int fd)
566 struct sockaddr_storage ss;
567 int length = sizeof(ss);
568 static char addr_buf[100];
569 static int initialised;
571 if (initialised) return addr_buf;
575 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
576 exit_cleanup(RERR_SOCKETIO);
579 getnameinfo((struct sockaddr *)&ss, length,
580 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
586 * Return the DNS name of the client
588 char *client_name(int fd)
590 struct sockaddr_storage ss;
591 int length = sizeof(ss);
592 static char name_buf[100];
593 static char port_buf[100];
594 char *def = "UNKNOWN";
595 static int initialised;
596 struct addrinfo hints, *res, *res0;
599 if (initialised) return name_buf;
603 strcpy(name_buf,def);
605 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
606 /* FIXME: Can we really not continue? */
607 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
608 fd, strerror(errno));
609 exit_cleanup(RERR_SOCKETIO);
613 if (ss.ss_family == AF_INET6 &&
614 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
615 struct sockaddr_in6 sin6;
616 struct sockaddr_in *sin;
618 memcpy(&sin6, &ss, sizeof(sin6));
619 sin = (struct sockaddr_in *)&ss;
620 memset(sin, 0, sizeof(*sin));
621 sin->sin_family = AF_INET;
622 length = sizeof(struct sockaddr_in);
623 #ifdef HAVE_SOCKADDR_LEN
624 sin->sin_len = length;
626 sin->sin_port = sin6.sin6_port;
627 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
628 sizeof(sin->sin_addr));
633 if (getnameinfo((struct sockaddr *)&ss, length,
634 name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
635 NI_NAMEREQD | NI_NUMERICSERV) != 0) {
636 strcpy(name_buf, def);
637 rprintf(FERROR, "reverse name lookup failed\n");
641 memset(&hints, 0, sizeof(hints));
642 hints.ai_family = PF_UNSPEC;
643 hints.ai_flags = AI_CANONNAME;
644 hints.ai_socktype = SOCK_STREAM;
645 error = getaddrinfo(name_buf, port_buf, &hints, &res0);
647 strcpy(name_buf, def);
649 RSYNC_NAME ": forward name lookup for %s failed: %s\n",
651 gai_strerror(error));
655 /* XXX sin6_flowinfo and other fields */
656 for (res = res0; res; res = res->ai_next) {
657 if (res->ai_family != ss.ss_family)
659 if (res->ai_addrlen != length)
661 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
665 /* TODO: Do a forward lookup as well to prevent spoofing */
668 strcpy(name_buf, def);
669 rprintf(FERROR, RSYNC_NAME ": "
670 "reverse name lookup mismatch on fd%d - spoofed address?\n",
679 /*******************************************************************
680 this is like socketpair but uses tcp. It is used by the Samba
682 The function guarantees that nobody else can attach to the socket,
683 or if they do that this function fails and the socket gets closed
684 returns 0 on success, -1 on failure
685 the resulting file descriptors are symmetrical
686 ******************************************************************/
687 static int socketpair_tcp(int fd[2])
690 struct sockaddr_in sock;
691 struct sockaddr_in sock2;
692 socklen_t socklen = sizeof(sock);
693 int connect_done = 0;
695 fd[0] = fd[1] = listener = -1;
697 memset(&sock, 0, sizeof(sock));
699 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
701 memset(&sock2, 0, sizeof(sock2));
702 #ifdef HAVE_SOCK_SIN_LEN
703 sock2.sin_len = sizeof(sock2);
705 sock2.sin_family = PF_INET;
707 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
709 if (listen(listener, 1) != 0) goto failed;
711 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
713 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
715 set_nonblocking(fd[1]);
717 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
719 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
720 if (errno != EINPROGRESS) goto failed;
725 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
728 if (connect_done == 0) {
729 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
730 && errno != EISCONN) goto failed;
733 set_blocking (fd[1]);
739 if (fd[0] != -1) close(fd[0]);
740 if (fd[1] != -1) close(fd[1]);
741 if (listener != -1) close(listener);
746 /*******************************************************************
747 run a program on a local tcp socket, this is used to launch smbd
748 when regression testing
749 the return value is a socket which is attached to a subprocess
750 running "prog". stdin and stdout are attached. stderr is left
751 attached to the original stderr
752 ******************************************************************/
753 int sock_exec(const char *prog)
756 if (socketpair_tcp(fd) != 0) {
757 rprintf (FERROR, RSYNC_NAME
758 ": socketpair_tcp failed (%s)\n",
770 RSYNC_NAME ": execute socket program \"%s\"\n",
772 exit (system (prog));