If we need to set IPV6_V6ONLY but setsockopt() fails, close the
[rsync/rsync.git] / socket.c
index 140480b..93f05a9 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -299,9 +299,14 @@ int open_socket_out(char *host, int port, const char *bind_address,
 int open_socket_out_wrapped(char *host, int port, const char *bind_address,
                            int af_hint)
 {
-       char *prog;
+       char *prog = getenv("RSYNC_CONNECT_PROG");
 
-       if ((prog = getenv("RSYNC_CONNECT_PROG")) != NULL)
+       if (verbose >= 2) {
+               rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
+                       prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
+                       host, port);
+       }
+       if (prog)
                return sock_exec(prog);
        return open_socket_out(host, port, bind_address, af_hint);
 }
@@ -313,15 +318,11 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
  *
  * Try to be better about handling the results of getaddrinfo(): when
  * opening an inbound socket, we might get several address results,
- * e.g. for the machine's ipv4 and ipv6 name.
- *
- * If binding a wildcard, then any one of them should do.  If an address
- * was specified but it's insufficiently specific then that's not our
- * fault.
+ * e.g. for the machine's IPv4 and IPv6 name.
  *
- * However, some of the advertized addresses may not work because e.g. we
- * don't have IPv6 support in the kernel.  In that case go on and try all
- * addresses until one succeeds.
+ * We return an array of socket file-descriptors, with the length of
+ * the array stored as the first element of the list.  This allows
+ * the caller to listen on all of them.
  *
  * @param bind_address Local address to bind, or NULL to allow it to
  * default.
@@ -374,8 +375,11 @@ static int *open_socket_in(int type, int port, const char *bind_address,
 
 #ifdef IPV6_V6ONLY
                if (resp->ai_family == AF_INET6) {
-                       setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
-                                  (char *)&one, sizeof one);
+                       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+                                      (char *)&one, sizeof one) < 0) {
+                               close(s);
+                               continue;
+                       }
                }
 #endif
 
@@ -441,7 +445,7 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
 void start_accept_loop(int port, int (*fn)(int, int))
 {
        fd_set deffds;
-       int *sp, maxfd, i, j;
+       int *sp, maxfd, i;
        extern char *bind_address;
        extern int default_af_hint;
 
@@ -455,9 +459,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
        maxfd = -1;
        for (i = 1; i <= *sp; i++) {
                if (listen(sp[i], 5) == -1) {
-                       for (j = 1; j <= i; j++)
-                               close(sp[j]);
-                       free(sp);
                        exit_cleanup(RERR_SOCKETIO);
                }
                FD_SET(sp[i], &deffds);
@@ -769,18 +770,14 @@ int sock_exec(const char *prog)
                        strerror(errno));
                return -1;
        }
+       if (verbose >= 2)
+               rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
        if (fork() == 0) {
                close(fd[0]);
                close(0);
                close(1);
                dup(fd[1]);
                dup(fd[1]);
-               if (verbose > 3) {
-                       /* Can't use rprintf because we've forked. */
-                       fprintf(stderr,
-                               RSYNC_NAME ": execute socket program \"%s\"\n",
-                               prog);
-               }
                exit(system(prog));
        }
        close(fd[1]);