From owner-freebsd-current Fri Feb 7 7:30:26 2003 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A29F037B401; Fri, 7 Feb 2003 07:30:20 -0800 (PST) Received: from cheer.mahoroba.org (flets20-242.kamome.or.jp [218.45.20.242]) by mx1.FreeBSD.org (Postfix) with ESMTP id DC22243FBF; Fri, 7 Feb 2003 07:30:13 -0800 (PST) (envelope-from ume@mahoroba.org) Received: from lyrics.mahoroba.org (IDENT:ciRnoXDiBPM29QFkM7CK25TmIYAIfmJZ4PxDCaalJwMZdtPPxNhCr4sqwB5fTn23@lyrics.mahoroba.org [IPv6:3ffe:501:185b:8010:280:88ff:fe03:4841]) (user=ume mech=CRAM-MD5 bits=0) by cheer.mahoroba.org (8.12.7/8.12.7) with ESMTP/inet6 id h17FTuCQ094783 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO); Sat, 8 Feb 2003 00:29:56 +0900 (JST) (envelope-from ume@mahoroba.org) Date: Sat, 08 Feb 2003 00:29:56 +0900 Message-ID: From: Hajimu UMEMOTO To: David Rhodus Cc: "Sean Winn" , FreeBSD users , obraun@FreeBSD.org Subject: Re: rsync --daemon problems In-Reply-To: References: <007e01c2ce2f$8c403c80$f400a8c0@private.gothic.net.au> User-Agent: xcite1.38> Wanderlust/2.11.0 (Wonderwall) SEMI/1.14.5 (Awara-Onsen) FLIM/1.14.5 (Demachiyanagi) APEL/10.4 Emacs/21.2 (i386--freebsd) MULE/5.0 (=?ISO-2022-JP?B?GyRCOC1MWhsoQg==?=) X-Operating-System: FreeBSD 5.0-CURRENT MIME-Version: 1.0 (generated by SEMI 1.14.5 - "Awara-Onsen") Content-Type: multipart/mixed; boundary="Multipart_Sat_Feb__8_00:29:56_2003-1" X-Spam-Status: No, hits=-1.0 required=5.0 tests=IN_REP_TO,REFERENCES,SPAM_PHRASE_00_01,USER_AGENT version=2.44 Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --Multipart_Sat_Feb__8_00:29:56_2003-1 Content-Type: text/plain; charset=US-ASCII Hi, >>>>> On Thu, 6 Feb 2003 19:33:10 -0500 >>>>> David Rhodus said: david> On one machine that rsync start's on, I get this from netstat. david> tcp6 0 0 *.873 *.* david> LISTEN 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. Sincerely, --Multipart_Sat_Feb__8_00:29:56_2003-1 Content-Type: text/x-patch; charset=US-ASCII Content-Disposition: attachment; filename="patch-socket.c" Content-Transfer-Encoding: 7bit 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); } --Multipart_Sat_Feb__8_00:29:56_2003-1 Content-Type: text/plain; charset=US-ASCII -- Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan ume@mahoroba.org ume@bisd.hitachi.co.jp ume@{,jp.}FreeBSD.org http://www.imasy.org/~ume/ --Multipart_Sat_Feb__8_00:29:56_2003-1-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message