{"thread":{"id":"1286","subject":"[PATCH 2/2] GIT: Listen on IPv6 as well, if available.","startedAt":"2005-07-21T13:10:49Z","lastAt":"2005-07-22T22:05:54Z","messageCount":4,"participants":["YOSHIFUJI Hideaki / 吉藤英明","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"6293","messageId":"20050721.091049.46807257.yoshfuji@linux-ipv6.org","threadId":"1286","inReplyTo":null,"subject":"[PATCH 2/2] GIT: Listen on IPv6 as well, if available.","fromName":"YOSHIFUJI Hideaki / 吉藤英明","fromEmail":"yoshfuji@linux-ipv6.org","sentAt":"2005-07-21T13:10:49Z","receivedAt":"2005-07-21T13:10:49Z","isPatch":true,"sender":{"key":"yoshfuji@linux-ipv6.org","avatar":"https://gravatar.com/avatar/92c288bb8d3e34afd7bb1574cc1079a3d0aa6d36d80955d1ec6a1cea2868d392?d=mp&s=160"},"body":"Hello.\n\nListen on IPv6 as well, if available.\n\nSigned-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>\n\ndiff --git a/daemon.c b/daemon.c\n--- a/daemon.c\n+++ b/daemon.c\n@@ -3,8 +3,8 @@\n #include <signal.h>\n #include <sys/wait.h>\n #include <sys/socket.h>\n+#include <netdb.h>\n #include <netinet/in.h>\n-#include <arpa/inet.h>\n \n static const char daemon_usage[] = \"git-daemon [--inetd | --port=n]\";\n \n@@ -79,15 +79,15 @@ static unsigned int children_deleted = 0\n \n struct child {\n \tpid_t pid;\n-\tint addrlen;\n-\tstruct sockaddr_in address;\n+\tsocklen_t addrlen;\n+\tstruct sockaddr_storage address;\n } live_child[MAX_CHILDREN];\n \n-static void add_child(int idx, pid_t pid, struct sockaddr_in *addr, int addrlen)\n+static void add_child(int idx, pid_t pid, struct sockaddr *addr, socklen_t addrlen)\n {\n \tlive_child[idx].pid = pid;\n \tlive_child[idx].addrlen = addrlen;\n-\tlive_child[idx].address = *addr;\n+\tmemcpy(&live_child[idx].address, addr, addrlen);\n }\n \n /*\n@@ -177,7 +177,7 @@ static void check_max_connections(void)\n \t}\n }\n \n-static void handle(int incoming, struct sockaddr_in *addr, int addrlen)\n+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)\n {\n \tpid_t pid = fork();\n \n@@ -219,37 +219,102 @@ static void child_handler(int signo)\n \n static int serve(int port)\n {\n-\tint sockfd;\n-\tstruct sockaddr_in addr;\n+\tstruct addrinfo hints, *ai0, *ai;\n+\tint gai;\n+\tint socknum = 0, *socklist = NULL;\n+\tint maxfd = -1;\n+\tfd_set fds_init, fds;\n+\tchar pbuf[NI_MAXSERV];\n \n \tsignal(SIGCHLD, child_handler);\n-\tsockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);\n-\tif (sockfd < 0)\n-\t\tdie(\"unable to open socket (%s)\", strerror(errno));\n-\tmemset(&addr, 0, sizeof(addr));\n-\taddr.sin_port = htons(port);\n-\taddr.sin_family = AF_INET;\n-\tif (bind(sockfd, (void *)&addr, sizeof(addr)) < 0)\n-\t\tdie(\"unable to bind to port %d (%s)\", port, strerror(errno));\n-\tif (listen(sockfd, 5) < 0)\n-\t\tdie(\"unable to listen to port %d (%s)\", port, strerror(errno));\n+\n+\tsprintf(pbuf, \"%d\", port);\n+\tmemset(&hints, 0, sizeof(hints));\n+\thints.ai_family = AF_UNSPEC;\n+\thints.ai_socktype = SOCK_STREAM;\n+\thints.ai_protocol = IPPROTO_TCP;\n+\thints.ai_flags = AI_PASSIVE;\n+\n+\tgai = getaddrinfo(NULL, pbuf, &hints, &ai0);\n+\tif (gai)\n+\t\tdie(\"getaddrinfo() failed: %s\\n\", gai_strerror(gai));\n+\n+\tFD_ZERO(&fds_init);\n+\n+\tfor (ai = ai0; ai; ai = ai->ai_next) {\n+\t\tint sockfd;\n+\t\tint *newlist;\n+#ifdef IPV6_V6ONLY\n+\t\tint on = 1;\n+#endif\n+\t\tsockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);\n+\t\tif (sockfd < 0)\n+\t\t\tcontinue;\n+\n+#ifdef IPV6_V6ONLY\n+\t\tif (ai->ai_family == AF_INET6) {\n+\t\t\tsetsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,\n+\t\t\t\t   &on, sizeof(on));\n+\t\t\t/* Note: error is not fatal */\n+\t\t}\n+#endif\n+\n+\t\tif (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {\n+\t\t\tclose(sockfd);\n+\t\t\tcontinue;\t/* not fatal */\n+\t\t}\n+\t\tif (listen(sockfd, 5) < 0) {\n+\t\t\tclose(sockfd);\n+\t\t\tcontinue;\t/* not fatal */\n+\t\t}\n+\n+\t\tnewlist = realloc(socklist, sizeof(int) * (socknum + 1));\n+\t\tif (!newlist)\n+\t\t\tdie(\"memory allocation failed: %s\", strerror(errno));\n+\n+\t\tsocklist = newlist;\n+\t\tsocklist[socknum++] = sockfd;\n+\n+\t\tFD_SET(sockfd, &fds_init);\n+\t\tif (maxfd < sockfd)\n+\t\t\tmaxfd = sockfd;\n+\t}\n+\n+\tfreeaddrinfo(ai0);\n+\n+\tif (socknum == 0)\n+\t\tdie(\"unable to allocate any listen sockets on port %u\", port);\n \n \tfor (;;) {\n-\t\tstruct sockaddr_in in;\n-\t\tsocklen_t addrlen = sizeof(in);\n-\t\tint incoming = accept(sockfd, (void *)&in, &addrlen);\n-\n-\t\tif (incoming < 0) {\n-\t\t\tswitch (errno) {\n-\t\t\tcase EAGAIN:\n-\t\t\tcase EINTR:\n-\t\t\tcase ECONNABORTED:\n-\t\t\t\tcontinue;\n-\t\t\tdefault:\n-\t\t\t\tdie(\"accept returned %s\", strerror(errno));\n+\t\tstruct sockaddr_storage ss;\n+\t\tsocklen_t sslen = sizeof(ss);\n+\n+\t\tint i;\n+\t\tfds = fds_init;\n+\t\t\n+\t\tif (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {\n+\t\t\t/* warning? */\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tfor (i = 0; i < socknum; i++) {\n+\t\t\tint sockfd = socklist[i];\n+\n+\t\t\tif (FD_ISSET(sockfd, &fds)) {\n+\t\t\t\tint incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);\n+\t\t\t\tif (incoming < 0) {\n+\t\t\t\t\tswitch (errno) {\n+\t\t\t\t\tcase EAGAIN:\n+\t\t\t\t\tcase EINTR:\n+\t\t\t\t\tcase ECONNABORTED:\n+\t\t\t\t\t\tcontinue;\n+\t\t\t\t\tdefault:\n+\t\t\t\t\t\tdie(\"accept returned %s\", strerror(errno));\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\thandle(incoming, (struct sockaddr *)&ss, sslen);\n \t\t\t}\n \t\t}\n-\t\thandle(incoming, &in, addrlen);\n \t}\n }\n \n\n-- \nYOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>\nGPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA\n"},{"id":"6323","messageId":"20050722212151.GI11916@pasky.ji.cz","threadId":"1286","inReplyTo":"20050721.091049.46807257.yoshfuji@linux-ipv6.org","subject":"Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-07-22T21:21:51Z","receivedAt":"2005-07-22T21:21:51Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, Jul 21, 2005 at 03:10:49PM CEST, I got a letter\nwhere \"YOSHIFUJI Hideaki / ?$B5HF#1QL@\" <yoshfuji@linux-ipv6.org> told me that...\n> Hello.\n\nHello from an IPv6 fan,\n\n> Listen on IPv6 as well, if available.\n> \n> Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>\n> \n> diff --git a/daemon.c b/daemon.c\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -219,37 +219,102 @@ static void child_handler(int signo)\n>  \n>  static int serve(int port)\n>  {\n..snip..\n\nthis whole getaddrinfo() magic looks horribly complicated. What's wrong\non just adding a similar code (or factoring it out to a function) for\nIPv6 as there is for IPv4, just s/INET/INET6/?\n\n>  \tfor (;;) {\n> -\t\tstruct sockaddr_in in;\n> -\t\tsocklen_t addrlen = sizeof(in);\n> -\t\tint incoming = accept(sockfd, (void *)&in, &addrlen);\n> -\n> -\t\tif (incoming < 0) {\n> -\t\t\tswitch (errno) {\n> -\t\t\tcase EAGAIN:\n> -\t\t\tcase EINTR:\n> -\t\t\tcase ECONNABORTED:\n> -\t\t\t\tcontinue;\n> -\t\t\tdefault:\n> -\t\t\t\tdie(\"accept returned %s\", strerror(errno));\n> +\t\tstruct sockaddr_storage ss;\n> +\t\tsocklen_t sslen = sizeof(ss);\n\nPerhaps move those to the most inner block. (All right, I'm nitpicking\ntoo much again, sorry.)\n\n> +\n> +\t\tint i;\n> +\t\tfds = fds_init;\n> +\t\t\n> +\t\tif (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {\n> +\t\t\t/* warning? */\n\nCertainly a warning and at least sleep(1) to avoid cpuburn-like\nbehaviour in case of anything going wrong.\n\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tfor (i = 0; i < socknum; i++) {\n> +\t\t\tint sockfd = socklist[i];\n> +\n> +\t\t\tif (FD_ISSET(sockfd, &fds)) {\n> +\t\t\t\tint incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);\n> +\t\t\t\tif (incoming < 0) {\n> +\t\t\t\t\tswitch (errno) {\n> +\t\t\t\t\tcase EAGAIN:\n> +\t\t\t\t\tcase EINTR:\n> +\t\t\t\t\tcase ECONNABORTED:\n> +\t\t\t\t\t\tcontinue;\n> +\t\t\t\t\tdefault:\n> +\t\t\t\t\t\tdie(\"accept returned %s\", strerror(errno));\n> +\t\t\t\t\t}\n> +\t\t\t\t}\n> +\t\t\t\thandle(incoming, (struct sockaddr *)&ss, sslen);\n>  \t\t\t}\n>  \t\t}\n> -\t\thandle(incoming, &in, addrlen);\n>  \t}\n>  }\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nIf you want the holes in your knowledge showing up try teaching\nsomeone.  -- Alan Cox\n"},{"id":"6327","messageId":"20050722.173517.73563363.yoshfuji@linux-ipv6.org","threadId":"1286","inReplyTo":"20050722212151.GI11916@pasky.ji.cz","subject":"Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.","fromName":"YOSHIFUJI Hideaki / 吉藤英明","fromEmail":"yoshfuji@linux-ipv6.org","sentAt":"2005-07-22T21:35:17Z","receivedAt":"2005-07-22T21:35:17Z","isPatch":true,"sender":{"key":"yoshfuji@linux-ipv6.org","avatar":"https://gravatar.com/avatar/92c288bb8d3e34afd7bb1574cc1079a3d0aa6d36d80955d1ec6a1cea2868d392?d=mp&s=160"},"body":"In article <20050722212151.GI11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:21:51 +0200), Petr Baudis <pasky@suse.cz> says:\n\n\n> this whole getaddrinfo() magic looks horribly complicated. What's wrong\n> on just adding a similar code (or factoring it out to a function) for\n> IPv6 as there is for IPv4, just s/INET/INET6/?\n\nBecause it is the Good Way To Go; protocol independent programming.\n\n\n> > -\t\t\t\tdie(\"accept returned %s\", strerror(errno));\n> > +\t\tstruct sockaddr_storage ss;\n> > +\t\tsocklen_t sslen = sizeof(ss);\n> \n> Perhaps move those to the most inner block. (All right, I'm nitpicking\n> too much again, sorry.)\n> \n\nokay.\n\n> > +             if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {\n> > +                     /* warning? */\n> \n> Certainly a warning and at least sleep(1) to avoid cpuburn-like\n> behaviour in case of anything going wrong.\n\nokay...\n\n--yoshfuji\n"},{"id":"6331","messageId":"20050722220554.GL11916@pasky.ji.cz","threadId":"1286","inReplyTo":"20050722.173517.73563363.yoshfuji@linux-ipv6.org","subject":"Re: [PATCH 2/2] GIT: Listen on IPv6 as well, if available.","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-07-22T22:05:54Z","receivedAt":"2005-07-22T22:05:54Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Jul 22, 2005 at 11:35:17PM CEST, I got a letter\nwhere \"YOSHIFUJI Hideaki / ?$B5HF#1QL@\" <yoshfuji@linux-ipv6.org> told me that...\n> In article <20050722212151.GI11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:21:51 +0200), Petr Baudis <pasky@suse.cz> says:\n> > this whole getaddrinfo() magic looks horribly complicated. What's wrong\n> > on just adding a similar code (or factoring it out to a function) for\n> > IPv6 as there is for IPv4, just s/INET/INET6/?\n> \n> Because it is the Good Way To Go; protocol independent programming.\n\nI can see its merits, and it doesn't look so horrible after a while. ;-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nIf you want the holes in your knowledge showing up try teaching\nsomeone.  -- Alan Cox\n"}]}