From f9c87be6b42dd0f8b31a4bb8c6a44326879fdd1a Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Thu, 4 Nov 2010 02:35:19 +0100 Subject: [PATCH] daemon: get remote host address from root-process 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 Signed-off-by: Junio C Hamano --- daemon.c | 79 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/daemon.c b/daemon.c index 941c095df4..8162f10ffc 100644 --- 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();