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 for (res = res0; res; res = res->ai_next) {
166 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
171 struct addrinfo bhints, *bres;
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);
179 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s <noport>: %s\n",
180 bind_address, gai_strerror(error));
184 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s resolved to multiple hosts\n",
189 bind(s, bres->ai_addr, bres->ai_addrlen);
192 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
198 establish_proxy_connection(s, host, port) != 0) {
207 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
216 * Open an outgoing socket, but allow for it to be intercepted by
217 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
218 * socketpair rather than really opening a socket.
220 * We use this primarily in testing to detect TCP flow bugs, but not
221 * cause security problems by really opening remote connections.
223 * This is based on the Samba LIBSMB_PROG feature.
225 * @param bind_address Local address to use. Normally NULL to get the stack default.
227 int open_socket_out_wrapped (char *host,
229 const char *bind_address,
234 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
235 return sock_exec (prog);
237 return open_socket_out (host, port, bind_address,
244 * Open a socket of the specified type, port and address for incoming data
246 * Try to be better about handling the results of getaddrinfo(): when
247 * opening an inbound socket, we might get several address results,
248 * e.g. for the machine's ipv4 and ipv6 name.
250 * If binding a wildcard, then any one of them should do. If an address
251 * was specified but it's insufficiently specific then that's not our
254 * However, some of the advertized addresses may not work because e.g. we
255 * don't have IPv6 support in the kernel. In that case go on and try all
256 * addresses until one succeeds.
258 * @param bind_address Local address to bind, or NULL to allow it to
261 static int open_socket_in(int type, int port, const char *bind_address,
266 struct addrinfo hints, *res, *resp;
270 memset(&hints, 0, sizeof(hints));
271 hints.ai_family = af_hint;
272 hints.ai_socktype = type;
273 hints.ai_flags = AI_PASSIVE;
274 snprintf(portbuf, sizeof(portbuf), "%d", port);
275 error = getaddrinfo(bind_address, portbuf, &hints, &res);
277 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
278 bind_address, gai_strerror(error));
281 /* XXX: Do we need to care about getting multiple results
282 * back? I think probably not; if the user passed
283 * bind_address == NULL and we set AI_PASSIVE then we ought to
284 * get a wildcard result. */
288 s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
291 break; /* got a socket */
292 } else if ((resp = resp->ai_next)) {
294 case EPROTONOSUPPORT:
297 /* See if there's another address that will work... */
302 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
303 "(dom=%d, type=%d, proto=%d) failed: %s\n",
304 resp->ai_family, resp->ai_socktype, resp->ai_protocol,
309 setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
311 /* now we've got a socket - we need to bind it */
312 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
313 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
327 * Determine if a file descriptor is in fact a socket
329 int is_a_socket(int fd)
335 /* Parameters to getsockopt, setsockopt etc are very
336 * unstandardized across platforms, so don't be surprised if
337 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
338 * It seems they all eventually get the right idea.
340 * Debian says: ``The fifth argument of getsockopt and
341 * setsockopt is in reality an int [*] (and this is what BSD
342 * 4.* and libc4 and libc5 have). Some POSIX confusion
343 * resulted in the present socklen_t. The draft standard has
344 * not been adopted yet, but glibc2 already follows it and
345 * also has socklen_t [*]. See also accept(2).''
347 * We now return to your regularly scheduled programming. */
348 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
352 void start_accept_loop(int port, int (*fn)(int ))
355 extern char *bind_address;
357 /* open an incoming socket */
358 s = open_socket_in(SOCK_STREAM, port, bind_address,
359 global_opts.af_hint);
361 exit_cleanup(RERR_SOCKETIO);
363 /* ready to listen */
364 if (listen(s, 5) == -1) {
366 exit_cleanup(RERR_SOCKETIO);
370 /* now accept incoming connections - forking a new process
371 for each incoming connection */
375 struct sockaddr addr;
376 int in_addrlen = sizeof(addr);
378 /* close log file before the potentially very long select so
379 file can be trimmed by another process instead of growing
386 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
390 if(!FD_ISSET(s, &fds)) continue;
392 fd = accept(s,(struct sockaddr *)&addr,&in_addrlen);
394 if (fd == -1) continue;
396 signal(SIGCHLD, SIG_IGN);
398 /* we shouldn't have any children left hanging around
399 but I have had reports that on Digital Unix zombies
400 are produced, so this ensures that they are reaped */
402 while (waitpid(-1, NULL, WNOHANG) > 0);
407 /* open log file in child before possibly giving
418 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
427 } socket_options[] = {
428 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
429 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
430 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
432 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
434 #ifdef IPTOS_LOWDELAY
435 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
437 #ifdef IPTOS_THROUGHPUT
438 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
441 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
444 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
447 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
450 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
453 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
456 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
462 /****************************************************************************
463 set user socket options
464 ****************************************************************************/
465 void set_socket_options(int fd, char *options)
468 if (!options || !*options) return;
470 options = strdup(options);
472 if (!options) out_of_memory("set_socket_options");
474 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
480 if ((p = strchr(tok,'='))) {
486 for (i=0;socket_options[i].name;i++)
487 if (strcmp(socket_options[i].name,tok)==0)
490 if (!socket_options[i].name) {
491 rprintf(FERROR,"Unknown socket option %s\n",tok);
495 switch (socket_options[i].opttype) {
498 ret = setsockopt(fd,socket_options[i].level,
499 socket_options[i].option,(char *)&value,sizeof(int));
504 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
507 int on = socket_options[i].value;
508 ret = setsockopt(fd,socket_options[i].level,
509 socket_options[i].option,(char *)&on,sizeof(int));
515 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
522 /****************************************************************************
523 become a daemon, discarding the controlling terminal
524 ****************************************************************************/
525 void become_daemon(void)
533 /* detach from the terminal */
538 i = open("/dev/tty", O_RDWR);
540 ioctl(i, (int) TIOCNOTTY, (char *)0);
543 #endif /* TIOCNOTTY */
545 /* make sure that stdin, stdout an stderr don't stuff things
546 up (library functions, for example) */
549 open("/dev/null", O_RDWR);
554 * Return the IP addr of the client as a string
556 char *client_addr(int fd)
559 int length = sizeof(ss);
560 static char addr_buf[100];
561 static int initialised;
563 if (initialised) return addr_buf;
567 if (getpeername(fd, &ss, &length)) {
568 exit_cleanup(RERR_SOCKETIO);
571 getnameinfo(&ss, length,
572 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
578 * Return the DNS name of the client
580 char *client_name(int fd)
583 int length = sizeof(ss);
584 static char name_buf[100];
585 static char port_buf[100];
586 char *def = "UNKNOWN";
587 static int initialised;
588 struct addrinfo hints, *res, *res0;
591 if (initialised) return name_buf;
595 strcpy(name_buf,def);
597 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
598 /* FIXME: Can we really not continue? */
599 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
600 fd, strerror(errno));
601 exit_cleanup(RERR_SOCKETIO);
605 if (ss.sa_family == AF_INET6 &&
606 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
607 struct sockaddr_in6 sin6;
608 struct sockaddr_in *sin;
610 memcpy(&sin6, &ss, sizeof(sin6));
611 sin = (struct sockaddr_in *)&ss;
612 memset(sin, 0, sizeof(*sin));
613 sin->sin_family = AF_INET;
614 length = sizeof(struct sockaddr_in);
615 #ifdef HAVE_SOCKADDR_LEN
616 sin->sin_len = length;
618 sin->sin_port = sin6.sin6_port;
619 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
620 sizeof(sin->sin_addr));
625 if (getnameinfo((struct sockaddr *)&ss, length,
626 name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
627 NI_NAMEREQD | NI_NUMERICSERV) != 0) {
628 strcpy(name_buf, def);
629 rprintf(FERROR, "reverse name lookup failed\n");
633 memset(&hints, 0, sizeof(hints));
634 hints.ai_family = PF_UNSPEC;
635 hints.ai_flags = AI_CANONNAME;
636 hints.ai_socktype = SOCK_STREAM;
637 error = getaddrinfo(name_buf, port_buf, &hints, &res0);
639 strcpy(name_buf, def);
641 RSYNC_NAME ": forward name lookup for %s failed: %s\n",
643 gai_strerror(error));
647 /* XXX sin6_flowinfo and other fields */
648 for (res = res0; res; res = res->ai_next) {
649 if (res->ai_family != ss.sa_family)
651 if (res->ai_addrlen != length)
653 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
657 /* TODO: Do a forward lookup as well to prevent spoofing */
660 strcpy(name_buf, def);
661 rprintf(FERROR, RSYNC_NAME ": "
662 "reverse name lookup mismatch on fd%d - spoofed address?\n",
671 /*******************************************************************
672 this is like socketpair but uses tcp. It is used by the Samba
674 The function guarantees that nobody else can attach to the socket,
675 or if they do that this function fails and the socket gets closed
676 returns 0 on success, -1 on failure
677 the resulting file descriptors are symmetrical
678 ******************************************************************/
679 static int socketpair_tcp(int fd[2])
682 struct sockaddr_in sock;
683 struct sockaddr_in sock2;
684 socklen_t socklen = sizeof(sock);
685 int connect_done = 0;
687 fd[0] = fd[1] = listener = -1;
689 memset(&sock, 0, sizeof(sock));
691 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
693 memset(&sock2, 0, sizeof(sock2));
694 #ifdef HAVE_SOCK_SIN_LEN
695 sock2.sin_len = sizeof(sock2);
697 sock2.sin_family = PF_INET;
699 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
701 if (listen(listener, 1) != 0) goto failed;
703 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
705 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
707 set_nonblocking(fd[1]);
709 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
711 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
712 if (errno != EINPROGRESS) goto failed;
717 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
720 if (connect_done == 0) {
721 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
722 && errno != EISCONN) goto failed;
725 set_blocking (fd[1]);
731 if (fd[0] != -1) close(fd[0]);
732 if (fd[1] != -1) close(fd[1]);
733 if (listener != -1) close(listener);
738 /*******************************************************************
739 run a program on a local tcp socket, this is used to launch smbd
740 when regression testing
741 the return value is a socket which is attached to a subprocess
742 running "prog". stdin and stdout are attached. stderr is left
743 attached to the original stderr
744 ******************************************************************/
745 int sock_exec(const char *prog)
748 if (socketpair_tcp(fd) != 0) {
749 rprintf (FERROR, RSYNC_NAME
750 ": socketpair_tcp failed (%s)\n",
762 RSYNC_NAME ": execute socket program \"%s\"\n",
764 exit (system (prog));