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.
22 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')))
94 /* open a socket to a tcp remote host with the specified port
95 based on code from Warren
96 proxy support by Stephen Rothwell */
97 static int open_socket_out (char *host,
99 struct in_addr *address)
101 int type = SOCK_STREAM;
102 struct sockaddr_in sock_out;
103 struct sockaddr_in sock;
112 /* if we have a RSYNC_PROXY env variable then redirect our
113 * connetcion via a web proxy at the given address. The format
114 * is hostname:port */
115 h = getenv("RSYNC_PROXY");
116 proxied = (h != NULL) && (*h != '\0');
119 strlcpy(buffer, h, sizeof(buffer));
120 cp = strchr(buffer, ':');
123 "invalid proxy specification: should be HOST:PORT\n");
134 res = socket(PF_INET, type, 0);
139 hp = gethostbyname(h);
141 rprintf(FERROR,"unknown host: \"%s\"\n", h);
146 memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
147 sock_out.sin_port = htons(p);
148 sock_out.sin_family = PF_INET;
151 sock.sin_addr = *address;
153 sock.sin_family = hp->h_addrtype;
154 bind(res, (struct sockaddr * ) &sock,sizeof(sock));
157 if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
158 rprintf (FERROR, RSYNC_NAME ": failed to connect to host %s: %s\n",
164 if (proxied && establish_proxy_connection(res, host, port) != 0) {
174 * Open an outgoing socket, but allow for it to be intercepted by
175 * $RSYNC_CONNECT_PROG, which will execute a program across a TCP
176 * socketpair rather than really opening a socket.
178 * We use this primarily in testing to detect TCP flow bugs, but not
179 * cause security problems by really opening remote connections.
181 * This is based on the Samba LIBSMB_PROG feature.
183 int open_socket_out_wrapped (char *host,
185 struct in_addr *address)
189 if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
190 return sock_exec (prog);
192 return open_socket_out (host, port, address);
197 /****************************************************************************
198 open a socket of the specified type, port and address for incoming data
199 ****************************************************************************/
200 static int open_socket_in(int type, int port, struct in_addr *address)
202 struct sockaddr_in sock;
206 memset((char *)&sock,0,sizeof(sock));
207 sock.sin_port = htons(port);
208 sock.sin_family = AF_INET;
210 sock.sin_addr = *address;
212 sock.sin_addr.s_addr = INADDR_ANY;
214 res = socket(AF_INET, type, 0);
216 rprintf(FERROR, RSYNC_NAME ": socket failed: %s\n",
221 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
223 /* now we've got a socket - we need to bind it */
224 if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) {
225 rprintf(FERROR,"bind failed on port %d: %s\n", port,
227 if (errno == EACCES && port < 1024) {
228 rprintf(FERROR, "Note: you must be root to bind "
229 "to low-numbered ports");
240 * Determine if a file descriptor is in fact a socket
242 int is_a_socket(int fd)
248 /* Parameters to getsockopt, setsockopt etc are very
249 * unstandardized across platforms, so don't be surprised if
250 * there are compiler warnings on e.g. SCO OpenSwerver or AIX.
251 * It seems they all eventually get the right idea.
253 * Debian says: ``The fifth argument of getsockopt and
254 * setsockopt is in reality an int [*] (and this is what BSD
255 * 4.* and libc4 and libc5 have). Some POSIX confusion
256 * resulted in the present socklen_t. The draft standard has
257 * not been adopted yet, but glibc2 already follows it and
258 * also has socklen_t [*]. See also accept(2).''
260 * We now return to your regularly scheduled programming. */
261 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
265 void start_accept_loop(int port, int (*fn)(int ))
268 extern struct in_addr socket_address;
270 /* open an incoming socket */
271 s = open_socket_in(SOCK_STREAM, port, &socket_address);
273 exit_cleanup(RERR_SOCKETIO);
275 /* ready to listen */
276 if (listen(s, 5) == -1) {
278 exit_cleanup(RERR_SOCKETIO);
282 /* now accept incoming connections - forking a new process
283 for each incoming connection */
287 struct sockaddr addr;
288 socklen_t in_addrlen = sizeof(addr);
290 /* close log file before the potentially very long select so
291 file can be trimmed by another process instead of growing
298 if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
302 if(!FD_ISSET(s, &fds)) continue;
304 /* See note above prototypes. */
305 fd = accept(s,&addr, &in_addrlen);
307 if (fd == -1) continue;
309 signal(SIGCHLD, SIG_IGN);
311 /* we shouldn't have any children left hanging around
312 but I have had reports that on Digital Unix zombies
313 are produced, so this ensures that they are reaped */
315 while (waitpid(-1, NULL, WNOHANG) > 0);
321 /* open log file in child before possibly giving
333 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
342 } socket_options[] = {
343 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
344 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
345 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
347 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
349 #ifdef IPTOS_LOWDELAY
350 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
352 #ifdef IPTOS_THROUGHPUT
353 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
356 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
359 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
362 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
365 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
368 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
371 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
377 /****************************************************************************
378 set user socket options
379 ****************************************************************************/
380 void set_socket_options(int fd, char *options)
383 if (!options || !*options) return;
385 options = strdup(options);
387 if (!options) out_of_memory("set_socket_options");
389 for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
395 if ((p = strchr(tok,'='))) {
401 for (i=0;socket_options[i].name;i++)
402 if (strcmp(socket_options[i].name,tok)==0)
405 if (!socket_options[i].name) {
406 rprintf(FERROR,"Unknown socket option %s\n",tok);
410 switch (socket_options[i].opttype) {
413 ret = setsockopt(fd,socket_options[i].level,
414 socket_options[i].option,(char *)&value,sizeof(int));
419 rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
422 int on = socket_options[i].value;
423 ret = setsockopt(fd,socket_options[i].level,
424 socket_options[i].option,(char *)&on,sizeof(int));
430 rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
437 /****************************************************************************
438 become a daemon, discarding the controlling terminal
439 ****************************************************************************/
440 void become_daemon(void)
448 /* detach from the terminal */
453 i = open("/dev/tty", O_RDWR);
455 ioctl(i, (int) TIOCNOTTY, (char *)0);
458 #endif /* TIOCNOTTY */
460 /* make sure that stdin, stdout an stderr don't stuff things
461 up (library functions, for example) */
464 open("/dev/null", O_RDWR);
468 /*******************************************************************
469 return the IP addr of the client as a string
470 ******************************************************************/
471 char *client_addr(int fd)
474 struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
475 socklen_t length = sizeof(sa);
476 static char addr_buf[100];
477 static int initialised;
479 if (initialised) return addr_buf;
483 if (getpeername(fd, &sa, &length)) {
484 exit_cleanup(RERR_SOCKETIO);
487 strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf));
492 /*******************************************************************
493 return the DNS name of the client
494 ******************************************************************/
495 char *client_name(int fd)
498 struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
499 socklen_t length = sizeof(sa);
500 static char name_buf[100];
503 char *def = "UNKNOWN";
504 static int initialised;
506 if (initialised) return name_buf;
510 strcpy(name_buf,def);
512 if (getpeername(fd, &sa, &length)) {
513 exit_cleanup(RERR_SOCKETIO);
516 /* Look up the remote host name. */
517 if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
518 sizeof(sockin->sin_addr),
520 strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf));
524 /* do a forward lookup as well to prevent spoofing */
525 hp = gethostbyname(name_buf);
527 strcpy (name_buf,def);
528 rprintf (FERROR, "reverse name lookup for \"%s\" failed\n",
531 for (p=hp->h_addr_list;*p;p++) {
532 if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
537 strcpy(name_buf,def);
538 rprintf(FERROR,"reverse name lookup mismatch - spoofed address?\n");
546 Convert a string to an IP address. The string can be a name or
547 dotted decimal number.
549 Returns a pointer to a static in_addr struct -- if you call this
550 more than once then you should copy it.
552 struct in_addr *ip_address(const char *str)
554 static struct in_addr ret;
558 rprintf (FERROR, "ip_address received NULL name\n");
562 /* try as an IP address */
563 if (inet_aton(str, &ret) != 0) {
567 /* otherwise assume it's a network name of some sort and use
569 if ((hp = gethostbyname (str)) == 0) {
570 rprintf(FERROR, "gethostbyname failed for \"%s\": unknown host?\n",str);
574 if (hp->h_addr == NULL) {
575 rprintf(FERROR, "gethostbyname: host address is invalid for host \"%s\"\n",str);
579 if (hp->h_length > sizeof ret) {
580 rprintf(FERROR, "gethostbyname: host address for \"%s\" is too large\n",
585 if (hp->h_addrtype != AF_INET) {
586 rprintf (FERROR, "gethostname: host address for \"%s\" is not IPv4\n",
591 /* This is kind of difficult. The only field in ret is
592 s_addr, which is the IP address as a 32-bit int. On
593 UNICOS, s_addr is in fact a *bitfield* for reasons best
594 know to Cray. This means we can't memcpy in to it. On the
595 other hand, h_addr is a char*, so we can't just assign.
597 Since there's meant to be only one field inside the in_addr
598 structure we will try just copying over the top and see how
600 memcpy (&ret, hp->h_addr, hp->h_length);
607 /*******************************************************************
608 this is like socketpair but uses tcp. It is used by the Samba
610 The function guarantees that nobody else can attach to the socket,
611 or if they do that this function fails and the socket gets closed
612 returns 0 on success, -1 on failure
613 the resulting file descriptors are symmetrical
614 ******************************************************************/
615 static int socketpair_tcp(int fd[2])
618 struct sockaddr_in sock;
619 struct sockaddr_in sock2;
620 socklen_t socklen = sizeof(sock);
621 int connect_done = 0;
623 fd[0] = fd[1] = listener = -1;
625 memset(&sock, 0, sizeof(sock));
627 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
629 memset(&sock2, 0, sizeof(sock2));
630 #ifdef HAVE_SOCK_SIN_LEN
631 sock2.sin_len = sizeof(sock2);
633 sock2.sin_family = PF_INET;
635 bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
637 if (listen(listener, 1) != 0) goto failed;
639 if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
641 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
643 set_nonblocking(fd[1]);
645 sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
647 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
648 if (errno != EINPROGRESS) goto failed;
653 if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
656 if (connect_done == 0) {
657 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
658 && errno != EISCONN) goto failed;
661 set_blocking (fd[1]);
667 if (fd[0] != -1) close(fd[0]);
668 if (fd[1] != -1) close(fd[1]);
669 if (listener != -1) close(listener);
674 /*******************************************************************
675 run a program on a local tcp socket, this is used to launch smbd
676 when regression testing
677 the return value is a socket which is attached to a subprocess
678 running "prog". stdin and stdout are attached. stderr is left
679 attached to the original stderr
680 ******************************************************************/
681 int sock_exec(const char *prog)
684 if (socketpair_tcp(fd) != 0) {
685 rprintf (FERROR, RSYNC_NAME
686 ": socketpair_tcp failed (%s)\n",
698 RSYNC_NAME ": execute socket program \"%s\"\n",
700 exit (system (prog));