daemon: get remote host address from root-process
authorErik Faye-Lund <kusmabite@gmail.com>
Thu, 4 Nov 2010 01:35:19 +0000 (02:35 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 4 Nov 2010 23:53:51 +0000 (16:53 -0700)
Get remote host in the process that accept() and pass it through
the REMOTE_ADDR environment variable to the handler-process.
Introduce the REMOTE_PORT environmen variable for the port.

Use these variables for reporting instead of doing
getpeername(0, ...), which doesn't work on Windows.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
daemon.c

index 941c095df4530b700858afeb9a30187725dda4d3..8162f10ffc40523321ae0bd9cda7eb1cf535bfb6 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -516,37 +516,14 @@ static void parse_host_arg(char *extra_args, int buflen)
 }
 
 
-static int execute(struct sockaddr *addr)
+static int execute(void)
 {
        static char line[1000];
        int pktlen, len, i;
+       char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT");
 
-       if (addr) {
-               char addrbuf[256] = "";
-               int port = -1;
-
-               if (addr->sa_family == AF_INET) {
-                       struct sockaddr_in *sin_addr = (void *) addr;
-                       inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
-                       port = ntohs(sin_addr->sin_port);
-#ifndef NO_IPV6
-               } else if (addr && addr->sa_family == AF_INET6) {
-                       struct sockaddr_in6 *sin6_addr = (void *) addr;
-
-                       char *buf = addrbuf;
-                       *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
-                       inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
-                       strcat(buf, "]");
-
-                       port = ntohs(sin6_addr->sin6_port);
-#endif
-               }
-               loginfo("Connection from %s:%d", addrbuf, port);
-               setenv("REMOTE_ADDR", addrbuf, 1);
-       }
-       else {
-               unsetenv("REMOTE_ADDR");
-       }
+       if (addr)
+               loginfo("Connection from %s:%s", addr, port);
 
        alarm(init_timeout ? init_timeout : timeout);
        pktlen = packet_read_line(0, line, sizeof(line));
@@ -680,6 +657,8 @@ static char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
        struct child_process cld = { 0 };
+       char addrbuf[300] = "REMOTE_ADDR=", portbuf[300];
+       char *env[] = { addrbuf, portbuf, NULL };
 
        if (max_connections && live_children >= max_connections) {
                kill_some_child();
@@ -692,6 +671,28 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
                }
        }
 
+       if (addr->sa_family == AF_INET) {
+               struct sockaddr_in *sin_addr = (void *) addr;
+               inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf + 12,
+                   sizeof(addrbuf) - 12);
+               snprintf(portbuf, sizeof(portbuf), "REMOTE_PORT=%d",
+                   ntohs(sin_addr->sin_port));
+#ifndef NO_IPV6
+       } else if (addr && addr->sa_family == AF_INET6) {
+               struct sockaddr_in6 *sin6_addr = (void *) addr;
+
+               char *buf = addrbuf + 12;
+               *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
+               inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf,
+                   sizeof(addrbuf) - 13);
+               strcat(buf, "]");
+
+               snprintf(portbuf, sizeof(portbuf), "REMOTE_PORT=%d",
+                   ntohs(sin6_addr->sin6_port));
+#endif
+       }
+
+       cld.env = (const char **)env;
        cld.argv = (const char **)cld_argv;
        cld.in = incoming;
        cld.out = dup(incoming);
@@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)
 
                for (i = 0; i < socklist->nr; i++) {
                        if (pfd[i].revents & POLLIN) {
-                               struct sockaddr_storage ss;
+                               union {
+                                       struct sockaddr sa;
+                                       struct sockaddr_in sai;
+#ifndef NO_IPV6
+                                       struct sockaddr_in6 sai6;
+#endif
+                               } ss;
                                unsigned int sslen = sizeof(ss);
-                               int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
+                               int incoming = accept(pfd[i].fd, &ss.sa, &sslen);
                                if (incoming < 0) {
                                        switch (errno) {
                                        case EAGAIN:
@@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)
                                                die_errno("accept returned");
                                        }
                                }
-                               handle(incoming, (struct sockaddr *)&ss, sslen);
+                               handle(incoming, &ss.sa, sslen);
                        }
                }
        }
@@ -1160,16 +1167,8 @@ int main(int argc, char **argv)
                        die_errno("failed to redirect stderr to /dev/null");
        }
 
-       if (inetd_mode || serve_mode) {
-               struct sockaddr_storage ss;
-               struct sockaddr *peer = (struct sockaddr *)&ss;
-               socklen_t slen = sizeof(ss);
-
-               if (getpeername(0, peer, &slen))
-                       return execute(NULL);
-               else
-                       return execute(peer);
-       }
+       if (inetd_mode || serve_mode)
+               return execute();
 
        if (detach) {
                daemonize();