Introduction
Introduction Statistics Contact Development Disclaimer Help
First version of multi listen. - geomyidae - A small C-based gopherd.
git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfri…
Log
Files
Refs
Tags
README
LICENSE
---
commit 60f33bbe3b6c58d451dad69933c1eb8b36cf3997
parent 3c940036398f0c5cb4b3822cb6f8ea1a76e2c968
Author: Christoph Lohmann <[email protected]>
Date: Sun, 11 Nov 2018 13:02:32 +0100
First version of multi listen.
Diffstat:
M main.c | 212 +++++++++++++++++++++++------…
1 file changed, 156 insertions(+), 56 deletions(-)
---
diff --git a/main.c b/main.c
@@ -24,6 +24,8 @@
#include <errno.h>
#include <arpa/inet.h>
#include <limits.h>
+#include <sys/select.h>
+#include <sys/time.h>
#include "ind.h"
#include "handlr.h"
@@ -40,7 +42,8 @@ enum {
int glfd = -1;
int loglvl = 15;
-int listfd = -1;
+int *listfds = NULL;
+int nlistfds = 0;
int revlookup = 1;
char *logfile = NULL;
@@ -253,6 +256,8 @@ handlerequest(int sock, char *base, char *ohost, char *port…
void
sighandler(int sig)
{
+ int i;
+
switch (sig) {
case SIGCHLD:
while (waitpid(-1, NULL, WNOHANG) > 0);
@@ -266,9 +271,13 @@ sighandler(int sig)
close(glfd);
glfd = -1;
}
- if (listfd >= 0) {
- shutdown(listfd, SHUT_RDWR);
- close(listfd);
+ if (listfds != NULL) {
+ for (i = 0; i < nlistfds; i++) {
+ if (listfds[i] >= 0) {
+ shutdown(listfds[i], SHUT_RDWR);
+ close(listfds[i]);
+ }
+ }
}
exit(0);
break;
@@ -295,60 +304,89 @@ initsignals(void)
* TODO: Move Linux and BSD to Plan 9 socket and bind handling, so we do not
* need the inconsistent return and exit on getaddrinfo.
*/
-int
-getlistenfd(struct addrinfo *hints, char *bindip, char *port)
+int *
+getlistenfd(struct addrinfo *hints, char *bindip, char *port, int *rlfdnum)
{
char addstr[INET6_ADDRSTRLEN];
struct addrinfo *ai, *rp;
void *sinaddr;
- int on, listenfd, aierr, errno_save;
+ int on, *listenfds, *listenfd, aierr, errno_save;
if ((aierr = getaddrinfo(bindip, port, hints, &ai)) || ai == NULL) {
fprintf(stderr, "getaddrinfo (%s:%s): %s\n", bindip, port,
- gai_strerror(aierr));
+ gai_strerror(aierr));
exit(1);
}
- listenfd = -1;
+ *rlfdnum = 0;
+ listenfds = NULL;
on = 1;
for (rp = ai; rp != NULL; rp = rp->ai_next) {
- listenfd = socket(rp->ai_family, rp->ai_socktype,
+ printf("getaddrinfo result: %s:%d\n", rp->ai_canonname,
+ rp->ai_protocol);
+ listenfds = xrealloc(listenfds,
+ sizeof(*listenfds) * (++*rlfdnum));
+ listenfd = &listenfds[*rlfdnum-1];
+
+ *listenfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
- if (listenfd < 0)
+ printf("*listenfd = %d\n", *listenfd);
+ if (*listenfd < 0)
+ continue;
+ if (setsockopt(*listenfd, SOL_SOCKET, SO_REUSEADDR, &on,
+ sizeof(on)) < 0) {
+ printf("setsockopt failed\n");
+ close(*listenfd);
+ (*rlfdnum)--;
+ continue;
+ }
+
+ if (rp->ai_family == AF_INET6 && (setsockopt(*listenfd,
+ IPPROTO_IPV6, IPV6_V6ONLY, &on,
+ sizeof(on)) < 0)) {
+ printf("ipv6 only failed\n");
+ close(*listenfd);
+ (*rlfdnum)--;
continue;
- if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on,
- sizeof(on)) < 0) {
- close(listenfd);
- listenfd = -1;
- break;
}
sinaddr = (rp->ai_family == AF_INET) ?
(void *)&((struct sockaddr_in *)rp->ai_addr)->sin_ad…
(void *)&((struct sockaddr_in6 *)rp->ai_addr)->sin6_…
- if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) == 0) {
+ if (bind(*listenfd, rp->ai_addr, rp->ai_addrlen) == 0) {
if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr,
- addstr, sizeof(addstr))) {
+ addstr, sizeof(addstr))) {
+ /* Do not revlookup here. */
+ on = revlookup;
+ revlookup = 0;
logentry(addstr, port, "-", "listening");
+ revlookup = on;
}
- break;
+ continue;
}
/* Save errno, because fprintf in logentry overwrites it. */
errno_save = errno;
- close(listenfd);
+ close(*listenfd);
+ (*rlfdnum)--;
if (loglvl & CONN && inet_ntop(rp->ai_family, sinaddr,
- addstr, sizeof(addstr))) {
+ addstr, sizeof(addstr))) {
+ /* Do not revlookup here. */
+ on = revlookup;
+ revlookup = 0;
logentry(addstr, port, "-", "could not bind");
+ revlookup = on;
}
errno = errno_save;
}
freeaddrinfo(ai);
- if (rp == NULL)
- return -1;
+ if (*rlfdnum < 1) {
+ free(listenfds);
+ return NULL;
+ }
- return listenfd;
+ return listenfds;
}
void
@@ -367,11 +405,13 @@ main(int argc, char *argv[])
struct addrinfo hints;
struct sockaddr_storage clt;
socklen_t cltlen;
- int sock, dofork, inetf, usechroot, nocgi, errno_save;
+ int sock, dofork, inetf, usechroot, nocgi, errno_save, nbindips, i, j,
+ nlfdret, *lfdret, listfd, maxlfd;
char *port, *base, clienth[NI_MAXHOST], clientp[NI_MAXSERV];
- char *user, *group, *bindip, *ohost, *sport, *p;
+ char *user, *group, **bindips, *ohost, *sport, *p;
struct passwd *us;
struct group *gr;
+ fd_set rfd;
base = stdbase;
port = stdport;
@@ -380,7 +420,8 @@ main(int argc, char *argv[])
group = NULL;
us = NULL;
gr = NULL;
- bindip = NULL;
+ bindips = NULL;
+ nbindips = 0;
ohost = NULL;
sport = NULL;
inetf = AF_UNSPEC;
@@ -424,7 +465,8 @@ main(int argc, char *argv[])
group = EARGF(usage());
break;
case 'i':
- bindip = EARGF(usage());
+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips));
+ bindips[nbindips-1] = EARGF(usage());
break;
case 'h':
ohost = EARGF(usage());
@@ -502,34 +544,50 @@ main(int argc, char *argv[])
glfd = 1;
}
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = inetf;
- hints.ai_flags = AI_PASSIVE;
- hints.ai_socktype = SOCK_STREAM;
- if (bindip)
- hints.ai_flags |= AI_CANONNAME;
-
- if ((listfd = getlistenfd(&hints, bindip, port)) < 0) {
- if (inetf == AF_UNSPEC) {
- hints.ai_family = AF_INET;
- listfd = getlistenfd(&hints, bindip, port);
- }
- /* Save errno because of fprintf to stderr. */
- errno_save = errno;
- }
- if (listfd < 0) {
- fprintf(stderr, "Unable to get a binding socket. "
- "Look at bindip and the tcp port.\n");
- errno = errno_save;
- perror("getlistenfd");
- return 1;
+ if (bindips == NULL) {
+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips));
+ bindips[nbindips-1] = "0.0.0.0";
+ bindips = xrealloc(bindips, sizeof(*bindips) * (++nbindips));
+ bindips[nbindips-1] = "::";
}
- if (listen(listfd, 255)) {
- perror("listen");
- close(listfd);
- return 1;
+ for (i = 0; i < nbindips; i++) {
+ printf("binding %s:%s\n", bindips[i], port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = inetf;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_STREAM;
+ if (bindips[i])
+ hints.ai_flags |= AI_CANONNAME;
+
+ nlfdret = 0;
+ lfdret = getlistenfd(&hints, bindips[i], port, &nlfdret);
+ if (nlfdret < 1) {
+ errno_save = errno;
+ fprintf(stderr, "Unable to get a binding socket for "
+ "%s:%s\n", bindips[i], port);
+ errno = errno_save;
+ perror("getlistenfd");
+ }
+
+ printf("nlfdret = %d\n", nlfdret);
+ for (j = 0; j < nlfdret; j++) {
+ printf("lfdret[%d] = %d\n", j, lfdret[j]);
+ if (listen(lfdret[j], 255) < 0) {
+ perror("listen");
+ close(lfdret[j]);
+ continue;
+ }
+ listfds = xrealloc(listfds,
+ sizeof(*listfds) * ++nlistfds);
+ listfds[nlistfds-1] = lfdret[j];
+ }
+ if (lfdret != NULL)
+ free(lfdret);
}
+ if (nlistfds < 1)
+ return 1;
if (usechroot) {
if (chdir(base) < 0) {
@@ -552,7 +610,15 @@ main(int argc, char *argv[])
if (dropprivileges(gr, us) < 0) {
perror("dropprivileges");
- close(listfd);
+ if (listfds != NULL) {
+ for (i = 0; i < nlistfds; i++) {
+ if (listfds[i] >= 0) {
+ shutdown(listfds[i], SHUT_RDWR);
+ close(listfds[i]);
+ }
+ }
+ free(listfds);
+ }
return 1;
}
@@ -569,7 +635,34 @@ main(int argc, char *argv[])
#endif /* __OpenBSD__ */
while (1) {
+ FD_ZERO(&rfd);
+ maxlfd = 0;
+ for (i = 0; i < nlistfds; i++) {
+ FD_SET(listfds[i], &rfd);
+ if (listfds[i] > maxlfd)
+ maxlfd = listfds[i];
+ }
+
+ printf("pselect\n");
+ if (pselect(maxlfd+1, &rfd, NULL, NULL, NULL, NULL) < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("pselect");
+ break;
+ }
+
+ listfd = -1;
+ for (i = 0; i < nlistfds; i++) {
+ if (FD_ISSET(listfds[i], &rfd)) {
+ listfd = listfds[i];
+ break;
+ }
+ }
+ if (listfd < 0)
+ continue;
+
cltlen = sizeof(clt);
+ printf("accept on %d\n", listfd);
sock = accept(listfd, (struct sockaddr *)&clt, &cltlen);
if (sock < 0) {
switch (errno) {
@@ -638,8 +731,15 @@ main(int argc, char *argv[])
close(sock);
}
- shutdown(listfd, SHUT_RDWR);
- close(listfd);
+ if (listfds != NULL) {
+ for (i = 0; i < nlistfds; i++) {
+ if (listfds[i] >= 0) {
+ shutdown(listfds[i], SHUT_RDWR);
+ close(listfds[i]);
+ }
+ }
+ free(listfds);
+ }
if (logfile != NULL && glfd != -1) {
close(glfd);
glfd = -1;
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.