Hi,

we had problems on FreeBSD-current. Attached is a patch we use on
FreeBSD-current. Find below the quote of the author of the patch. Maybe
it is possible to incorporate this patch into the next release of
rsync.

From [EMAIL PROTECTED]:

  "It seems the daemon mode of rsync depends on an IPv4-mapped IPv6
  address.  Since an IPv4-mapped IPv6 address is off by default on
  5-CURRENT, rsync doesn't listen on IPv4.  Further, rsync has a bug
  that it always listen on 1st entry's address of the result of
  getaddrinfo() call.  Please try attached patch.  With this patch,
  rsync listen on both an IPv4 and an IPv6."

Please Cc me since I am not on the list.

Regards,
         Olli
-- 
obraun@ -+-[ informatik.unibw-muenchen.de ]-+-[ IIS _ INF _ UniBwM ]
         |-[ FreeBSD.org                  ]-+-[ FreeBSD Commmitter ]
         |-[ unsane.org                   ]-+-[ everything __ else ]
Index: socket.c
diff -u socket.c.orig socket.c
--- socket.c.orig       Mon Jan 27 12:35:09 2003
+++ socket.c    Sat Feb  8 00:06:59 2003
@@ -292,11 +292,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, *socks, maxs;
        struct addrinfo hints, *all_ai, *resp;
        char portbuf[10];
        int error;
@@ -310,41 +310,65 @@
        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 may open */
+       for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++)
+               ;
+       socks = malloc((maxs + 1) * sizeof(int));
+       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. */
+       *socks = 0;   /* num of sockets counter at start of array */
+       s = socks + 1;
        for (resp = all_ai; resp; resp = resp->ai_next) {
-               s = socket(resp->ai_family, resp->ai_socktype,
+               *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,
+               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, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
+               if (bind(*s, resp->ai_addr, resp->ai_addrlen) < 0) {
                        /* Nope, try another */
-                       close(s);
+                       close(*s);
                        continue;
                }
 
-               freeaddrinfo(all_ai);
-               return s;
+               (*socks)++;
+               s++;
        }
 
-       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;
 }
 
 
@@ -376,19 +400,29 @@
 
 void start_accept_loop(int port, int (*fn)(int, int))
 {
-       int s;
+       fd_set deffds;
+       int *s, 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)
+       if (s == 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 <= *s; i++) {
+               if (listen(s[i], 5) == -1) {
+                       for (j = 1; j <= i; j++)
+                               close(s[j]);
+                       free(s);
+                       exit_cleanup(RERR_SOCKETIO);
+               }
+               FD_SET(s[i], &deffds);
+               if (maxfd < s[i])
+                       maxfd = s[i];
        }
 
 
@@ -406,16 +440,20 @@
                   forever */
                log_close();
 
-               FD_ZERO(&fds);
-               FD_SET(s, &fds);
+               FD_COPY(&deffds, &fds);
 
-               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 = accept(s,(struct sockaddr *)&addr,&addrlen);
+               fd = -1;
+               for (i = 1; i <= *s; i++) {
+                       if (FD_ISSET(s[i], &fds)) {
+                               fd = accept(s[i], (struct sockaddr *)&addr,
+                                           &addrlen);
+                               break;
+                       }
+               }
 
                if (fd == -1) continue;
 
@@ -430,7 +468,7 @@
 
                if ((pid = fork()) == 0) {
                        int ret;
-                       close(s);
+                       close(s[i]);
                        /* open log file in child before possibly giving
                           up privileges  */
                        log_open();
@@ -452,6 +490,7 @@
                        close(fd);
                }
        }
+       free(s);
 }
 
 

Attachment: pgp00000.pgp
Description: PGP signature

-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html

Reply via email to