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 /*******************************************************************
674 this is like socketpair but uses tcp. It is used by the Samba
676 The function guarantees that nobody else can attach to the socket,
677 or if they do that this function fails and the socket gets closed
678 returns 0 on success, -1 on failure
679 the resulting file descriptors are symmetrical
680 ******************************************************************/
681 static int socketpair_tcp(int fd[2])
684 struct sockaddr_in sock;
685 struct sockaddr_in sock2;
686 socklen_t socklen = sizeof(sock);
687 int connect_done = 0;
689 fd[0] = fd[1] = listener = -1;
691 memset(&sock, 0, sizeof(sock));
693 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
695 memset(&sock2, 0, sizeof(sock2));
696 #ifdef HAVE_SOCK_SIN_LEN
697 sock2.sin_len = sizeof(sock2);
699 sock2.sin_family = PF_INET;
701 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
703 if (listen(listener, 1) != 0) goto failed;
705 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
707 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
709 set_nonblocking(fd[1]);
711 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
713 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
714 if (errno != EINPROGRESS) goto failed;
719 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
722 if (connect_done == 0) {
723 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
724 && errno != EISCONN) goto failed;
727 set_blocking (fd[1]);
733 if (fd[0] != -1) close(fd[0]);
734 if (fd[1] != -1) close(fd[1]);
735 if (listener != -1) close(listener);
740 /*******************************************************************
741 run a program on a local tcp socket, this is used to launch smbd
742 when regression testing
743 the return value is a socket which is attached to a subprocess
744 running "prog". stdin and stdout are attached. stderr is left
745 attached to the original stderr
746 ******************************************************************/
747 int sock_exec(const char *prog)
750 if (socketpair_tcp(fd) != 0) {
751 rprintf (FERROR, RSYNC_NAME
752 ": socketpair_tcp failed (%s)\n",
764 RSYNC_NAME ": execute socket program \"%s\"\n",
766 exit (system (prog));