Diff for /embedaddon/rsync/socket.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2016/11/01 09:54:32 version 1.1.1.4, 2021/03/17 00:32:36
Line 3 Line 3
  *   *
  * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>   * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>   * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
 * Copyright (C) 2003-2015 Wayne Davison * Copyright (C) 2003-2020 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
Line 26 Line 26
   
 #include "rsync.h"  #include "rsync.h"
 #include "itypes.h"  #include "itypes.h"
   #include "ifuncs.h"
 #ifdef HAVE_NETINET_IN_SYSTM_H  #ifdef HAVE_NETINET_IN_SYSTM_H
 #include <netinet/in_systm.h>  #include <netinet/in_systm.h>
 #endif  #endif
Line 38  extern char *bind_address; Line 39  extern char *bind_address;
 extern char *sockopts;  extern char *sockopts;
 extern int default_af_hint;  extern int default_af_hint;
 extern int connect_timeout;  extern int connect_timeout;
   extern int pid_file_fd;
   extern int diffserv;
   extern char *congestion_alg;
   
 #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
 static struct sigaction sigact;  static struct sigaction sigact;
Line 48  static int sock_exec(const char *prog); Line 52  static int sock_exec(const char *prog);
 /* Establish a proxy connection on an open socket to a web proxy by using the  /* Establish a proxy connection on an open socket to a web proxy by using the
  * CONNECT method.  If proxy_user and proxy_pass are not NULL, they are used to   * CONNECT method.  If proxy_user and proxy_pass are not NULL, they are used to
  * authenticate to the proxy using the "Basic" proxy-authorization protocol. */   * authenticate to the proxy using the "Basic" proxy-authorization protocol. */
static int establish_proxy_connection(int fd, char *host, int port,static int establish_proxy_connection(int fd, char *host, int port, char *proxy_user, char *proxy_pass)
                                      char *proxy_user, char *proxy_pass) 
 {  {
         char *cp, buffer[1024];          char *cp, buffer[1024];
         char *authhdr, authbuf[1024];          char *authhdr, authbuf[1024];
Line 73  static int establish_proxy_connection(int fd, char *ho Line 76  static int establish_proxy_connection(int fd, char *ho
                 authhdr = "";                  authhdr = "";
         }          }
   
        snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n",        len = snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n", host, port, authhdr, authbuf);
                 host, port, authhdr, authbuf);        assert(len > 0 && len < (int)sizeof buffer);
        len = strlen(buffer); 
         if (write(fd, buffer, len) != len) {          if (write(fd, buffer, len) != len) {
                 rsyserr(FERROR, errno, "failed to write to proxy");                  rsyserr(FERROR, errno, "failed to write to proxy");
                 return -1;                  return -1;
Line 166  static void contimeout_handler(UNUSED(int val)) Line 168  static void contimeout_handler(UNUSED(int val))
         connect_timeout = -1;          connect_timeout = -1;
 }  }
   
   /* Set special socket options
    *
    * Diffserv is a value in the range of 0-63, and needs to be shifted left
    *          2 places AND treated differently for ipv4 and ipv6.
    * Setting TCP congestion control is rather Linux specific (at the moment)
    * and sends a varying length string to setsockopt rather than an integer
    * or character.
   */
   
   void set_special_sockopts(int s)
   {
   #if defined(TCP_CONGESTION)
           if (congestion_alg) {
                   if (setsockopt(s, SOL_TCP, TCP_CONGESTION, congestion_alg, strlen(congestion_alg)) == -1)
                           rprintf(FINFO, "Couldn't set %s congestion algorithm\n", congestion_alg);
           }
   #endif
   
   /* setting the diffserv/tos bits is different on ipv6 and
    *  ipv4, so we just hammer down on both and ignore the result
    *  And ipv6 demands an int for v. I didn't write the spec.
    */
           if (diffserv) {
                   int v = (diffserv & 63) <<2;
                   setsockopt(s,IPPROTO_IP, IP_TOS, &v, sizeof(v));
   #if defined(IPV6_TCLASS)
                   setsockopt(s,IPPROTO_IPV6, IPV6_TCLASS, &v, sizeof(v));
   #endif
           }
   }
   
 /* Open a socket to a tcp remote host with the specified port.  /* Open a socket to a tcp remote host with the specified port.
  *   *
  * Based on code from Warren.  Proxy support by Stephen Rothwell.   * Based on code from Warren.  Proxy support by Stephen Rothwell.
Line 182  static void contimeout_handler(UNUSED(int val)) Line 215  static void contimeout_handler(UNUSED(int val))
  * bind_addr: local address to use.  Normally NULL to bind the wildcard address.   * bind_addr: local address to use.  Normally NULL to bind the wildcard address.
  *   *
  * af_hint: address family, e.g. AF_INET or AF_INET6. */   * af_hint: address family, e.g. AF_INET or AF_INET6. */
int open_socket_out(char *host, int port, const char *bind_addr,int open_socket_out(char *host, int port, const char *bind_addr, int af_hint)
                    int af_hint) 
 {  {
         int type = SOCK_STREAM;          int type = SOCK_STREAM;
         int error, s, j, addr_cnt, *errnos;          int error, s, j, addr_cnt, *errnos;
Line 195  int open_socket_out(char *host, int port, const char * Line 227  int open_socket_out(char *host, int port, const char *
         char *proxy_user = NULL, *proxy_pass = NULL;          char *proxy_user = NULL, *proxy_pass = NULL;
   
         /* if we have a RSYNC_PROXY env variable then redirect our          /* if we have a RSYNC_PROXY env variable then redirect our
         * connetcion via a web proxy at the given address. */         * connection via a web proxy at the given address. */
         h = getenv("RSYNC_PROXY");          h = getenv("RSYNC_PROXY");
         proxied = h != NULL && *h != '\0';          proxied = h != NULL && *h != '\0';
   
Line 250  int open_socket_out(char *host, int port, const char * Line 282  int open_socket_out(char *host, int port, const char *
   
         for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}          for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
         errnos = new_array0(int, addr_cnt);          errnos = new_array0(int, addr_cnt);
         if (!errnos)  
                 out_of_memory("open_socket_out");  
   
         s = -1;          s = -1;
         /* Try to connect to all addresses for this machine until we get          /* Try to connect to all addresses for this machine until we get
Line 275  int open_socket_out(char *host, int port, const char * Line 305  int open_socket_out(char *host, int port, const char *
                         alarm(connect_timeout);                          alarm(connect_timeout);
                 }                  }
   
                   set_special_sockopts(s);
                 set_socket_options(s, sockopts);                  set_socket_options(s, sockopts);
                 while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {                  while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
                         if (connect_timeout < 0)                          if (connect_timeout < 0)
Line 294  int open_socket_out(char *host, int port, const char * Line 325  int open_socket_out(char *host, int port, const char *
                         continue;                          continue;
                 }                  }
   
                if (proxied                if (proxied && establish_proxy_connection(s, host, port, proxy_user, proxy_pass) != 0) {
                 && establish_proxy_connection(s, host, port, 
                                               proxy_user, proxy_pass) != 0) { 
                         close(s);                          close(s);
                         s = -1;                          s = -1;
                         continue;                          continue;
Line 340  int open_socket_out(char *host, int port, const char * Line 369  int open_socket_out(char *host, int port, const char *
  * This is based on the Samba LIBSMB_PROG feature.   * This is based on the Samba LIBSMB_PROG feature.
  *   *
  * bind_addr: local address to use.  Normally NULL to get the stack default. */   * bind_addr: local address to use.  Normally NULL to get the stack default. */
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,int open_socket_out_wrapped(char *host, int port, const char *bind_addr, int af_hint)
                            int af_hint) 
 {  {
         char *prog = getenv("RSYNC_CONNECT_PROG");          char *prog = getenv("RSYNC_CONNECT_PROG");
   
Line 359  int open_socket_out_wrapped(char *host, int port, cons Line 387  int open_socket_out_wrapped(char *host, int port, cons
                                 len += hlen;                                  len += hlen;
                 }                  }
                 f = prog;                  f = prog;
                if (!(prog = new_array(char, len)))                prog = new_array(char, len);
                        out_of_memory("open_socket_out_wrapped"); 
                 for (t = prog; *f; f++) {                  for (t = prog; *f; f++) {
                         if (*f == '%') {                          if (*f == '%') {
                                 switch (*++f) {                                  switch (*++f) {
Line 428  static int *open_socket_in(int type, int port, const c Line 455  static int *open_socket_in(int type, int port, const c
   
         socks = new_array(int, maxs + 1);          socks = new_array(int, maxs + 1);
         errmsgs = new_array(char *, maxs);          errmsgs = new_array(char *, maxs);
         if (!socks || !errmsgs)  
                 out_of_memory("open_socket_in");  
   
         /* We may not be able to create the socket, if for example the          /* We may not be able to create the socket, if for example the
          * machine knows about IPv6 in the C library, but not in the           * machine knows about IPv6 in the C library, but not in the
Line 449  static int *open_socket_in(int type, int port, const c Line 474  static int *open_socket_in(int type, int port, const c
                         continue;                          continue;
                 }                  }
   
                   set_special_sockopts(s);
                 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,                  setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                            (char *)&one, sizeof one);                             (char *)&one, sizeof one);
                 if (sockopts)                  if (sockopts)
Line 458  static int *open_socket_in(int type, int port, const c Line 484  static int *open_socket_in(int type, int port, const c
   
 #ifdef IPV6_V6ONLY  #ifdef IPV6_V6ONLY
                 if (resp->ai_family == AF_INET6) {                  if (resp->ai_family == AF_INET6) {
                        if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,                        if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof one) < 0
                                       (char *)&one, sizeof one) < 0                         && default_af_hint != AF_INET6) {
                            && default_af_hint != AF_INET6) { 
                                 close(s);                                  close(s);
                                 continue;                                  continue;
                         }                          }
Line 532  int is_a_socket(int fd) Line 557  int is_a_socket(int fd)
 static void sigchld_handler(UNUSED(int val))  static void sigchld_handler(UNUSED(int val))
 {  {
 #ifdef WNOHANG  #ifdef WNOHANG
        while (waitpid(-1, NULL, WNOHANG) > 0) {}        int status;
         while (waitpid(-1, &status, WNOHANG) > 0) {
                 if (WIFSIGNALED(status)) {
                         rprintf(FLOG,
                                 "rsync error: (3) Child proccess has unexpectedly died with signal %d\n",
                                 WTERMSIG(status));
                 } else if (WIFEXITED(status) && WEXITSTATUS(status) == RERR_WECRASHED) {
                         rprintf(FLOG,
                                 "rsync error: (3) Child proccess has CRASHED.\n");
                 }
         }
 #endif  #endif
 #ifndef HAVE_SIGACTION  #ifndef HAVE_SIGACTION
         signal(SIGCHLD, sigchld_handler);          signal(SIGCHLD, sigchld_handler);
Line 544  void start_accept_loop(int port, int (*fn)(int, int)) Line 579  void start_accept_loop(int port, int (*fn)(int, int))
 {  {
         fd_set deffds;          fd_set deffds;
         int *sp, maxfd, i;          int *sp, maxfd, i;
   #ifdef HAVE_LIBSLP
           time_t next_slp_refresh;
           short slp_timeout = lp_use_slp() ? lp_slp_refresh() : 0;
           if (slp_timeout) {
                   if (slp_timeout < SLP_MIN_TIMEOUT)
                           slp_timeout = SLP_MIN_TIMEOUT;
                   /* re-register before slp times out */
                   slp_timeout -= 15;
           }
   #endif
   
 #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
         sigact.sa_flags = SA_NOCLDSTOP;          sigact.sa_flags = SA_NOCLDSTOP;
Line 561  void start_accept_loop(int port, int (*fn)(int, int)) Line 606  void start_accept_loop(int port, int (*fn)(int, int))
                         rsyserr(FERROR, errno, "listen() on socket failed");                          rsyserr(FERROR, errno, "listen() on socket failed");
 #ifdef INET6  #ifdef INET6
                         if (errno == EADDRINUSE && i > 0) {                          if (errno == EADDRINUSE && i > 0) {
                                rprintf(FINFO,                                rprintf(FINFO, "Try using --ipv4 or --ipv6 to avoid this listen() error.\n");
                                    "Try using --ipv4 or --ipv6 to avoid this listen() error.\n"); 
                         }                          }
 #endif  #endif
                         exit_cleanup(RERR_SOCKETIO);                          exit_cleanup(RERR_SOCKETIO);
Line 572  void start_accept_loop(int port, int (*fn)(int, int)) Line 616  void start_accept_loop(int port, int (*fn)(int, int))
                         maxfd = sp[i];                          maxfd = sp[i];
         }          }
   
   #ifdef HAVE_LIBSLP
           next_slp_refresh = time(NULL) + slp_timeout;
   #endif
   
         /* now accept incoming connections - forking a new process          /* now accept incoming connections - forking a new process
          * for each incoming connection */           * for each incoming connection */
         while (1) {          while (1) {
                 fd_set fds;                  fd_set fds;
                 pid_t pid;                  pid_t pid;
                 int fd;                  int fd;
                   int sel_ret;
                 struct sockaddr_storage addr;                  struct sockaddr_storage addr;
                 socklen_t addrlen = sizeof addr;                  socklen_t addrlen = sizeof addr;
   #ifdef HAVE_LIBSLP
                   struct timeval slp_tv;
   
                   slp_tv.tv_sec = 10;
                   slp_tv.tv_usec = 0;
   #endif
   
                 /* close log file before the potentially very long select so                  /* close log file before the potentially very long select so
                  * file can be trimmed by another process instead of growing                   * file can be trimmed by another process instead of growing
                  * forever */                   * forever */
Line 592  void start_accept_loop(int port, int (*fn)(int, int)) Line 647  void start_accept_loop(int port, int (*fn)(int, int))
                 fds = deffds;                  fds = deffds;
 #endif  #endif
   
                if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1)#ifdef HAVE_LIBSLP
                 sel_ret = select(maxfd + 1, &fds, NULL, NULL,
                                  slp_timeout ? &slp_tv : NULL);
                 if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) {
                         rprintf(FINFO, "Service registration expired, refreshing it\n");
                         register_services();
                         next_slp_refresh = time(NULL) + slp_timeout;
                 }
 #else
                 sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL);
 #endif
                 if (sel_ret < 1)
                         continue;                          continue;
   
                 for (i = 0, fd = -1; sp[i] >= 0; i++) {                  for (i = 0, fd = -1; sp[i] >= 0; i++) {
                         if (FD_ISSET(sp[i], &fds)) {                          if (FD_ISSET(sp[i], &fds)) {
                                fd = accept(sp[i], (struct sockaddr *)&addr,                                fd = accept(sp[i], (struct sockaddr *)&addr, &addrlen);
                                            &addrlen); 
                                 break;                                  break;
                         }                          }
                 }                  }
Line 610  void start_accept_loop(int port, int (*fn)(int, int)) Line 675  void start_accept_loop(int port, int (*fn)(int, int))
   
                 if ((pid = fork()) == 0) {                  if ((pid = fork()) == 0) {
                         int ret;                          int ret;
                           if (pid_file_fd >= 0)
                                   close(pid_file_fd);
                         for (i = 0; sp[i] >= 0; i++)                          for (i = 0; sp[i] >= 0; i++)
                                 close(sp[i]);                                  close(sp[i]);
                         /* Re-open log file in child before possibly giving                          /* Re-open log file in child before possibly giving
Line 690  void set_socket_options(int fd, char *options) Line 757  void set_socket_options(int fd, char *options)
   
         options = strdup(options);          options = strdup(options);
   
         if (!options)  
                 out_of_memory("set_socket_options");  
   
         for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {          for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
                 int ret=0,i;                  int ret=0,i;
                 int value = 1;                  int value = 1;
Line 797  static int socketpair_tcp(int fd[2]) Line 861  static int socketpair_tcp(int fd[2])
         set_blocking(fd[1]);          set_blocking(fd[1]);
   
         if (connect_done == 0) {          if (connect_done == 0) {
                if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0                if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0 && errno != EISCONN)
                    && errno != EISCONN) 
                         goto failed;                          goto failed;
         }          }
   
Line 820  static int socketpair_tcp(int fd[2]) Line 883  static int socketpair_tcp(int fd[2])
  * stdout.  This is used to fake a connection to a daemon for testing -- not   * stdout.  This is used to fake a connection to a daemon for testing -- not
  * for the normal case of running SSH.   * for the normal case of running SSH.
  *   *
 * Retruns a socket which is attached to a subprocess running "prog". stdin and * Returns a socket which is attached to a subprocess running "prog". stdin and
  * stdout are attached. stderr is left attached to the original stderr. */   * stdout are attached. stderr is left attached to the original stderr. */
 static int sock_exec(const char *prog)  static int sock_exec(const char *prog)
 {  {
Line 847  static int sock_exec(const char *prog) Line 910  static int sock_exec(const char *prog)
                         fprintf(stderr, "Failed to run \"%s\"\n", prog);                          fprintf(stderr, "Failed to run \"%s\"\n", prog);
                         exit(1);                          exit(1);
                 }                  }
                exit(system(prog));                exit(shell_exec(prog));
         }          }
   
         close(fd[1]);          close(fd[1]);

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>