[PATCH/RFC] added possibility to supply more than one --listen argument to git-daemon

2 messages, 1 author, 2016-06-15 · open the first message on its own page

[PATCH/RFC] added possibility to supply more than one --listen argument to git-daemon

From: Alexander Sulfrian <hidden>
Date: 2016-06-15 22:49:17

Hi list,

I have written a patch to allow more than one --listen argument to the
git daemon. The current situation is, that the daemon silently ignores
all --listen arguments beside the last one. So there is no possibility
to let on server listen on many addresses without let it bind to all.

Even if that is currently not a problem with ipv4 addresses, in the
future that problem gets even worse. I wanted git-daemon to listen on
an ipv4 address and an ipv6 address. That is currently not possible
without running two instances. So I created that patch.

What do you think?

Thanks,
Alex


PS: This is my first patch for git.git, so please point out if I done
    something technically wrong.

[PATCH/RFC] added possibility to supply more than one --listen argument to git-daemon

From: Alexander Sulfrian <hidden>
Date: 2016-06-15 22:49:17

--listen arguments are gathered in a string_list
serve and socksetup get listen_addr as string_list
socketsetup creates a listen socket for each host in that string_list

Signed-off-by: Alexander Sulfrian <redacted>
---
 daemon.c |  183 ++++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 107 insertions(+), 76 deletions(-)
diff --git a/daemon.c b/daemon.c
index e22a2b7..f4492fe 100644
--- a/daemon.c
+++ b/daemon.c
@@ -3,6 +3,7 @@
 #include "exec_cmd.h"
 #include "run-command.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 #include <syslog.h>
 
@@ -736,7 +737,7 @@ static int set_reuse_addr(int sockfd)
 
 #ifndef NO_IPV6
 
-static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
+static int socksetup(struct string_list *listen_addr, int listen_port, int **socklist_p)
 {
 	int socknum = 0, *socklist = NULL;
 	int maxfd = -1;
@@ -744,6 +745,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 	struct addrinfo hints, *ai0, *ai;
 	int gai;
 	long flags;
+	int i;
 
 	sprintf(pbuf, "%d", listen_port);
 	memset(&hints, 0, sizeof(hints));
@@ -752,57 +754,69 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 	hints.ai_protocol = IPPROTO_TCP;
 	hints.ai_flags = AI_PASSIVE;
 
-	gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
-	if (gai)
-		die("getaddrinfo() failed: %s", gai_strerror(gai));
+	i = 0;
+	do {
+		if (listen_addr->nr > 0) {
+			gai = getaddrinfo(listen_addr->items[i].string, pbuf,
+					  &hints, &ai0);
+		}
+		else {
+			gai = getaddrinfo(NULL, pbuf, &hints, &ai0);
+		}
 
-	for (ai = ai0; ai; ai = ai->ai_next) {
-		int sockfd;
+		if (gai)
+			die("getaddrinfo() failed: %s", gai_strerror(gai));
 
-		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-		if (sockfd < 0)
-			continue;
-		if (sockfd >= FD_SETSIZE) {
-			logerror("Socket descriptor too large");
-			close(sockfd);
-			continue;
-		}
+		for (ai = ai0; ai; ai = ai->ai_next) {
+			int sockfd;
+
+			sockfd = socket(ai->ai_family, ai->ai_socktype,
+					ai->ai_protocol);
+			if (sockfd < 0)
+				continue;
+			if (sockfd >= FD_SETSIZE) {
+				logerror("Socket descriptor too large");
+				close(sockfd);
+				continue;
+			}
 
 #ifdef IPV6_V6ONLY
-		if (ai->ai_family == AF_INET6) {
-			int on = 1;
-			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
-				   &on, sizeof(on));
-			/* Note: error is not fatal */
-		}
+			if (ai->ai_family == AF_INET6) {
+				int on = 1;
+				setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
+					   &on, sizeof(on));
+				/* Note: error is not fatal */
+			}
 #endif
 
-		if (set_reuse_addr(sockfd)) {
-			close(sockfd);
-			continue;
-		}
+			if (set_reuse_addr(sockfd)) {
+				close(sockfd);
+				continue;
+			}
 
-		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 */
-		}
+			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 */
+			}
 
-		flags = fcntl(sockfd, F_GETFD, 0);
-		if (flags >= 0)
-			fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
+			flags = fcntl(sockfd, F_GETFD, 0);
+			if (flags >= 0)
+				fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
 
-		socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
-		socklist[socknum++] = sockfd;
+			socklist = xrealloc(socklist,
+					    sizeof(int) * (socknum + 1));
+			socklist[socknum++] = sockfd;
 
-		if (maxfd < sockfd)
-			maxfd = sockfd;
-	}
+			if (maxfd < sockfd)
+				maxfd = sockfd;
+		}
 
-	freeaddrinfo(ai0);
+		freeaddrinfo(ai0);
+	} while  (++i < listen_addr->nr);
 
 	*socklist_p = socklist;
 	return socknum;
@@ -810,50 +824,60 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 
 #else /* NO_IPV6 */
 
-static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
+static int socksetup(struct string_list *listen_addr, int listen_port, int **socklist_p)
 {
+	int socknum = 0, *socklist = NULL;
 	struct sockaddr_in sin;
 	int sockfd;
 	long flags;
+	int i;
 
 	memset(&sin, 0, sizeof sin);
 	sin.sin_family = AF_INET;
 	sin.sin_port = htons(listen_port);
 
-	if (listen_addr) {
-		/* Well, host better be an IP address here. */
-		if (inet_pton(AF_INET, listen_addr, &sin.sin_addr.s_addr) <= 0)
+	i = 0;
+	do {
+		if (listen_addr->nr > 0) {
+			/* Well, host better be an IP address here. */
+			if (inet_pton(AF_INET, listen_addr->items[i].string,
+				      &sin.sin_addr.s_addr) <= 0)
+				return 0;
+		}
+		else {
+			sin.sin_addr.s_addr = htonl(INADDR_ANY);
+		}
+
+		sockfd = socket(AF_INET, SOCK_STREAM, 0);
+		if (sockfd < 0)
 			return 0;
-	} else {
-		sin.sin_addr.s_addr = htonl(INADDR_ANY);
-	}
 
-	sockfd = socket(AF_INET, SOCK_STREAM, 0);
-	if (sockfd < 0)
-		return 0;
+		if (set_reuse_addr(sockfd)) {
+			close(sockfd);
+			return 0;
+		}
 
-	if (set_reuse_addr(sockfd)) {
-		close(sockfd);
-		return 0;
-	}
+		if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
+			close(sockfd);
+			return 0;
+		}
 
-	if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
-		close(sockfd);
-		return 0;
-	}
+		if (listen(sockfd, 5) < 0) {
+			close(sockfd);
+			return 0;
+		}
 
-	if (listen(sockfd, 5) < 0) {
-		close(sockfd);
-		return 0;
-	}
+		flags = fcntl(sockfd, F_GETFD, 0);
+		if (flags >= 0)
+			fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
 
-	flags = fcntl(sockfd, F_GETFD, 0);
-	if (flags >= 0)
-		fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
+		socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
+		socklist[socknum++] = sockfd;
 
-	*socklist_p = xmalloc(sizeof(int));
-	**socklist_p = sockfd;
-	return 1;
+	} while (++i < listen_addr->nr);
+
+	*socklist_p = socklist;
+	return socknum;
 }
 
 #endif
@@ -946,14 +970,14 @@ static void store_pid(const char *path)
 		die_errno("failed to write pid file '%s'", path);
 }
 
-static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
+static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
 {
 	int socknum, *socklist;
 
 	socknum = socksetup(listen_addr, listen_port, &socklist);
 	if (socknum == 0)
-		die("unable to allocate any listen sockets on host %s port %u",
-		    listen_addr, listen_port);
+		die("unable to allocate any listen sockets on port %u",
+		    listen_port);
 
 	if (pass && gid &&
 	    (initgroups(pass->pw_name, gid) || setgid (gid) ||
@@ -966,14 +990,17 @@ static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t
 int main(int argc, char **argv)
 {
 	int listen_port = 0;
-	char *listen_addr = NULL;
 	int inetd_mode = 0;
+	struct string_list listen_addr;
 	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 	int detach = 0;
 	struct passwd *pass = NULL;
 	struct group *group;
 	gid_t gid = 0;
 	int i;
+	int return_value;
+
+	memset(&listen_addr, 0, sizeof(struct string_list));
 
 	git_extract_argv0_path(argv[0]);
 
@@ -981,7 +1008,7 @@ int main(int argc, char **argv)
 		char *arg = argv[i];
 
 		if (!prefixcmp(arg, "--listen=")) {
-			listen_addr = xstrdup_tolower(arg + 9);
+			string_list_append(&listen_addr, xstrdup_tolower(arg + 9));
 			continue;
 		}
 		if (!prefixcmp(arg, "--port=")) {
@@ -1106,7 +1133,7 @@ int main(int argc, char **argv)
 	if (inetd_mode && (group_name || user_name))
 		die("--user and --group are incompatible with --inetd");
 
-	if (inetd_mode && (listen_port || listen_addr))
+	if (inetd_mode && (listen_port || (listen_addr.nr > 0)))
 		die("--listen= and --port= are incompatible with --inetd");
 	else if (listen_port == 0)
 		listen_port = DEFAULT_GIT_PORT;
@@ -1161,5 +1188,9 @@ int main(int argc, char **argv)
 	if (pid_file)
 		store_pid(pid_file);
 
-	return serve(listen_addr, listen_port, pass, gid);
+	return_value = serve(&listen_addr, listen_port, pass, gid);
+
+	string_list_clear(&listen_addr, 0);
+
+	return return_value;
 }
-- 
1.7.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help