git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/2] GIT: Listen on IPv6 as well, if available.
@ 2005-07-21 13:10 YOSHIFUJI Hideaki / 吉藤英明
  2005-07-22 21:21 ` Petr Baudis
  0 siblings, 1 reply; 4+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-07-21 13:10 UTC (permalink / raw)
  To: git; +Cc: yoshfuji

Hello.

Listen on IPv6 as well, if available.

Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>

diff --git a/daemon.c b/daemon.c
--- a/daemon.c
+++ b/daemon.c
@@ -3,8 +3,8 @@
 #include <signal.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
+#include <netdb.h>
 #include <netinet/in.h>
-#include <arpa/inet.h>
 
 static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
 
@@ -79,15 +79,15 @@ static unsigned int children_deleted = 0
 
 struct child {
 	pid_t pid;
-	int addrlen;
-	struct sockaddr_in address;
+	socklen_t addrlen;
+	struct sockaddr_storage address;
 } live_child[MAX_CHILDREN];
 
-static void add_child(int idx, pid_t pid, struct sockaddr_in *addr, int addrlen)
+static void add_child(int idx, pid_t pid, struct sockaddr *addr, socklen_t addrlen)
 {
 	live_child[idx].pid = pid;
 	live_child[idx].addrlen = addrlen;
-	live_child[idx].address = *addr;
+	memcpy(&live_child[idx].address, addr, addrlen);
 }
 
 /*
@@ -177,7 +177,7 @@ static void check_max_connections(void)
 	}
 }
 
-static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
 	pid_t pid = fork();
 
@@ -219,37 +219,102 @@ static void child_handler(int signo)
 
 static int serve(int port)
 {
-	int sockfd;
-	struct sockaddr_in addr;
+	struct addrinfo hints, *ai0, *ai;
+	int gai;
+	int socknum = 0, *socklist = NULL;
+	int maxfd = -1;
+	fd_set fds_init, fds;
+	char pbuf[NI_MAXSERV];
 
 	signal(SIGCHLD, child_handler);
-	sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
-	if (sockfd < 0)
-		die("unable to open socket (%s)", strerror(errno));
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_port = htons(port);
-	addr.sin_family = AF_INET;
-	if (bind(sockfd, (void *)&addr, sizeof(addr)) < 0)
-		die("unable to bind to port %d (%s)", port, strerror(errno));
-	if (listen(sockfd, 5) < 0)
-		die("unable to listen to port %d (%s)", port, strerror(errno));
+
+	sprintf(pbuf, "%d", port);
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+	hints.ai_flags = AI_PASSIVE;
+
+	gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
+	if (gai)
+		die("getaddrinfo() failed: %s\n", gai_strerror(gai));
+
+	FD_ZERO(&fds_init);
+
+	for (ai = ai0; ai; ai = ai->ai_next) {
+		int sockfd;
+		int *newlist;
+#ifdef IPV6_V6ONLY
+		int on = 1;
+#endif
+		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+		if (sockfd < 0)
+			continue;
+
+#ifdef IPV6_V6ONLY
+		if (ai->ai_family == AF_INET6) {
+			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
+				   &on, sizeof(on));
+			/* Note: error is not fatal */
+		}
+#endif
+
+		if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
+			close(sockfd);
+			continue;	/* not fatal */
+		}
+		if (listen(sockfd, 5) < 0) {
+			close(sockfd);
+			continue;	/* not fatal */
+		}
+
+		newlist = realloc(socklist, sizeof(int) * (socknum + 1));
+		if (!newlist)
+			die("memory allocation failed: %s", strerror(errno));
+
+		socklist = newlist;
+		socklist[socknum++] = sockfd;
+
+		FD_SET(sockfd, &fds_init);
+		if (maxfd < sockfd)
+			maxfd = sockfd;
+	}
+
+	freeaddrinfo(ai0);
+
+	if (socknum == 0)
+		die("unable to allocate any listen sockets on port %u", port);
 
 	for (;;) {
-		struct sockaddr_in in;
-		socklen_t addrlen = sizeof(in);
-		int incoming = accept(sockfd, (void *)&in, &addrlen);
-
-		if (incoming < 0) {
-			switch (errno) {
-			case EAGAIN:
-			case EINTR:
-			case ECONNABORTED:
-				continue;
-			default:
-				die("accept returned %s", strerror(errno));
+		struct sockaddr_storage ss;
+		socklen_t sslen = sizeof(ss);
+
+		int i;
+		fds = fds_init;
+		
+		if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
+			/* warning? */
+			continue;
+		}
+
+		for (i = 0; i < socknum; i++) {
+			int sockfd = socklist[i];
+
+			if (FD_ISSET(sockfd, &fds)) {
+				int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
+				if (incoming < 0) {
+					switch (errno) {
+					case EAGAIN:
+					case EINTR:
+					case ECONNABORTED:
+						continue;
+					default:
+						die("accept returned %s", strerror(errno));
+					}
+				}
+				handle(incoming, (struct sockaddr *)&ss, sslen);
 			}
 		}
-		handle(incoming, &in, addrlen);
 	}
 }
 

-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.
  2005-07-21 13:10 [PATCH 2/2] GIT: Listen on IPv6 as well, if available YOSHIFUJI Hideaki / 吉藤英明
@ 2005-07-22 21:21 ` Petr Baudis
  2005-07-22 21:35   ` YOSHIFUJI Hideaki / 吉藤英明
  0 siblings, 1 reply; 4+ messages in thread
From: Petr Baudis @ 2005-07-22 21:21 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / ?$B5HF#1QL@; +Cc: git, yoshfuji

Dear diary, on Thu, Jul 21, 2005 at 03:10:49PM CEST, I got a letter
where "YOSHIFUJI Hideaki / ?$B5HF#1QL@" <yoshfuji@linux-ipv6.org> told me that...
> Hello.

Hello from an IPv6 fan,

> Listen on IPv6 as well, if available.
> 
> Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
> 
> diff --git a/daemon.c b/daemon.c
> --- a/daemon.c
> +++ b/daemon.c
> @@ -219,37 +219,102 @@ static void child_handler(int signo)
>  
>  static int serve(int port)
>  {
..snip..

this whole getaddrinfo() magic looks horribly complicated. What's wrong
on just adding a similar code (or factoring it out to a function) for
IPv6 as there is for IPv4, just s/INET/INET6/?

>  	for (;;) {
> -		struct sockaddr_in in;
> -		socklen_t addrlen = sizeof(in);
> -		int incoming = accept(sockfd, (void *)&in, &addrlen);
> -
> -		if (incoming < 0) {
> -			switch (errno) {
> -			case EAGAIN:
> -			case EINTR:
> -			case ECONNABORTED:
> -				continue;
> -			default:
> -				die("accept returned %s", strerror(errno));
> +		struct sockaddr_storage ss;
> +		socklen_t sslen = sizeof(ss);

Perhaps move those to the most inner block. (All right, I'm nitpicking
too much again, sorry.)

> +
> +		int i;
> +		fds = fds_init;
> +		
> +		if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
> +			/* warning? */

Certainly a warning and at least sleep(1) to avoid cpuburn-like
behaviour in case of anything going wrong.

> +			continue;
> +		}
> +
> +		for (i = 0; i < socknum; i++) {
> +			int sockfd = socklist[i];
> +
> +			if (FD_ISSET(sockfd, &fds)) {
> +				int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
> +				if (incoming < 0) {
> +					switch (errno) {
> +					case EAGAIN:
> +					case EINTR:
> +					case ECONNABORTED:
> +						continue;
> +					default:
> +						die("accept returned %s", strerror(errno));
> +					}
> +				}
> +				handle(incoming, (struct sockaddr *)&ss, sslen);
>  			}
>  		}
> -		handle(incoming, &in, addrlen);
>  	}
>  }

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
If you want the holes in your knowledge showing up try teaching
someone.  -- Alan Cox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.
  2005-07-22 21:21 ` Petr Baudis
@ 2005-07-22 21:35   ` YOSHIFUJI Hideaki / 吉藤英明
  2005-07-22 22:05     ` Petr Baudis
  0 siblings, 1 reply; 4+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2005-07-22 21:35 UTC (permalink / raw)
  To: pasky; +Cc: git, yoshfuji

In article <20050722212151.GI11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:21:51 +0200), Petr Baudis <pasky@suse.cz> says:


> this whole getaddrinfo() magic looks horribly complicated. What's wrong
> on just adding a similar code (or factoring it out to a function) for
> IPv6 as there is for IPv4, just s/INET/INET6/?

Because it is the Good Way To Go; protocol independent programming.


> > -				die("accept returned %s", strerror(errno));
> > +		struct sockaddr_storage ss;
> > +		socklen_t sslen = sizeof(ss);
> 
> Perhaps move those to the most inner block. (All right, I'm nitpicking
> too much again, sorry.)
> 

okay.

> > +             if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
> > +                     /* warning? */
> 
> Certainly a warning and at least sleep(1) to avoid cpuburn-like
> behaviour in case of anything going wrong.

okay...

--yoshfuji

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.
  2005-07-22 21:35   ` YOSHIFUJI Hideaki / 吉藤英明
@ 2005-07-22 22:05     ` Petr Baudis
  0 siblings, 0 replies; 4+ messages in thread
From: Petr Baudis @ 2005-07-22 22:05 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / ?$B5HF#1QL@; +Cc: git

Dear diary, on Fri, Jul 22, 2005 at 11:35:17PM CEST, I got a letter
where "YOSHIFUJI Hideaki / ?$B5HF#1QL@" <yoshfuji@linux-ipv6.org> told me that...
> In article <20050722212151.GI11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:21:51 +0200), Petr Baudis <pasky@suse.cz> says:
> > this whole getaddrinfo() magic looks horribly complicated. What's wrong
> > on just adding a similar code (or factoring it out to a function) for
> > IPv6 as there is for IPv4, just s/INET/INET6/?
> 
> Because it is the Good Way To Go; protocol independent programming.

I can see its merits, and it doesn't look so horrible after a while. ;-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
If you want the holes in your knowledge showing up try teaching
someone.  -- Alan Cox

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-07-22 22:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-21 13:10 [PATCH 2/2] GIT: Listen on IPv6 as well, if available YOSHIFUJI Hideaki / 吉藤英明
2005-07-22 21:21 ` Petr Baudis
2005-07-22 21:35   ` YOSHIFUJI Hideaki / 吉藤英明
2005-07-22 22:05     ` Petr Baudis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).