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 /* Establish a proxy connection on an open socket to a web roxy by
30 * using the CONNECT method. */
31 static int establish_proxy_connection(int fd, char *host, int port)
36 snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
37 if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
38 rprintf(FERROR, "failed to write to proxy: %s\n",
43 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
44 if (read(fd, cp, 1) != 1) {
45 rprintf(FERROR, "failed to read from proxy: %s\n",
58 if (strncmp(buffer, "HTTP/", 5) != 0) {
59 rprintf(FERROR, "bad response from proxy - %s\n",
63 for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
68 rprintf(FERROR, "bad response from proxy - %s\n",
72 /* throw away the rest of the HTTP header */
74 for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
76 if (read(fd, cp, 1) != 1) {
77 rprintf(FERROR, "failed to read from proxy: %s\n",
84 if ((cp > buffer) && (*cp == '\n'))
86 if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
95 * Open a socket to a tcp remote host with the specified port .
97 * Based on code from Warren. Proxy support by Stephen Rothwell.
98 * getaddrinfo() rewrite contributed by KAME.net.
100 * Now that we support IPv6 we need to look up the remote machine's
101 * address first, using @p af_hint to set a preference for the type
102 * of address. Then depending on whether it has v4 or v6 addresses we
103 * try to open a connection.
105 * The loop allows for machines with some addresses which may not be
106 * reachable, perhaps because we can't e.g. route ipv6 to that network
107 * but we can get ip4 packets through.
109 * @param bind_address Local address to use. Normally NULL to bind
110 * the wildcard address.
112 * @param af_hint Address family, e.g. AF_INET or AF_INET6.
114 int open_socket_out(char *host, int port, const char *bind_address,
117 int type = SOCK_STREAM;
121 struct addrinfo hints, *res0, *res;
128 /* if we have a RSYNC_PROXY env variable then redirect our
129 * connetcion via a web proxy at the given address. The format
130 * is hostname:port */
131 h = getenv("RSYNC_PROXY");
132 proxied = (h != NULL) && (*h != '\0');
135 strlcpy(buffer, h, sizeof(buffer));
136 cp = strchr(buffer, ':');
139 "invalid proxy specification: should be HOST:PORT\n");
146 snprintf(portbuf, sizeof(portbuf), "%d", port);
150 memset(&hints, 0, sizeof(hints));
151 hints.ai_family = af_hint;
152 hints.ai_socktype = type;
153 error = getaddrinfo(h, portbuf, &hints, &res0);
155 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
156 h, portbuf, gai_strerror(error));
161 /* Try to connect to all addresses for this machine until we get
162 * through. It might e.g. be multi-homed, or have both IPv4 and IPv6
163 * addresses. We need to create a socket for each record, since the
164 * address record tells us what protocol to use to try to connect. */
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: "
180 "bind address %s <noport>: %s\n",
181 bind_address, gai_strerror(error));
185 /* I'm not at all sure that this is the right
186 * response here... -- mbp */
187 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
188 "bind address %s resolved to multiple hosts\n",
193 bind(s, bres->ai_addr, bres->ai_addrlen);
196 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
202 establish_proxy_connection(s, host, port) != 0) {
211 rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
220 * Open an outgoing socket, but allow for it to be intercepted by
221 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
222 * socketpair rather than really opening a socket.
224 * We use this primarily in testing to detect TCP flow bugs, but not
225 * cause security problems by really opening remote connections.
227 * This is based on the Samba LIBSMB_PROG feature.
229 * @param bind_address Local address to use. Normally NULL to get the stack default.
231 int open_socket_out_wrapped (char *host,
233 const char *bind_address,
238 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
239 return sock_exec (prog);
241 return open_socket_out (host, port, bind_address,
248 * Open a socket of the specified type, port and address for incoming data
250 * Try to be better about handling the results of getaddrinfo(): when
251 * opening an inbound socket, we might get several address results,
252 * e.g. for the machine's ipv4 and ipv6 name.
254 * If binding a wildcard, then any one of them should do. If an address
255 * was specified but it's insufficiently specific then that's not our
258 * However, some of the advertized addresses may not work because e.g. we
259 * don't have IPv6 support in the kernel. In that case go on and try all
260 * addresses until one succeeds.
262 * @param bind_address Local address to bind, or NULL to allow it to
265 static int open_socket_in(int type, int port, const char *bind_address,
270 struct addrinfo hints, *res, *resp;
274 memset(&hints, 0, sizeof(hints));
275 hints.ai_family = af_hint;
276 hints.ai_socktype = type;
277 hints.ai_flags = AI_PASSIVE;
278 snprintf(portbuf, sizeof(portbuf), "%d", port);
279 error = getaddrinfo(bind_address, portbuf, &hints, &res);
281 rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
282 bind_address, gai_strerror(error));
285 /* XXX: Do we need to care about getting multiple results
286 * back? I think probably not; if the user passed
287 * bind_address == NULL and we set AI_PASSIVE then we ought to
288 * get a wildcard result. */
292 s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
295 break; /* got a socket */
296 } else if ((resp = resp->ai_next)) {
298 case EPROTONOSUPPORT:
302 /* See if there's another address that will work... */
307 rprintf(FERROR, RSYNC_NAME ": open inbound socket"
308 "(dom=%d, type=%d, proto=%d) failed: %s\n",
309 resp->ai_family, resp->ai_socktype, resp->ai_protocol,
314 setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
316 /* now we've got a socket - we need to bind it */
317 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
318 rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
332 * Determine if a file descriptor is in fact a socket
334 int is_a_socket(int fd)
340 /* Parameters to getsockopt, setsockopt etc are very
341 * unstandardized across platforms, so don't be surprised if
342 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
343 * It seems they all eventually get the right idea.
345 * Debian says: ``The fifth argument of getsockopt and
346 * setsockopt is in reality an int [*] (and this is what BSD
347 * 4.* and libc4 and libc5 have). Some POSIX confusion
348 * resulted in the present socklen_t. The draft standard has
349 * not been adopted yet, but glibc2 already follows it and
350 * also has socklen_t [*]. See also accept(2).''
352 * We now return to your regularly scheduled programming. */
353 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
357 void start_accept_loop(int port, int (*fn)(int ))
360 extern char *bind_address;
362 /* open an incoming socket */
363 s = open_socket_in(SOCK_STREAM, port, bind_address,
364 global_opts.af_hint);
366 exit_cleanup(RERR_SOCKETIO);
368 /* ready to listen */
369 if (listen(s, 5) == -1) {
371 exit_cleanup(RERR_SOCKETIO);
375 /* now accept incoming connections - forking a new process
376 for each incoming connection */
380 struct sockaddr_storage addr;
381 int addrlen = sizeof(addr);
383 /* close log file before the potentially very long select so
384 file can be trimmed by another process instead of growing
391 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
395 if(!FD_ISSET(s, &fds)) continue;
397 fd = accept(s,(struct sockaddr *)&addr,&addrlen);
399 if (fd == -1) continue;
401 signal(SIGCHLD, SIG_IGN);
403 /* we shouldn't have any children left hanging around
404 but I have had reports that on Digital Unix zombies
405 are produced, so this ensures that they are reaped */
407 while (waitpid(-1, NULL, WNOHANG) > 0);
412 /* open log file in child before possibly giving
423 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
432 } socket_options[] = {
433 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
434 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
435 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
437 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
439 #ifdef IPTOS_LOWDELAY
440 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
442 #ifdef IPTOS_THROUGHPUT
443 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
446 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
449 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
452 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
455 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
458 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
461 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
467 /****************************************************************************
468 set user socket options
469 ****************************************************************************/
470 void set_socket_options(int fd, char *options)
473 if (!options || !*options) return;
475 options = strdup(options);
477 if (!options) out_of_memory("set_socket_options");
479 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
485 if ((p = strchr(tok,'='))) {
491 for (i=0;socket_options[i].name;i++)
492 if (strcmp(socket_options[i].name,tok)==0)
495 if (!socket_options[i].name) {
496 rprintf(FERROR,"Unknown socket option %s\n",tok);
500 switch (socket_options[i].opttype) {
503 ret = setsockopt(fd,socket_options[i].level,
504 socket_options[i].option,(char *)&value,sizeof(int));
509 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
512 int on = socket_options[i].value;
513 ret = setsockopt(fd,socket_options[i].level,
514 socket_options[i].option,(char *)&on,sizeof(int));
520 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
527 /****************************************************************************
528 become a daemon, discarding the controlling terminal
529 ****************************************************************************/
530 void become_daemon(void)
538 /* detach from the terminal */
543 i = open("/dev/tty", O_RDWR);
545 ioctl(i, (int) TIOCNOTTY, (char *)0);
548 #endif /* TIOCNOTTY */
550 /* make sure that stdin, stdout an stderr don't stuff things
551 up (library functions, for example) */
554 open("/dev/null", O_RDWR);
559 * Return the IP addr of the client as a string
561 char *client_addr(int fd)
563 struct sockaddr_storage ss;
564 int length = sizeof(ss);
565 static char addr_buf[100];
566 static int initialised;
568 if (initialised) return addr_buf;
572 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
573 exit_cleanup(RERR_SOCKETIO);
576 getnameinfo((struct sockaddr *)&ss, length,
577 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
582 static int get_sockaddr_family(const struct sockaddr_storage *ss)
584 return ((struct sockaddr *) ss)->sa_family;
589 * Return the DNS name of the client
591 char *client_name(int fd)
593 struct sockaddr_storage ss;
594 int length = sizeof(ss);
595 static char name_buf[100];
596 static char port_buf[100];
597 char *def = "UNKNOWN";
598 static int initialised;
599 struct addrinfo hints, *res, *res0;
602 if (initialised) return name_buf;
606 strcpy(name_buf,def);
608 if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
609 /* FIXME: Can we really not continue? */
610 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
611 fd, strerror(errno));
612 exit_cleanup(RERR_SOCKETIO);
616 if (get_sockaddr_family(&ss) == AF_INET6 &&
617 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
618 struct sockaddr_in6 sin6;
619 struct sockaddr_in *sin;
621 memcpy(&sin6, &ss, sizeof(sin6));
622 sin = (struct sockaddr_in *)&ss;
623 memset(sin, 0, sizeof(*sin));
624 sin->sin_family = AF_INET;
625 length = sizeof(struct sockaddr_in);
626 #ifdef HAVE_SOCKADDR_LEN
627 sin->sin_len = length;
629 sin->sin_port = sin6.sin6_port;
630 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
631 sizeof(sin->sin_addr));
636 if (getnameinfo((struct sockaddr *)&ss, length,
637 name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
638 NI_NAMEREQD | NI_NUMERICSERV) != 0) {
639 strcpy(name_buf, def);
640 rprintf(FERROR, "reverse name lookup failed\n");
644 memset(&hints, 0, sizeof(hints));
645 hints.ai_family = PF_UNSPEC;
646 hints.ai_flags = AI_CANONNAME;
647 hints.ai_socktype = SOCK_STREAM;
648 error = getaddrinfo(name_buf, port_buf, &hints, &res0);
650 strcpy(name_buf, def);
652 RSYNC_NAME ": forward name lookup for %s failed: %s\n",
654 gai_strerror(error));
658 /* XXX sin6_flowinfo and other fields */
659 for (res = res0; res; res = res->ai_next) {
660 if (res->ai_family != get_sockaddr_family(&ss))
662 if (res->ai_addrlen != length)
664 if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
668 /* TODO: Do a forward lookup as well to prevent spoofing */
671 strcpy(name_buf, def);
672 rprintf(FERROR, RSYNC_NAME ": "
673 "reverse name lookup mismatch on fd%d - spoofed address?\n",
682 /*******************************************************************
683 this is like socketpair but uses tcp. It is used by the Samba
685 The function guarantees that nobody else can attach to the socket,
686 or if they do that this function fails and the socket gets closed
687 returns 0 on success, -1 on failure
688 the resulting file descriptors are symmetrical
689 ******************************************************************/
690 static int socketpair_tcp(int fd[2])
693 struct sockaddr_in sock;
694 struct sockaddr_in sock2;
695 socklen_t socklen = sizeof(sock);
696 int connect_done = 0;
698 fd[0] = fd[1] = listener = -1;
700 memset(&sock, 0, sizeof(sock));
702 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
704 memset(&sock2, 0, sizeof(sock2));
705 #ifdef HAVE_SOCK_SIN_LEN
706 sock2.sin_len = sizeof(sock2);
708 sock2.sin_family = PF_INET;
710 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
712 if (listen(listener, 1) != 0) goto failed;
714 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
716 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
718 set_nonblocking(fd[1]);
720 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
722 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
723 if (errno != EINPROGRESS) goto failed;
728 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
731 if (connect_done == 0) {
732 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
733 && errno != EISCONN) goto failed;
736 set_blocking (fd[1]);
742 if (fd[0] != -1) close(fd[0]);
743 if (fd[1] != -1) close(fd[1]);
744 if (listener != -1) close(listener);
749 /*******************************************************************
750 run a program on a local tcp socket, this is used to launch smbd
751 when regression testing
752 the return value is a socket which is attached to a subprocess
753 running "prog". stdin and stdout are attached. stderr is left
754 attached to the original stderr
755 ******************************************************************/
756 int sock_exec(const char *prog)
759 if (socketpair_tcp(fd) != 0) {
760 rprintf (FERROR, RSYNC_NAME
761 ": socketpair_tcp failed (%s)\n",
773 RSYNC_NAME ": execute socket program \"%s\"\n",
775 exit (system (prog));