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 // extern int af; /* NO MORE BLOODY GLOBALS! */
35 /* Establish a proxy connection on an open socket to a web roxy by
36 * using the CONNECT method. */
37 static int establish_proxy_connection(int fd, char *host, int port)
42 snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
43 if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
44 rprintf(FERROR, "failed to write to proxy: %s\n",
49 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
50 if (read(fd, cp, 1) != 1) {
51 rprintf(FERROR, "failed to read from proxy: %s\n",
64 if (strncmp(buffer, "HTTP/", 5) != 0) {
65 rprintf(FERROR, "bad response from proxy - %s\n",
69 for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
74 rprintf(FERROR, "bad response from proxy - %s\n",
78 /* throw away the rest of the HTTP header */
80 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
82 if (read(fd, cp, 1) != 1) {
83 rprintf(FERROR, "failed to read from proxy: %s\n",
90 if ((cp > buffer) && (*cp == '\n'))
92 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
101 * Open a socket to a tcp remote host with the specified port .
103 * Based on code from Warren. Proxy support by Stephen Rothwell.
104 * getaddrinfo() rewrite contributed by KAME.net.
106 * Now that we support IPv6 we need to look up the remote machine's
107 * address first, using @p af_hint to set a preference for the type
108 * of address. Then depending on whether it has v4 or v6 addresses we
109 * try to open a connection.
111 * The loop allows for machines with some addresses which may not be
112 * reachable, perhaps because we can't e.g. route ipv6 to that network
113 * but we can get ip4 packets through.
115 * @param bind_address Local address to use. Normally NULL to bind
116 * the wildcard address.
118 * @param af_hint Address family, e.g. AF_INET or AF_INET6.
120 int open_socket_out(char *host, int port, const char *bind_address,
123 int type = SOCK_STREAM;
127 struct addrinfo hints, *res0, *res;
134 /* if we have a RSYNC_PROXY env variable then redirect our
135 * connetcion via a web proxy at the given address. The format
136 * is hostname:port */
137 h = getenv("RSYNC_PROXY");
138 proxied = (h != NULL) && (*h != '\0');
141 strlcpy(buffer, h, sizeof(buffer));
142 cp = strchr(buffer, ':');
145 "invalid proxy specification: should be HOST:PORT\n");
152 snprintf(portbuf, sizeof(portbuf), "%d", port);
156 memset(&hints, 0, sizeof(hints));
157 hints.ai_family = af_hint;
158 hints.ai_socktype = type;
159 error = getaddrinfo(h, portbuf, &hints, &res0);
161 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
162 h, portbuf, gai_strerror(error));
167 for (res = res0; res; res = res->ai_next) {
168 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
173 struct addrinfo bhints, *bres;
175 memset(&bhints, 0, sizeof(bhints));
176 bhints.ai_family = res->ai_family;
177 bhints.ai_socktype = type;
178 bhints.ai_flags = AI_PASSIVE;
179 error = getaddrinfo(bind_address, NULL, &bhints, &bres);
181 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s <noport>: %s\n",
182 bind_address, gai_strerror(error));
186 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s resolved to multiple hosts\n",
191 bind(s, bres->ai_addr, bres->ai_addrlen);
194 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
200 establish_proxy_connection(s, host, port) != 0) {
209 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
218 * Open an outgoing socket, but allow for it to be intercepted by
219 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
220 * socketpair rather than really opening a socket.
222 * We use this primarily in testing to detect TCP flow bugs, but not
223 * cause security problems by really opening remote connections.
225 * This is based on the Samba LIBSMB_PROG feature.
227 * @param bind_address Local address to use. Normally NULL to get the stack default.
229 int open_socket_out_wrapped (char *host,
231 const char *bind_address,
236 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
237 return sock_exec (prog);
239 return open_socket_out (host, port, bind_address,
246 * Open a socket of the specified type, port and address for incoming data
248 * Try to be better about handling the results of getaddrinfo(): when
249 * opening an inbound socket, we might get several address results,
250 * e.g. for the machine's ipv4 and ipv6 name.
252 * If binding a wildcard, then any one of them should do. If an address
253 * was specified but it's insufficiently specific then that's not our
256 * However, some of the advertized addresses may not work because e.g. we
257 * don't have IPv6 support in the kernel. In that case go on and try all
258 * addresses until one succeeds.
260 * @param bind_address Local address to bind, or NULL to allow it to
263 static int open_socket_in(int type, int port, const char *bind_address,
268 struct addrinfo hints, *res, *resp;
272 memset(&hints, 0, sizeof(hints));
273 hints.ai_family = af_hint;
274 hints.ai_socktype = type;
275 hints.ai_flags = AI_PASSIVE;
276 snprintf(portbuf, sizeof(portbuf), "%d", port);
277 error = getaddrinfo(bind_address, portbuf, &hints, &res);
279 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
280 bind_address, gai_strerror(error));
283 /* XXX: Do we need to care about getting multiple results
284 * back? I think probably not; if the user passed
285 * bind_address == NULL and we set AI_PASSIVE then we ought to
286 * get a wildcard result. */
290 s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
293 break; /* got a socket */
294 } else if ((resp = resp->ai_next)) {
296 case EPROTONOSUPPORT:
299 /* See if there's another address that will work... */
304 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
305 "(dom=%d, type=%d, proto=%d) failed: %s\n",
306 resp->ai_family, resp->ai_socktype, resp->ai_protocol,
311 setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
313 /* now we've got a socket - we need to bind it */
314 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
315 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
329 * Determine if a file descriptor is in fact a socket
331 int is_a_socket(int fd)
337 /* Parameters to getsockopt, setsockopt etc are very
338 * unstandardized across platforms, so don't be surprised if
339 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
340 * It seems they all eventually get the right idea.
342 * Debian says: ``The fifth argument of getsockopt and
343 * setsockopt is in reality an int [*] (and this is what BSD
344 * 4.* and libc4 and libc5 have). Some POSIX confusion
345 * resulted in the present socklen_t. The draft standard has
346 * not been adopted yet, but glibc2 already follows it and
347 * also has socklen_t [*]. See also accept(2).''
349 * We now return to your regularly scheduled programming. */
350 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
354 void start_accept_loop(int port, int (*fn)(int ))
357 extern char *bind_address;
359 /* open an incoming socket */
360 s = open_socket_in(SOCK_STREAM, port, bind_address,
361 global_opts.af_hint);
363 exit_cleanup(RERR_SOCKETIO);
365 /* ready to listen */
366 if (listen(s, 5) == -1) {
368 exit_cleanup(RERR_SOCKETIO);
372 /* now accept incoming connections - forking a new process
373 for each incoming connection */
377 struct sockaddr addr;
378 int in_addrlen = sizeof(addr);
380 /* close log file before the potentially very long select so
381 file can be trimmed by another process instead of growing
388 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
392 if(!FD_ISSET(s, &fds)) continue;
394 fd = accept(s,(struct sockaddr *)&addr,&in_addrlen);
396 if (fd == -1) continue;
398 signal(SIGCHLD, SIG_IGN);
400 /* we shouldn't have any children left hanging around
401 but I have had reports that on Digital Unix zombies
402 are produced, so this ensures that they are reaped */
404 while (waitpid(-1, NULL, WNOHANG) > 0);
409 /* open log file in child before possibly giving
420 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
429 } socket_options[] = {
430 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
431 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
432 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
434 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
436 #ifdef IPTOS_LOWDELAY
437 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
439 #ifdef IPTOS_THROUGHPUT
440 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
443 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
446 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
449 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
452 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
455 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
458 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
464 /****************************************************************************
465 set user socket options
466 ****************************************************************************/
467 void set_socket_options(int fd, char *options)
470 if (!options || !*options) return;
472 options = strdup(options);
474 if (!options) out_of_memory("set_socket_options");
476 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
482 if ((p = strchr(tok,'='))) {
488 for (i=0;socket_options[i].name;i++)
489 if (strcmp(socket_options[i].name,tok)==0)
492 if (!socket_options[i].name) {
493 rprintf(FERROR,"Unknown socket option %s\n",tok);
497 switch (socket_options[i].opttype) {
500 ret = setsockopt(fd,socket_options[i].level,
501 socket_options[i].option,(char *)&value,sizeof(int));
506 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
509 int on = socket_options[i].value;
510 ret = setsockopt(fd,socket_options[i].level,
511 socket_options[i].option,(char *)&on,sizeof(int));
517 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
524 /****************************************************************************
525 become a daemon, discarding the controlling terminal
526 ****************************************************************************/
527 void become_daemon(void)
535 /* detach from the terminal */
540 i = open("/dev/tty", O_RDWR);
542 ioctl(i, (int) TIOCNOTTY, (char *)0);
545 #endif /* TIOCNOTTY */
547 /* make sure that stdin, stdout an stderr don't stuff things
548 up (library functions, for example) */
551 open("/dev/null", O_RDWR);
556 * Return the IP addr of the client as a string
558 char *client_addr(int fd)
561 int length = sizeof(ss);
562 static char addr_buf[100];
563 static int initialised;
565 if (initialised) return addr_buf;
569 if (getpeername(fd, &ss, &length)) {
570 exit_cleanup(RERR_SOCKETIO);
573 getnameinfo(&ss, length,
574 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
580 * Return the DNS name of the client
582 char *client_name(int fd)
585 int length = sizeof(ss);
586 static char name_buf[100];
587 static char port_buf[100];
588 char *def = "UNKNOWN";
589 static int initialised;
590 struct addrinfo hints, *res, *res0;
593 if (initialised) return name_buf;
597 strcpy(name_buf,def);
599 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
600 /* FIXME: Can we really not continue? */
601 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
603 exit_cleanup(RERR_SOCKETIO);
607 if (ss.ss_family == AF_INET6 &&
608 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
609 struct sockaddr_in6 sin6;
610 struct sockaddr_in *sin;
612 memcpy(&sin6, &ss, sizeof(sin6));
613 sin = (struct sockaddr_in *)&ss;
614 memset(sin, 0, sizeof(*sin));
615 sin->sin_family = AF_INET;
616 length = sizeof(struct sockaddr_in);
617 #ifdef HAVE_SOCKADDR_LEN
618 sin->sin_len = length;
620 sin->sin_port = sin6.sin6_port;
621 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
622 sizeof(sin->sin_addr));
627 if (getnameinfo((struct sockaddr *)&ss, length,
628 name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
629 NI_NAMEREQD | NI_NUMERICSERV) != 0) {
630 strcpy(name_buf, def);
631 rprintf(FERROR, "reverse name lookup failed\n");
635 memset(&hints, 0, sizeof(hints));
636 hints.ai_family = PF_UNSPEC;
637 hints.ai_flags = AI_CANONNAME;
638 hints.ai_socktype = SOCK_STREAM;
639 error = getaddrinfo(name_buf, port_buf, &hints, &res0);
641 strcpy(name_buf, def);
643 RSYNC_NAME ": forward name lookup for %s failed: %s\n",
645 gai_strerror(error));
649 /* XXX sin6_flowinfo and other fields */
650 for (res = res0; res; res = res->ai_next) {
651 if (res->ai_family != ss.sa_family)
653 if (res->ai_addrlen != length)
655 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
659 /* TODO: Do a forward lookup as well to prevent spoofing */
662 strcpy(name_buf, def);
663 rprintf(FERROR, RSYNC_NAME ": "
664 "reverse name lookup mismatch on fd%d - spoofed address?\n",
673 * Convert a string to an IP address. The string can be a name or
674 * dotted decimal number.
676 * Returns a pointer to a static in_addr struct -- if you call this
677 * more than once then you should copy it.
679 * TODO: Use getaddrinfo() instead, or make this function call getnameinfo
681 struct in_addr *ip_address(const char *str)
683 static struct in_addr ret;
687 rprintf (FERROR, "ip_address received NULL name\n");
691 /* try as an IP address */
692 if (inet_aton(str, &ret) != 0) {
696 /* otherwise assume it's a network name of some sort and use
698 if ((hp = gethostbyname (str)) == 0) {
699 rprintf(FERROR, "gethostbyname failed for \"%s\": unknown host?\n",str);
703 if (hp->h_addr == NULL) {
704 rprintf(FERROR, "gethostbyname: host address is invalid for host \"%s\"\n",str);
708 if (hp->h_length > sizeof ret) {
709 rprintf(FERROR, "gethostbyname: host address for \"%s\" is too large\n",
714 if (hp->h_addrtype != AF_INET) {
715 rprintf (FERROR, "gethostname: host address for \"%s\" is not IPv4\n",
720 /* This is kind of difficult. The only field in ret is
721 s_addr, which is the IP address as a 32-bit int. On
722 UNICOS, s_addr is in fact a *bitfield* for reasons best
723 know to Cray. This means we can't memcpy in to it. On the
724 other hand, h_addr is a char*, so we can't just assign.
726 Since there's meant to be only one field inside the in_addr
727 structure we will try just copying over the top and see how
729 memcpy (&ret, hp->h_addr, hp->h_length);
736 /*******************************************************************
737 this is like socketpair but uses tcp. It is used by the Samba
739 The function guarantees that nobody else can attach to the socket,
740 or if they do that this function fails and the socket gets closed
741 returns 0 on success, -1 on failure
742 the resulting file descriptors are symmetrical
743 ******************************************************************/
744 static int socketpair_tcp(int fd[2])
747 struct sockaddr_in sock;
748 struct sockaddr_in sock2;
749 socklen_t socklen = sizeof(sock);
750 int connect_done = 0;
752 fd[0] = fd[1] = listener = -1;
754 memset(&sock, 0, sizeof(sock));
756 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
758 memset(&sock2, 0, sizeof(sock2));
759 #ifdef HAVE_SOCK_SIN_LEN
760 sock2.sin_len = sizeof(sock2);
762 sock2.sin_family = PF_INET;
764 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
766 if (listen(listener, 1) != 0) goto failed;
768 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
770 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
772 set_nonblocking(fd[1]);
774 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
776 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
777 if (errno != EINPROGRESS) goto failed;
782 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
785 if (connect_done == 0) {
786 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
787 && errno != EISCONN) goto failed;
790 set_blocking (fd[1]);
796 if (fd[0] != -1) close(fd[0]);
797 if (fd[1] != -1) close(fd[1]);
798 if (listener != -1) close(listener);
803 /*******************************************************************
804 run a program on a local tcp socket, this is used to launch smbd
805 when regression testing
806 the return value is a socket which is attached to a subprocess
807 running "prog". stdin and stdout are attached. stderr is left
808 attached to the original stderr
809 ******************************************************************/
810 int sock_exec(const char *prog)
813 if (socketpair_tcp(fd) != 0) {
814 rprintf (FERROR, RSYNC_NAME
815 ": socketpair_tcp failed (%s)\n",
827 RSYNC_NAME ": execute socket program \"%s\"\n",
829 exit (system (prog));