NO_IPV6 support for git daemon
authorPeter Anvin <hpa@tazenda.sc.orionmulti.com>
Thu, 29 Sep 2005 00:26:44 +0000 (17:26 -0700)
committerPeter Anvin <hpa@tazenda.sc.orionmulti.com>
Thu, 29 Sep 2005 00:26:44 +0000 (17:26 -0700)
Makefile
connect.c
daemon.c

index be5c0a8..2183903 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -239,7 +239,7 @@ ifdef NO_STRCASESTR
        LIB_OBJS += compat/strcasestr.o
 endif
 ifdef NO_IPV6
-       DEFINES += -DNO_IPV6
+       DEFINES += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
 endif
 
 ifdef PPC_SHA1
index 39d320c..b157cf1 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -397,7 +397,7 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
 
                memset(&sa, 0, sizeof sa);
                sa.sin_family = he->h_addrtype;
-               sa.sin_port = nport;
+               sa.sin_port = htons(nport);
                memcpy(&sa.sin_addr, ap, he->h_length);
 
                if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
index a369ce5..79e72e0 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,9 +1,11 @@
 #include "cache.h"
 #include "pkt-line.h"
+#include <alloca.h>
 #include <signal.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/poll.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -328,6 +330,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
                inet_ntop(AF_INET, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
                port = sin_addr->sin_port;
 
+#ifndef NO_IPV6
        } else if (addr->sa_family == AF_INET6) {
                struct sockaddr_in6 *sin6_addr = (void *) addr;
 
@@ -337,6 +340,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
                strcat(buf, "]");
 
                port = sin6_addr->sin6_port;
+#endif
        }
        loginfo("Connection from %s:%d", addrbuf, port);
 
@@ -369,16 +373,17 @@ static void child_handler(int signo)
        }
 }
 
-static int serve(int port)
+#ifndef NO_IPV6
+
+static int socksetup(int port, int **socklist_p)
 {
-       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);
+       struct addrinfo hints, *ai0, *ai;
+       int gai;
 
        sprintf(pbuf, "%d", port);
        memset(&hints, 0, sizeof(hints));
@@ -438,16 +443,59 @@ static int serve(int port)
 
        freeaddrinfo(ai0);
 
-       if (socknum == 0)
-               die("unable to allocate any listen sockets on port %u", port);
+       *socklist_p = socklist;
+       return socknum;
+}
+
+#else /* NO_IPV6 */
+
+static int socksetup(int port, int **socklist_p)
+{
+       struct sockaddr_in sin;
+       int sockfd;
+
+       sockfd = socket(AF_INET, SOCK_STREAM, 0);
+       if (sockfd < 0)
+               return 0;
+
+       memset(&sin, 0, sizeof sin);
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = htonl(INADDR_ANY);
+       sin.sin_port = htons(port);
+
+       if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
+               close(sockfd);
+               return 0;
+       }
 
+       *socklist_p = malloc(sizeof(int));
+       if ( !*socklist_p )
+               die("memory allocation failed: %s", strerror(errno));
+       **socklist_p = sockfd;
+}
+
+#endif
+
+static int service_loop(int socknum, int *socklist)
+{
+       struct pollfd *pfd;
+       int i;
+
+       pfd = calloc(socknum, sizeof(struct pollfd));
+       if (!pfd)
+               die("memory allocation failed: %s", strerror(errno));
+
+       for (i = 0; i < socknum; i++) {
+               pfd[i].fd = socklist[i];
+               pfd[i].events = POLLIN;
+       }
+       
        for (;;) {
                int i;
-               fds = fds_init;
-               
-               if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {
+
+               if (poll(pfd, socknum, 0) < 0) {
                        if (errno != EINTR) {
-                               error("select failed, resuming: %s",
+                               error("poll failed, resuming: %s",
                                      strerror(errno));
                                sleep(1);
                        }
@@ -455,12 +503,10 @@ static int serve(int port)
                }
 
                for (i = 0; i < socknum; i++) {
-                       int sockfd = socklist[i];
-
-                       if (FD_ISSET(sockfd, &fds)) {
+                       if (pfd[i].revents & POLLIN) {
                                struct sockaddr_storage ss;
                                int sslen = sizeof(ss);
-                               int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen);
+                               int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
                                if (incoming < 0) {
                                        switch (errno) {
                                        case EAGAIN:
@@ -477,6 +523,19 @@ static int serve(int port)
        }
 }
 
+static int serve(int port)
+{
+       int socknum, *socklist;
+       
+       signal(SIGCHLD, child_handler);
+       
+       socknum = socksetup(port, &socklist);
+       if (socknum == 0)
+               die("unable to allocate any listen sockets on port %u", port);
+       
+       return service_loop(socknum, socklist);
+}      
+
 int main(int argc, char **argv)
 {
        int port = DEFAULT_GIT_PORT;
@@ -526,7 +585,7 @@ int main(int argc, char **argv)
        if (inetd_mode) {
                fclose(stderr); //FIXME: workaround
                return execute();
+       } else {
+               return serve(port);
        }
-
-       return serve(port);
 }