summaryrefslogtreecommitdiffstats
path: root/usr.sbin/inetd
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2014-10-29 03:33:14 +0000
committerdlg <dlg@openbsd.org>2014-10-29 03:33:14 +0000
commit8d1bc828ab25fd233e046999f7c7a0ca731dad8d (patch)
tree0c3ed306efe9b77a099735524cc29bc12fb9d657 /usr.sbin/inetd
parentIn terminal output, unify handling of Unicode and numbered character (diff)
downloadwireguard-openbsd-8d1bc828ab25fd233e046999f7c7a0ca731dad8d.tar.xz
wireguard-openbsd-8d1bc828ab25fd233e046999f7c7a0ca731dad8d.zip
replace the use of select and hand rolled deferral of signal handling
with libevent. this has been in snaps for a while without any negative (or positive) feedback. review and tweaks by bluhm@ nicm@ ok bluhm@ deraadt@
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r--usr.sbin/inetd/Makefile4
-rw-r--r--usr.sbin/inetd/inetd.c281
2 files changed, 75 insertions, 210 deletions
diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile
index ccdc58fe2e0..29b6f742f55 100644
--- a/usr.sbin/inetd/Makefile
+++ b/usr.sbin/inetd/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.3 2000/03/31 01:00:49 deraadt Exp $
+# $OpenBSD: Makefile,v 1.4 2014/10/29 03:33:14 dlg Exp $
PROG= inetd
+LDADD= -levent
+DPADD= ${LIBEVENT}
MAN= inetd.8
MLINKS= inetd.8 inetd.conf.5
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index 5863c7ae052..d74e11554a3 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inetd.c,v 1.141 2014/10/13 01:53:14 dlg Exp $ */
+/* $OpenBSD: inetd.c,v 1.142 2014/10/29 03:33:14 dlg Exp $ */
/*
* Copyright (c) 1983,1991 The Regents of the University of California.
@@ -151,6 +151,7 @@
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpcsvc/nfs_prot.h>
+#include <event.h>
#include "pathnames.h"
#define TOOMANY 256 /* don't start more than TOOMANY */
@@ -158,15 +159,11 @@
#define RETRYTIME (60*10) /* retry after bind or server fail */
int debug = 0;
-int nsock, maxsock;
-fd_set *allsockp;
-int allsockn;
+int maxsock;
int toomany = TOOMANY;
int timingout;
struct servent *sp;
uid_t uid;
-sigset_t blockmask;
-sigset_t emptymask;
#ifndef OPEN_MAX
#define OPEN_MAX 64
@@ -214,6 +211,7 @@ struct servtab {
int se_count; /* number started since se_time */
struct timeval se_time; /* start of se_count */
struct servtab *se_next;
+ struct event se_event;
} *servtab;
void echo_stream(int, struct servtab *);
@@ -257,21 +255,19 @@ struct biltin {
{ 0 }
};
-volatile sig_atomic_t wantretry;
-volatile sig_atomic_t wantconfig;
-volatile sig_atomic_t wantreap;
-volatile sig_atomic_t wantdie;
-
-void config(int);
-void doconfig(void);
-void reap(int);
-void doreap(void);
-void retry(int);
-void doretry(void);
-void die(int);
-void dodie(void);
-void spawn(struct servtab *, int);
-int gettcp(struct servtab *);
+struct event evsig_alrm;
+struct event evsig_hup;
+struct event evsig_chld;
+struct event evsig_term;
+struct event evsig_int;
+
+void config(int, short, void *);
+void reap(int, short, void *);
+void retry(int, short, void *);
+void die(int, short, void *);
+
+void spawn(int, short, void *);
+void gettcp(int, short, void *);
int setconfig(void);
void endconfig(void);
void register_rpc(struct servtab *);
@@ -288,40 +284,15 @@ int dg_broadcast(struct in_addr *in);
#define NUMINT (sizeof(intab) / sizeof(struct inent))
char *CONFIG = _PATH_INETDCONF;
-void fd_grow(fd_set **fdsp, int *bytes, int fd);
int dg_badinput(struct sockaddr *sa);
void inetd_setproctitle(char *a, int s);
void initring(void);
u_int32_t machtime(void);
-void
-fd_grow(fd_set **fdsp, int *bytes, int fd)
-{
- caddr_t new;
- int newbytes;
-
- newbytes = howmany(fd+1, NFDBITS) * sizeof(fd_mask);
- if (newbytes > *bytes) {
- newbytes *= 2; /* optimism */
- new = realloc(*fdsp, newbytes);
- if (new == NULL) {
- syslog(LOG_ERR, "Out of memory.");
- exit(1);
- }
- memset(new + *bytes, 0, newbytes - *bytes);
- *fdsp = (fd_set *)new;
- *bytes = newbytes;
- }
-}
-
-struct sigaction sa, sapipe;
-
int
main(int argc, char *argv[])
{
- fd_set *fdsrp = NULL;
- int readablen = 0, ch;
- struct servtab *sep;
+ int ch;
extern char *optarg;
extern int optind;
@@ -391,109 +362,38 @@ main(int argc, char *argv[])
rlim_nofile_cur = OPEN_MAX;
}
- sigemptyset(&emptymask);
- sigemptyset(&blockmask);
- sigaddset(&blockmask, SIGCHLD);
- sigaddset(&blockmask, SIGHUP);
- sigaddset(&blockmask, SIGALRM);
-
- memset(&sa, 0, sizeof(sa));
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGALRM);
- sigaddset(&sa.sa_mask, SIGCHLD);
- sigaddset(&sa.sa_mask, SIGHUP);
- sa.sa_handler = retry;
- sigaction(SIGALRM, &sa, NULL);
- doconfig();
- sa.sa_handler = config;
- sigaction(SIGHUP, &sa, NULL);
- sa.sa_handler = reap;
- sigaction(SIGCHLD, &sa, NULL);
- sa.sa_handler = die;
- sigaction(SIGTERM, &sa, NULL);
- sa.sa_handler = die;
- sigaction(SIGINT, &sa, NULL);
- sa.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &sa, &sapipe);
+ event_init();
- for (;;) {
- int n, ctrl = -1;
-
- restart:
- if (nsock == 0) {
- (void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
- while (nsock == 0) {
- if (wantretry || wantconfig || wantreap || wantdie)
- break;
- sigsuspend(&emptymask);
- }
- (void) sigprocmask(SIG_SETMASK, &emptymask, NULL);
- }
+ signal_set(&evsig_alrm, SIGALRM, retry, NULL);
+ signal_add(&evsig_alrm, NULL);
- while (wantretry || wantconfig || wantreap || wantdie) {
- if (wantretry) {
- wantretry = 0;
- doretry();
- }
- if (wantconfig) {
- wantconfig = 0;
- doconfig();
- }
- if (wantreap) {
- wantreap = 0;
- doreap();
- }
- if (wantdie)
- dodie();
- goto restart;
- }
+ config(0, 0, NULL);
- if (readablen != allsockn) {
- if (fdsrp)
- free(fdsrp);
- fdsrp = calloc(allsockn, 1);
- if (fdsrp == NULL) {
- syslog(LOG_ERR, "Out of memory.");
- exit(1);
- }
- readablen = allsockn;
- }
- bcopy(allsockp, fdsrp, allsockn);
+ signal_set(&evsig_hup, SIGHUP, config, NULL);
+ signal_add(&evsig_hup, NULL);
+ signal_set(&evsig_chld, SIGCHLD, reap, NULL);
+ signal_add(&evsig_chld, NULL);
+ signal_set(&evsig_term, SIGTERM, die, NULL);
+ signal_add(&evsig_term, NULL);
+ signal_set(&evsig_int, SIGINT, die, NULL);
+ signal_add(&evsig_int, NULL);
- if ((n = select(maxsock + 1, fdsrp, NULL, NULL, NULL)) <= 0) {
- if (n < 0 && errno != EINTR) {
- syslog(LOG_WARNING, "select: %m");
- sleep(1);
- }
- continue;
- }
+ signal(SIGPIPE, SIG_IGN);
- for (sep = servtab; n && sep; sep = sep->se_next) {
- if (sep->se_fd != -1 &&
- FD_ISSET(sep->se_fd, fdsrp)) {
- n--;
- if (debug)
- fprintf(stderr, "someone wants %s\n",
- sep->se_service);
- if (!sep->se_wait &&
- sep->se_socktype == SOCK_STREAM) {
- ctrl = gettcp(sep);
- if (ctrl == -1)
- continue;
- } else
- ctrl = sep->se_fd;
- (void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
- spawn(sep, ctrl); /* spawn will unblock */
- }
- }
- }
+ event_dispatch();
+
+ return (0);
}
-int
-gettcp(struct servtab *sep)
+void
+gettcp(int fd, short events, void *xsep)
{
+ struct servtab *sep = xsep;
int ctrl;
+ if (debug)
+ fprintf(stderr, "someone wants %s\n", sep->se_service);
+
ctrl = accept(sep->se_fd, NULL, NULL);
if (debug)
fprintf(stderr, "accept, ctrl %d\n", ctrl);
@@ -502,7 +402,7 @@ gettcp(struct servtab *sep)
errno != ECONNABORTED)
syslog(LOG_WARNING, "accept (for %s): %m",
sep->se_service);
- return -1;
+ return;
}
if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) &&
sep->se_socktype == SOCK_STREAM) {
@@ -513,7 +413,7 @@ gettcp(struct servtab *sep)
if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) < 0) {
syslog(LOG_WARNING, "could not getpeername");
close(ctrl);
- return -1;
+ return;
}
if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0,
sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 &&
@@ -522,12 +422,12 @@ gettcp(struct servtab *sep)
* ignore things that look like ftp bounce
*/
close(ctrl);
- return -1;
+ return;
}
}
- return (ctrl);
-}
+ spawn(ctrl, 0, sep);
+}
int
dg_badinput(struct sockaddr *sa)
@@ -603,15 +503,8 @@ dg_broadcast(struct in_addr *in)
return (0);
}
-/* ARGSUSED */
void
-reap(int sig)
-{
- wantreap = 1;
-}
-
-void
-doreap(void)
+reap(int sig, short event, void *arg)
{
struct servtab *sep;
int status;
@@ -640,9 +533,7 @@ doreap(void)
"%s: exit signal %d",
sep->se_server, WTERMSIG(status));
sep->se_wait = 1;
- fd_grow(&allsockp, &allsockn, sep->se_fd);
- FD_SET(sep->se_fd, allsockp);
- nsock++;
+ event_add(&sep->se_event, NULL);
if (debug)
fprintf(stderr, "restored %s, fd %d\n",
sep->se_service, sep->se_fd);
@@ -650,20 +541,12 @@ doreap(void)
}
}
-/* ARGSUSED */
-void
-config(int sig)
-{
- wantconfig = 1;
-}
-
void
-doconfig(void)
+config(int sig, short event, void *arg)
{
struct servtab *sep, *cp, **sepp;
int add;
char protoname[10];
- sigset_t omask;
if (!setconfig()) {
syslog(LOG_ERR, "%s: %m", CONFIG);
@@ -682,7 +565,6 @@ doconfig(void)
#define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;}
- sigprocmask(SIG_BLOCK, &blockmask, &omask);
/*
* sep->se_wait may be holding the pid of a daemon
* that we're waiting for. If so, don't overwrite
@@ -703,7 +585,6 @@ doconfig(void)
unregister_rpc(sep);
sep->se_rpcversl = cp->se_rpcversl;
sep->se_rpcversh = cp->se_rpcversh;
- sigprocmask(SIG_SETMASK, &omask, NULL);
freeconfig(cp);
add = 1;
} else {
@@ -778,8 +659,7 @@ doconfig(void)
if (port != sep->se_ctrladdr_in.sin_port) {
sep->se_ctrladdr_in.sin_port = port;
if (sep->se_fd != -1) {
- FD_CLR(sep->se_fd, allsockp);
- nsock--;
+ event_del(&sep->se_event);
(void) close(sep->se_fd);
}
sep->se_fd = -1;
@@ -834,8 +714,7 @@ doconfig(void)
if (port != sep->se_ctrladdr_in6.sin6_port) {
sep->se_ctrladdr_in6.sin6_port = port;
if (sep->se_fd != -1) {
- FD_CLR(sep->se_fd, allsockp);
- nsock--;
+ event_del(&sep->se_event);
(void) close(sep->se_fd);
}
sep->se_fd = -1;
@@ -862,7 +741,6 @@ doconfig(void)
/*
* Purge anything not looked at above.
*/
- sigprocmask(SIG_BLOCK, &blockmask, &omask);
sepp = &servtab;
while ((sep = *sepp)) {
if (sep->se_checked) {
@@ -871,8 +749,7 @@ doconfig(void)
}
*sepp = sep->se_next;
if (sep->se_fd != -1) {
- FD_CLR(sep->se_fd, allsockp);
- nsock--;
+ event_del(&sep->se_event);
(void) close(sep->se_fd);
}
if (isrpcservice(sep))
@@ -884,18 +761,10 @@ doconfig(void)
freeconfig(sep);
free(sep);
}
- sigprocmask(SIG_SETMASK, &omask, NULL);
}
-/* ARGSUSED */
void
-retry(int sig)
-{
- wantretry = 1;
-}
-
-void
-doretry(void)
+retry(int sig, short events, void *arg)
{
struct servtab *sep;
@@ -915,15 +784,8 @@ doretry(void)
}
}
-/* ARGSUSED */
-void
-die(int sig)
-{
- wantdie = 1;
-}
-
void
-dodie(void)
+die(int sig, short events, void *arg)
{
struct servtab *sep;
@@ -1015,9 +877,16 @@ setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on))
if (sep->se_socktype == SOCK_STREAM)
listen(sep->se_fd, 10);
- fd_grow(&allsockp, &allsockn, sep->se_fd);
- FD_SET(sep->se_fd, allsockp);
- nsock++;
+ if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+ event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
+ gettcp, sep);
+ } else {
+ event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
+ spawn, sep);
+ }
+
+ event_add(&sep->se_event, NULL);
+
if (sep->se_fd > maxsock) {
maxsock = sep->se_fd;
if (maxsock > rlim_nofile_cur - FD_MARGIN)
@@ -1078,7 +947,6 @@ struct servtab *
enter(struct servtab *cp)
{
struct servtab *sep;
- sigset_t omask;
sep = malloc(sizeof (*sep));
if (sep == NULL) {
@@ -1088,10 +956,8 @@ enter(struct servtab *cp)
*sep = *cp;
sep->se_fd = -1;
sep->se_rpcprog = -1;
- sigprocmask(SIG_BLOCK, &blockmask, &omask);
sep->se_next = servtab;
servtab = sep;
- sigprocmask(SIG_SETMASK, &omask, NULL);
return (sep);
}
@@ -1835,14 +1701,18 @@ print_service(char *action, struct servtab *sep)
}
void
-spawn(struct servtab *sep, int ctrl)
+spawn(int ctrl, short events, void *xsep)
{
+ struct servtab *sep = xsep;
struct passwd *pwd;
int tmpint, dofork;
struct group *grp = NULL;
char buf[50];
pid_t pid;
+ if (debug)
+ fprintf(stderr, "someone wants %s\n", sep->se_service);
+
pid = 0;
dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
if (dofork) {
@@ -1869,8 +1739,6 @@ spawn(struct servtab *sep, int ctrl)
* Simply ignore the connection.
*/
--sep->se_count;
- sigprocmask(SIG_SETMASK, &emptymask,
- NULL);
return;
}
syslog(LOG_ERR,
@@ -1879,13 +1747,11 @@ spawn(struct servtab *sep, int ctrl)
if (!sep->se_wait &&
sep->se_socktype == SOCK_STREAM)
close(ctrl);
- FD_CLR(sep->se_fd, allsockp);
+ event_del(&sep->se_event);
(void) close(sep->se_fd);
+
sep->se_fd = -1;
sep->se_count = 0;
- nsock--;
- sigprocmask(SIG_SETMASK, &emptymask,
- NULL);
if (!timingout) {
timingout = 1;
alarm(RETRYTIME);
@@ -1899,16 +1765,13 @@ spawn(struct servtab *sep, int ctrl)
syslog(LOG_ERR, "fork: %m");
if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
close(ctrl);
- sigprocmask(SIG_SETMASK, &emptymask, NULL);
sleep(1);
return;
}
if (pid && sep->se_wait) {
sep->se_wait = pid;
- FD_CLR(sep->se_fd, allsockp);
- nsock--;
+ event_del(&sep->se_event);
}
- sigprocmask(SIG_SETMASK, &emptymask, NULL);
if (pid == 0) {
if (sep->se_bi)
(*sep->se_bi->bi_fn)(ctrl, sep);
@@ -1965,7 +1828,7 @@ spawn(struct servtab *sep, int ctrl)
dup2(STDIN_FILENO, STDERR_FILENO);
closelog();
closefrom(3);
- sigaction(SIGPIPE, &sapipe, NULL);
+ signal(SIGPIPE, SIG_DFL);
execv(sep->se_server, sep->se_argv);
if (sep->se_socktype != SOCK_STREAM)
recv(0, buf, sizeof (buf), 0);