summaryrefslogtreecommitdiff
path: root/usr.sbin/popa3d/standalone.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2004-07-17 20:54:25 +0000
committerBrad Smith <brad@cvs.openbsd.org>2004-07-17 20:54:25 +0000
commit9cd0aac99160e4593314efe7856c1f4da1b6c477 (patch)
tree2a885be32785f2eca66d2d001cabcdc5ab238be5 /usr.sbin/popa3d/standalone.c
parent9c135ead40bb12a1f8e24882ade5db4c1004e036 (diff)
the IPv4/IPv6 standalone mode patch has some issues so back it out for now.
requested by deraadt@
Diffstat (limited to 'usr.sbin/popa3d/standalone.c')
-rw-r--r--usr.sbin/popa3d/standalone.c269
1 files changed, 95 insertions, 174 deletions
diff --git a/usr.sbin/popa3d/standalone.c b/usr.sbin/popa3d/standalone.c
index 009373718ee..2d146dd5b84 100644
--- a/usr.sbin/popa3d/standalone.c
+++ b/usr.sbin/popa3d/standalone.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: standalone.c,v 1.6 2004/06/20 20:46:27 itojun Exp $ */
+/* $OpenBSD: standalone.c,v 1.7 2004/07/17 20:54:24 brad Exp $ */
/*
* Standalone POP server: accepts connections, checks the anti-flood limits,
@@ -17,8 +17,6 @@
#include <syslog.h>
#include <time.h>
#include <errno.h>
-#include <netdb.h>
-#include <poll.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -38,7 +36,6 @@ int deny_severity = SYSLOG_PRI_HI;
extern int log_error(char *s);
extern int do_pop_startup(void);
extern int do_pop_session(void);
-extern int af;
typedef volatile sig_atomic_t va_int;
@@ -49,7 +46,7 @@ typedef volatile sig_atomic_t va_int;
* information about sessions that we could have allowed to proceed.
*/
static struct {
- char addr[NI_MAXHOST]; /* Source IP address */
+ struct in_addr addr; /* Source IP address */
volatile int pid; /* PID of the server, or 0 for none */
clock_t start; /* When the server was started */
clock_t log; /* When we've last logged a failure */
@@ -58,15 +55,13 @@ static struct {
static va_int child_blocked; /* We use blocking to avoid races */
static va_int child_pending; /* Are any dead children waiting? */
-int handle(int);
-
/*
* SIGCHLD handler.
*/
static void handle_child(int signum)
{
int saved_errno;
- int pid;
+ pid_t pid;
int i;
saved_errno = errno;
@@ -77,11 +72,11 @@ static void handle_child(int signum)
child_pending = 0;
while ((pid = waitpid(0, NULL, WNOHANG)) > 0)
- for (i = 0; i < MAX_SESSIONS; i++)
- if (sessions[i].pid == pid) {
- sessions[i].pid = 0;
- break;
- }
+ for (i = 0; i < MAX_SESSIONS; i++)
+ if (sessions[i].pid == pid) {
+ sessions[i].pid = 0;
+ break;
+ }
}
signal(SIGCHLD, handle_child);
@@ -116,75 +111,32 @@ int main(void)
#endif
{
int true = 1;
- int *fds, new, sock;
- struct pollfd *pfds;
- int i, n;
- struct addrinfo hints, *res, *res0;
- char sbuf[NI_MAXSERV];
- int error;
+ int sock, new;
+ struct sockaddr_in addr;
+ socklen_t addrlen;
+ pid_t pid;
+ struct tms buf;
+ clock_t now, log;
+ int i, j, n;
if (do_pop_startup()) return 1;
- snprintf(sbuf, sizeof(sbuf), "%u", DAEMON_PORT);
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = af;
- hints.ai_flags = AI_PASSIVE;
- error = getaddrinfo(NULL, sbuf, &hints, &res0);
- if (error)
- return log_error("getaddrinfo");
-
- i = 0;
- for (res = res0; res; res = res->ai_next)
- i++;
-
- fds = malloc(i * sizeof(fds[0]));
- if (!fds)
- return log_error("malloc");
- pfds = malloc(i * sizeof(pfds[0]));
- if (!pfds)
- return log_error("malloc");
-
- i = 0;
- for (res = res0; res; res = res->ai_next) {
- if ((fds[i] = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) < 0)
- continue;
-
- if (setsockopt(fds[i], SOL_SOCKET, SO_REUSEADDR,
- (void *)&true, sizeof(true))) {
- close(fds[i]);
- continue;
- }
-
-#ifdef IPV6_V6ONLY
- if (res->ai_family == AF_INET6)
- (void)setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&true, sizeof(true));
-#endif
-
- if (bind(fds[i], res->ai_addr, res->ai_addrlen)) {
- close(fds[i]);
- continue;
- }
-
- if (listen(fds[i], MAX_BACKLOG)) {
- close(fds[i]);
- continue;
- }
-
- memset(&pfds[i], 0, sizeof(pfds[i]));
- pfds[i].fd = fds[i];
- pfds[i].events = POLLIN;
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ return log_error("socket");
- i++;
- }
- freeaddrinfo(res0);
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&true, sizeof(true)))
+ return log_error("setsockopt");
- if (i == 0)
- return log_error("socket");
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(DAEMON_ADDR);
+ addr.sin_port = htons(DAEMON_PORT);
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
+ return log_error("bind");
- n = i;
+ if (listen(sock, MAX_BACKLOG))
+ return log_error("listen");
chdir("/");
setsid();
@@ -207,49 +159,19 @@ int main(void)
signal(SIGCHLD, handle_child);
memset((void *)sessions, 0, sizeof(sessions));
+ log = 0;
new = 0;
while (1) {
child_blocked = 0;
- if (child_pending)
- raise(SIGCHLD);
-
- i = poll(pfds, n, INFTIM);
-
- if (i < 0)
- log_error("poll");
-
- sock = -1;
- for (i = 0; i < n; i++)
- if (pfds[i].revents & POLLIN)
- handle(pfds[i].fd);
- }
-}
-
-int
-handle(int sock)
-{
- clock_t now, log;
- int new;
- char hbuf[NI_MAXHOST];
- struct sockaddr_storage addr;
- int addrlen;
- int pid;
- struct tms buf;
- int error;
- int j, n, i;
-
- log = 0;
- new = 0;
+ if (child_pending) raise(SIGCHLD);
- addrlen = sizeof(addr);
- new = accept(sock, (struct sockaddr *)&addr, &addrlen);
+ if (new > 0)
+ if (close(new)) return log_error("close");
- error = getnameinfo((struct sockaddr *)&addr, addrlen,
- hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
- if (error)
- ; /* XXX */
+ addrlen = sizeof(addr);
+ new = accept(sock, (struct sockaddr *)&addr, &addrlen);
/*
* I wish there was a portable way to classify errno's... In this case,
@@ -257,76 +179,75 @@ handle(int sock)
* rather than risk terminating the entire service because of a minor
* temporary error having to do with one particular connection attempt.
*/
- if (new < 0)
- return 0;
-
- now = times(&buf);
- if (!now)
- now = 1;
-
- child_blocked = 1;
-
- j = -1;
- n = 0;
- for (i = 0; i < MAX_SESSIONS; i++) {
- if (sessions[i].start > now)
- sessions[i].start = 0;
- if (sessions[i].pid ||
- (sessions[i].start &&
- now - sessions[i].start < MIN_DELAY * CLK_TCK)) {
- if (strcmp(sessions[i].addr, hbuf) == 0)
- if (++n >= MAX_SESSIONS_PER_SOURCE)
- break;
- } else if (j < 0)
- j = i;
- }
+ if (new < 0) continue;
+
+ now = times(&buf);
+ if (!now) now = 1;
+
+ child_blocked = 1;
+
+ j = -1; n = 0;
+ for (i = 0; i < MAX_SESSIONS; i++) {
+ if (sessions[i].start > now)
+ sessions[i].start = 0;
+ if (sessions[i].pid ||
+ (sessions[i].start &&
+ now - sessions[i].start < MIN_DELAY * CLK_TCK)) {
+ if (sessions[i].addr.s_addr ==
+ addr.sin_addr.s_addr)
+ if (++n >= MAX_SESSIONS_PER_SOURCE) break;
+ } else
+ if (j < 0) j = i;
+ }
- if (n >= MAX_SESSIONS_PER_SOURCE) {
- if (!sessions[i].log ||
- now < sessions[i].log ||
- now - sessions[i].log >= MIN_DELAY * CLK_TCK) {
- syslog(SYSLOG_PRI_HI,
- "%s: per source limit reached",
- hbuf);
- sessions[i].log = now;
+ if (n >= MAX_SESSIONS_PER_SOURCE) {
+ if (!sessions[i].log ||
+ now < sessions[i].log ||
+ now - sessions[i].log >= MIN_DELAY * CLK_TCK) {
+ syslog(SYSLOG_PRI_HI,
+ "%s: per source limit reached",
+ inet_ntoa(addr.sin_addr));
+ sessions[i].log = now;
+ }
+ continue;
}
- return 0;
- }
- if (j < 0) {
- if (!log ||
- now < log || now - log >= MIN_DELAY * CLK_TCK) {
- syslog(SYSLOG_PRI_HI,
- "%s: sessions limit reached", hbuf);
- log = now;
+ if (j < 0) {
+ if (!log ||
+ now < log || now - log >= MIN_DELAY * CLK_TCK) {
+ syslog(SYSLOG_PRI_HI,
+ "%s: sessions limit reached",
+ inet_ntoa(addr.sin_addr));
+ log = now;
+ }
+ continue;
}
- return 0;
- }
- switch ((pid = fork())) {
- case -1:
- syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", hbuf);
- break;
+ switch ((pid = fork())) {
+ case -1:
+ syslog(SYSLOG_PRI_ERROR, "%s: fork: %m",
+ inet_ntoa(addr.sin_addr));
+ break;
- case 0:
- if (close(sock)) return log_error("close");
+ case 0:
+ if (close(sock)) return log_error("close");
#if DAEMON_LIBWRAP
- check_access(new);
+ check_access(new);
#endif
- syslog(SYSLOG_PRI_LO, "Session from %s",
- hbuf);
- if (dup2(new, 0) < 0) return log_error("dup2");
- if (dup2(new, 1) < 0) return log_error("dup2");
- if (dup2(new, 2) < 0) return log_error("dup2");
- if (close(new)) return log_error("close");
- return do_pop_session();
-
- default:
- strlcpy(sessions[j].addr, hbuf,
- sizeof(sessions[j].addr));
- (va_int)sessions[j].pid = pid;
- sessions[j].start = now;
- sessions[j].log = 0;
+ syslog(SYSLOG_PRI_LO, "Session from %s",
+ inet_ntoa(addr.sin_addr));
+ if (dup2(new, 0) < 0) return log_error("dup2");
+ if (dup2(new, 1) < 0) return log_error("dup2");
+ if (dup2(new, 2) < 0) return log_error("dup2");
+ if (close(new)) return log_error("close");
+ return do_pop_session();
+
+ default:
+ sessions[j].addr = addr.sin_addr;
+ sessions[j].pid = pid;
+ sessions[j].start = now;
+ sessions[j].log = 0;
+ }
}
}