Applied a slightly-tweaked version of Oliver Braun's patch that
implements listening on multiple addresses and a fix for IPv6-only
systems.
diff --git a/socket.c b/socket.c
index 7298351..830e164 100644
--- a/socket.c
+++ b/socket.c
@@ -285,11 +285,11 @@
  * @param bind_address Local address to bind, or NULL to allow it to
  * default.
  **/
-static int open_socket_in(int type, int port, const char *bind_address,
-			  int af_hint)
+static int *open_socket_in(int type, int port, const char *bind_address,
+			   int af_hint)
 {
 	int one=1;
-	int s;
+	int s, *sp, *socks, maxs;
 	struct addrinfo hints, *all_ai, *resp;
 	char portbuf[10];
 	int error;
@@ -303,23 +303,41 @@
 	if (error) {
 		rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
 			bind_address, gai_strerror(error));
-		return -1;
+		return NULL;
+	}
+
+	/* Count max number of sockets we might open. */
+	for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
+	socks = new_array(int, maxs + 1);
+	if (!socks) {
+		rprintf(FERROR,
+			RSYNC_NAME "couldn't allocate memory for sockets");
+		return NULL;
 	}
 
 	/* 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
 	 * kernel. */
+	sp = socks + 1; /* Leave room for count at start of array. */
 	for (resp = all_ai; resp; resp = resp->ai_next) {
 		s = socket(resp->ai_family, resp->ai_socktype,
 			   resp->ai_protocol);
 
-		if (s == -1)
+		if (s == -1) {
 			/* See if there's another address that will work... */
 			continue;
+		}
 
 		setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
 			   (char *)&one, sizeof one);
 
+#ifdef IPV6_V6ONLY
+		if (resp->ai_family == AF_INET6) {
+			setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+				   (char *)&one, sizeof one);
+		}
+#endif
+
 		/* Now we've got a socket - we need to bind it. */
 		if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
 			/* Nope, try another */
@@ -327,17 +345,21 @@
 			continue;
 		}
 
-		freeaddrinfo(all_ai);
-		return s;
+		*sp++ = s;
 	}
+	*socks = sp - socks - 1;   /* Save count. */
 
-	rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
-		"%s\n",
-		port,
-		strerror(errno));
+	if (all_ai)
+		freeaddrinfo(all_ai);
 
-	freeaddrinfo(all_ai);
-	return -1;
+	if (*socks == 0) {
+		rprintf(FERROR,
+			RSYNC_NAME ": open inbound socket on port %d failed: "
+			"%s\n", port, strerror(errno));
+		free(socks);
+		return NULL;
+	}
+	return socks;
 }
 
 
@@ -378,19 +400,29 @@
 
 void start_accept_loop(int port, int (*fn)(int, int))
 {
-	int s;
+	fd_set deffds;
+	int *sp, maxfd, i, j;
 	extern char *bind_address;
 	extern int default_af_hint;
 
 	/* open an incoming socket */
-	s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
-	if (s == -1)
+	sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
+	if (sp == NULL)
 		exit_cleanup(RERR_SOCKETIO);
 
 	/* ready to listen */
-	if (listen(s, 5) == -1) {
-		close(s);
-		exit_cleanup(RERR_SOCKETIO);
+	FD_ZERO(&deffds);
+	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);
+		if (maxfd < sp[i])
+			maxfd = sp[i];
 	}
 
 
@@ -408,25 +440,32 @@
 		   forever */
 		log_close();
 
-		FD_ZERO(&fds);
-		FD_SET(s, &fds);
+#ifdef FD_COPY
+		FD_COPY(&deffds, &fds);
+#else
+		fds = deffds;
+#endif
 
-		if (select(s+1, &fds, NULL, NULL, NULL) != 1)
+		if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
 			continue;
 
-		if (!FD_ISSET(s, &fds))
-			continue;
+		fd = -1;
+		for (i = 1; i <= *sp; i++) {
+			if (FD_ISSET(sp[i], &fds)) {
+				fd = accept(sp[i], (struct sockaddr *)&addr,
+					    &addrlen);
+				break;
+			}
+		}
 
-		fd = accept(s,(struct sockaddr *)&addr,&addrlen);
-
-		if (fd == -1)
+		if (fd < 0)
 			continue;
 
 		signal(SIGCHLD, sigchld_handler);
 
 		if ((pid = fork()) == 0) {
 			int ret;
-			close(s);
+			close(sp[i]);
 			/* open log file in child before possibly giving
 			   up privileges  */
 			log_open();
@@ -448,6 +487,7 @@
 			close(fd);
 		}
 	}
+	free(sp);
 }