* [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).