iFirst version of multi listen. - geomyidae - A small C-based gopherd. Err bitreich.org 70 hgit clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ URL:git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ bitreich.org 70 1Log /scm/geomyidae/log.gph bitreich.org 70 1Files /scm/geomyidae/files.gph bitreich.org 70 1Refs /scm/geomyidae/refs.gph bitreich.org 70 1Tags /scm/geomyidae/tag bitreich.org 70 1README /scm/geomyidae/file/README.gph bitreich.org 70 1LICENSE /scm/geomyidae/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 60f33bbe3b6c58d451dad69933c1eb8b36cf3997 /scm/geomyidae/commit/60f33bbe3b6c58d451dad69933c1eb8b36cf3997.gph bitreich.org 70 1parent 3c940036398f0c5cb4b3822cb6f8ea1a76e2c968 /scm/geomyidae/commit/3c940036398f0c5cb4b3822cb6f8ea1a76e2c968.gph bitreich.org 70 hAuthor: Christoph Lohmann <20h@r-36.net> URL:mailto:20h@r-36.net bitreich.org 70 iDate: Sun, 11 Nov 2018 13:02:32 +0100 Err bitreich.org 70 i Err bitreich.org 70 iFirst version of multi listen. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M main.c | 212 +++++++++++++++++++++++-------- Err bitreich.org 70 i Err bitreich.org 70 i1 file changed, 156 insertions(+), 56 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/main.c b/main.c /scm/geomyidae/file/main.c.gph bitreich.org 70 i@@ -24,6 +24,8 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i Err bitreich.org 70 i #include "ind.h" Err bitreich.org 70 i #include "handlr.h" Err bitreich.org 70 i@@ -40,7 +42,8 @@ enum { Err bitreich.org 70 i Err bitreich.org 70 i int glfd = -1; Err bitreich.org 70 i int loglvl = 15; Err bitreich.org 70 i-int listfd = -1; Err bitreich.org 70 i+int *listfds = NULL; Err bitreich.org 70 i+int nlistfds = 0; Err bitreich.org 70 i int revlookup = 1; Err bitreich.org 70 i char *logfile = NULL; Err bitreich.org 70 i Err bitreich.org 70 i@@ -253,6 +256,8 @@ handlerequest(int sock, char *base, char *ohost, char *port, char *clienth, Err bitreich.org 70 i void Err bitreich.org 70 i sighandler(int sig) Err bitreich.org 70 i { Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i switch (sig) { Err bitreich.org 70 i case SIGCHLD: Err bitreich.org 70 i while (waitpid(-1, NULL, WNOHANG) > 0); Err bitreich.org 70 i@@ -266,9 +271,13 @@ sighandler(int sig) Err bitreich.org 70 i close(glfd); Err bitreich.org 70 i glfd = -1; Err bitreich.org 70 i } Err bitreich.org 70 i- if (listfd >= 0) { Err bitreich.org 70 i- shutdown(listfd, SHUT_RDWR); Err bitreich.org 70 i- close(listfd); Err bitreich.org 70 i+ if (listfds != NULL) { Err bitreich.org 70 i+ for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i+ if (listfds[i] >= 0) { Err bitreich.org 70 i+ shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i+ close(listfds[i]); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i } Err bitreich.org 70 i exit(0); Err bitreich.org 70 i break; Err bitreich.org 70 i@@ -295,60 +304,89 @@ initsignals(void) Err bitreich.org 70 i * TODO: Move Linux and BSD to Plan 9 socket and bind handling, so we do not Err bitreich.org 70 i * need the inconsistent return and exit on getaddrinfo. Err bitreich.org 70 i */ Err bitreich.org 70 i-int Err bitreich.org 70 i-getlistenfd(struct addrinfo *hints, char *bindip, char *port) Err bitreich.org 70 i+int * Err bitreich.org 70 i+getlistenfd(struct addrinfo *hints, char *bindip, char *port, int *rlfdnum) Err bitreich.org 70 i { Err bitreich.org 70 i char addstr[INET6_ADDRSTRLEN]; Err bitreich.org 70 i struct addrinfo *ai, *rp; Err bitreich.org 70 i void *sinaddr; Err bitreich.org 70 i- int on, listenfd, aierr, errno_save; Err bitreich.org 70 i+ int on, *listenfds, *listenfd, aierr, errno_save; Err bitreich.org 70 i Err bitreich.org 70 i if ((aierr = getaddrinfo(bindip, port, hints, &ai)) || ai == NULL) { Err bitreich.org 70 i fprintf(stderr, "getaddrinfo (%s:%s): %s\n", bindip, port, Err bitreich.org 70 i- gai_strerror(aierr)); Err bitreich.org 70 i+ gai_strerror(aierr)); Err bitreich.org 70 i exit(1); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- listenfd = -1; Err bitreich.org 70 i+ *rlfdnum = 0; Err bitreich.org 70 i+ listenfds = NULL; Err bitreich.org 70 i on = 1; Err bitreich.org 70 i for (rp = ai; rp != NULL; rp = rp->ai_next) { Err bitreich.org 70 i- listenfd = socket(rp->ai_family, rp->ai_socktype, Err bitreich.org 70 i+ printf("getaddrinfo result: %s:%d\n", rp->ai_canonname, Err bitreich.org 70 i+ rp->ai_protocol); Err bitreich.org 70 i+ listenfds = xrealloc(listenfds, Err bitreich.org 70 i+ sizeof(*listenfds) * (++*rlfdnum)); Err bitreich.org 70 i+ listenfd = &listenfds[*rlfdnum-1]; Err bitreich.org 70 i+ Err bitreich.org 70 i+ *listenfd = socket(rp->ai_family, rp->ai_socktype, Err bitreich.org 70 i rp->ai_protocol); Err bitreich.org 70 i- if (listenfd < 0) Err bitreich.org 70 i+ printf("*listenfd = %d\n", *listenfd); Err bitreich.org 70 i+ if (*listenfd < 0) Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ if (setsockopt(*listenfd, SOL_SOCKET, SO_REUSEADDR, &on, Err bitreich.org 70 i+ sizeof(on)) < 0) { Err bitreich.org 70 i+ printf("setsockopt failed\n"); Err bitreich.org 70 i+ close(*listenfd); Err bitreich.org 70 i+ (*rlfdnum)--; Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (rp->ai_family == AF_INET6 && (setsockopt(*listenfd, Err bitreich.org 70 i+ IPPROTO_IPV6, IPV6_V6ONLY, &on, Err bitreich.org 70 i+ sizeof(on)) < 0)) { Err bitreich.org 70 i+ printf("ipv6 only failed\n"); Err bitreich.org 70 i+ close(*listenfd); Err bitreich.org 70 i+ (*rlfdnum)--; Err bitreich.org 70 i continue; Err bitreich.org 70 i- if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, Err bitreich.org 70 i- sizeof(on)) < 0) { Err bitreich.org 70 i- close(listenfd); Err bitreich.org 70 i- listenfd = -1; Err bitreich.org 70 i- break; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i sinaddr = (rp->ai_family == AF_INET) ? Err bitreich.org 70 i (void *)&((struct sockaddr_in *)rp->ai_addr)->sin_addr : Err bitreich.org 70 i (void *)&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr; Err bitreich.org 70 i Err bitreich.org 70 i- if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) == 0) { Err bitreich.org 70 i+ if (bind(*listenfd, rp->ai_addr, rp->ai_addrlen) == 0) { Err bitreich.org 70 i if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr, Err bitreich.org 70 i- addstr, sizeof(addstr))) { Err bitreich.org 70 i+ addstr, sizeof(addstr))) { Err bitreich.org 70 i+ /* Do not revlookup here. */ Err bitreich.org 70 i+ on = revlookup; Err bitreich.org 70 i+ revlookup = 0; Err bitreich.org 70 i logentry(addstr, port, "-", "listening"); Err bitreich.org 70 i+ revlookup = on; Err bitreich.org 70 i } Err bitreich.org 70 i- break; Err bitreich.org 70 i+ continue; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i /* Save errno, because fprintf in logentry overwrites it. */ Err bitreich.org 70 i errno_save = errno; Err bitreich.org 70 i- close(listenfd); Err bitreich.org 70 i+ close(*listenfd); Err bitreich.org 70 i+ (*rlfdnum)--; Err bitreich.org 70 i if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr, Err bitreich.org 70 i- addstr, sizeof(addstr))) { Err bitreich.org 70 i+ addstr, sizeof(addstr))) { Err bitreich.org 70 i+ /* Do not revlookup here. */ Err bitreich.org 70 i+ on = revlookup; Err bitreich.org 70 i+ revlookup = 0; Err bitreich.org 70 i logentry(addstr, port, "-", "could not bind"); Err bitreich.org 70 i+ revlookup = on; Err bitreich.org 70 i } Err bitreich.org 70 i errno = errno_save; Err bitreich.org 70 i } Err bitreich.org 70 i freeaddrinfo(ai); Err bitreich.org 70 i- if (rp == NULL) Err bitreich.org 70 i- return -1; Err bitreich.org 70 i+ if (*rlfdnum < 1) { Err bitreich.org 70 i+ free(listenfds); Err bitreich.org 70 i+ return NULL; Err bitreich.org 70 i+ } Err bitreich.org 70 i Err bitreich.org 70 i- return listenfd; Err bitreich.org 70 i+ return listenfds; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i void Err bitreich.org 70 i@@ -367,11 +405,13 @@ main(int argc, char *argv[]) Err bitreich.org 70 i struct addrinfo hints; Err bitreich.org 70 i struct sockaddr_storage clt; Err bitreich.org 70 i socklen_t cltlen; Err bitreich.org 70 i- int sock, dofork, inetf, usechroot, nocgi, errno_save; Err bitreich.org 70 i+ int sock, dofork, inetf, usechroot, nocgi, errno_save, nbindips, i, j, Err bitreich.org 70 i+ nlfdret, *lfdret, listfd, maxlfd; Err bitreich.org 70 i char *port, *base, clienth[NI_MAXHOST], clientp[NI_MAXSERV]; Err bitreich.org 70 i- char *user, *group, *bindip, *ohost, *sport, *p; Err bitreich.org 70 i+ char *user, *group, **bindips, *ohost, *sport, *p; Err bitreich.org 70 i struct passwd *us; Err bitreich.org 70 i struct group *gr; Err bitreich.org 70 i+ fd_set rfd; Err bitreich.org 70 i Err bitreich.org 70 i base = stdbase; Err bitreich.org 70 i port = stdport; Err bitreich.org 70 i@@ -380,7 +420,8 @@ main(int argc, char *argv[]) Err bitreich.org 70 i group = NULL; Err bitreich.org 70 i us = NULL; Err bitreich.org 70 i gr = NULL; Err bitreich.org 70 i- bindip = NULL; Err bitreich.org 70 i+ bindips = NULL; Err bitreich.org 70 i+ nbindips = 0; Err bitreich.org 70 i ohost = NULL; Err bitreich.org 70 i sport = NULL; Err bitreich.org 70 i inetf = AF_UNSPEC; Err bitreich.org 70 i@@ -424,7 +465,8 @@ main(int argc, char *argv[]) Err bitreich.org 70 i group = EARGF(usage()); Err bitreich.org 70 i break; Err bitreich.org 70 i case 'i': Err bitreich.org 70 i- bindip = EARGF(usage()); Err bitreich.org 70 i+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i+ bindips[nbindips-1] = EARGF(usage()); Err bitreich.org 70 i break; Err bitreich.org 70 i case 'h': Err bitreich.org 70 i ohost = EARGF(usage()); Err bitreich.org 70 i@@ -502,34 +544,50 @@ main(int argc, char *argv[]) Err bitreich.org 70 i glfd = 1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- memset(&hints, 0, sizeof(hints)); Err bitreich.org 70 i- hints.ai_family = inetf; Err bitreich.org 70 i- hints.ai_flags = AI_PASSIVE; Err bitreich.org 70 i- hints.ai_socktype = SOCK_STREAM; Err bitreich.org 70 i- if (bindip) Err bitreich.org 70 i- hints.ai_flags |= AI_CANONNAME; Err bitreich.org 70 i- Err bitreich.org 70 i- if ((listfd = getlistenfd(&hints, bindip, port)) < 0) { Err bitreich.org 70 i- if (inetf == AF_UNSPEC) { Err bitreich.org 70 i- hints.ai_family = AF_INET; Err bitreich.org 70 i- listfd = getlistenfd(&hints, bindip, port); Err bitreich.org 70 i- } Err bitreich.org 70 i- /* Save errno because of fprintf to stderr. */ Err bitreich.org 70 i- errno_save = errno; Err bitreich.org 70 i- } Err bitreich.org 70 i- if (listfd < 0) { Err bitreich.org 70 i- fprintf(stderr, "Unable to get a binding socket. " Err bitreich.org 70 i- "Look at bindip and the tcp port.\n"); Err bitreich.org 70 i- errno = errno_save; Err bitreich.org 70 i- perror("getlistenfd"); Err bitreich.org 70 i- return 1; Err bitreich.org 70 i+ if (bindips == NULL) { Err bitreich.org 70 i+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i+ bindips[nbindips-1] = "0.0.0.0"; Err bitreich.org 70 i+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips)); Err bitreich.org 70 i+ bindips[nbindips-1] = "::"; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- if (listen(listfd, 255)) { Err bitreich.org 70 i- perror("listen"); Err bitreich.org 70 i- close(listfd); Err bitreich.org 70 i- return 1; Err bitreich.org 70 i+ for (i = 0; i < nbindips; i++) { Err bitreich.org 70 i+ printf("binding %s:%s\n", bindips[i], port); Err bitreich.org 70 i+ Err bitreich.org 70 i+ memset(&hints, 0, sizeof(hints)); Err bitreich.org 70 i+ hints.ai_family = inetf; Err bitreich.org 70 i+ hints.ai_flags = AI_PASSIVE; Err bitreich.org 70 i+ hints.ai_socktype = SOCK_STREAM; Err bitreich.org 70 i+ if (bindips[i]) Err bitreich.org 70 i+ hints.ai_flags |= AI_CANONNAME; Err bitreich.org 70 i+ Err bitreich.org 70 i+ nlfdret = 0; Err bitreich.org 70 i+ lfdret = getlistenfd(&hints, bindips[i], port, &nlfdret); Err bitreich.org 70 i+ if (nlfdret < 1) { Err bitreich.org 70 i+ errno_save = errno; Err bitreich.org 70 i+ fprintf(stderr, "Unable to get a binding socket for " Err bitreich.org 70 i+ "%s:%s\n", bindips[i], port); Err bitreich.org 70 i+ errno = errno_save; Err bitreich.org 70 i+ perror("getlistenfd"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ printf("nlfdret = %d\n", nlfdret); Err bitreich.org 70 i+ for (j = 0; j < nlfdret; j++) { Err bitreich.org 70 i+ printf("lfdret[%d] = %d\n", j, lfdret[j]); Err bitreich.org 70 i+ if (listen(lfdret[j], 255) < 0) { Err bitreich.org 70 i+ perror("listen"); Err bitreich.org 70 i+ close(lfdret[j]); Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ listfds = xrealloc(listfds, Err bitreich.org 70 i+ sizeof(*listfds) * ++nlistfds); Err bitreich.org 70 i+ listfds[nlistfds-1] = lfdret[j]; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (lfdret != NULL) Err bitreich.org 70 i+ free(lfdret); Err bitreich.org 70 i } Err bitreich.org 70 i+ if (nlistfds < 1) Err bitreich.org 70 i+ return 1; Err bitreich.org 70 i Err bitreich.org 70 i if (usechroot) { Err bitreich.org 70 i if (chdir(base) < 0) { Err bitreich.org 70 i@@ -552,7 +610,15 @@ main(int argc, char *argv[]) Err bitreich.org 70 i Err bitreich.org 70 i if (dropprivileges(gr, us) < 0) { Err bitreich.org 70 i perror("dropprivileges"); Err bitreich.org 70 i- close(listfd); Err bitreich.org 70 i+ if (listfds != NULL) { Err bitreich.org 70 i+ for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i+ if (listfds[i] >= 0) { Err bitreich.org 70 i+ shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i+ close(listfds[i]); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free(listfds); Err bitreich.org 70 i+ } Err bitreich.org 70 i return 1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -569,7 +635,34 @@ main(int argc, char *argv[]) Err bitreich.org 70 i #endif /* __OpenBSD__ */ Err bitreich.org 70 i Err bitreich.org 70 i while (1) { Err bitreich.org 70 i+ FD_ZERO(&rfd); Err bitreich.org 70 i+ maxlfd = 0; Err bitreich.org 70 i+ for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i+ FD_SET(listfds[i], &rfd); Err bitreich.org 70 i+ if (listfds[i] > maxlfd) Err bitreich.org 70 i+ maxlfd = listfds[i]; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ printf("pselect\n"); Err bitreich.org 70 i+ if (pselect(maxlfd+1, &rfd, NULL, NULL, NULL, NULL) < 0) { Err bitreich.org 70 i+ if (errno == EINTR) Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ perror("pselect"); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ listfd = -1; Err bitreich.org 70 i+ for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i+ if (FD_ISSET(listfds[i], &rfd)) { Err bitreich.org 70 i+ listfd = listfds[i]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (listfd < 0) Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ Err bitreich.org 70 i cltlen = sizeof(clt); Err bitreich.org 70 i+ printf("accept on %d\n", listfd); Err bitreich.org 70 i sock = accept(listfd, (struct sockaddr *)&clt, &cltlen); Err bitreich.org 70 i if (sock < 0) { Err bitreich.org 70 i switch (errno) { Err bitreich.org 70 i@@ -638,8 +731,15 @@ main(int argc, char *argv[]) Err bitreich.org 70 i close(sock); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- shutdown(listfd, SHUT_RDWR); Err bitreich.org 70 i- close(listfd); Err bitreich.org 70 i+ if (listfds != NULL) { Err bitreich.org 70 i+ for (i = 0; i < nlistfds; i++) { Err bitreich.org 70 i+ if (listfds[i] >= 0) { Err bitreich.org 70 i+ shutdown(listfds[i], SHUT_RDWR); Err bitreich.org 70 i+ close(listfds[i]); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free(listfds); Err bitreich.org 70 i+ } Err bitreich.org 70 i if (logfile != NULL && glfd != -1) { Err bitreich.org 70 i close(glfd); Err bitreich.org 70 i glfd = -1; Err bitreich.org 70 .