summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2009-01-04 22:35:10 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2009-01-04 22:35:10 +0000
commit92102d1d1b05d500457859fe5b0485fe1cc7868d (patch)
tree4f0652b091967145b5dea3f5d59b57a3992511df /usr.sbin
parent79dc2898a960528ca8c456fd9ef71358ff4debfe (diff)
- smtp can now pause/resume the accepting of incoming messages
- smtpctl recognizes "pause incoming" and "resume incoming" - setup imsg communication between control process and smtp process
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/smtpd/control.c91
-rw-r--r--usr.sbin/smtpd/parser.c4
-rw-r--r--usr.sbin/smtpd/parser.h4
-rw-r--r--usr.sbin/smtpd/runner.c10
-rw-r--r--usr.sbin/smtpd/smtp.c86
-rw-r--r--usr.sbin/smtpd/smtpctl.c18
-rw-r--r--usr.sbin/smtpd/smtpd.h14
7 files changed, 196 insertions, 31 deletions
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c
index a1905876d4d..c0b5e06633e 100644
--- a/usr.sbin/smtpd/control.c
+++ b/usr.sbin/smtpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.6 2009/01/04 19:37:41 gilles Exp $ */
+/* $OpenBSD: control.c,v 1.7 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -57,6 +57,7 @@ void control_dispatch_lka(int, short, void *);
void control_dispatch_mfa(int, short, void *);
void control_dispatch_queue(int, short, void *);
void control_dispatch_runner(int, short, void *);
+void control_dispatch_smtp(int, short, void *);
struct ctl_connlist ctl_conns;
@@ -87,6 +88,7 @@ control(struct smtpd *env)
struct peer peers [] = {
{ PROC_QUEUE, control_dispatch_queue },
{ PROC_RUNNER, control_dispatch_runner },
+ { PROC_SMTP, control_dispatch_smtp },
};
switch (pid = fork()) {
@@ -159,7 +161,7 @@ control(struct smtpd *env)
TAILQ_INIT(&ctl_conns);
- config_peers(env, peers, 2);
+ config_peers(env, peers, 3);
control_listen(env);
event_dispatch();
control_shutdown();
@@ -311,51 +313,72 @@ control_dispatch_ext(int fd, short event, void *arg)
env->sc_flags |= SMTPD_EXITING;
imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
break;
- case IMSG_RUNNER_PAUSE_MDA:
+ case IMSG_MDA_PAUSE:
if (env->sc_flags & SMTPD_MDA_PAUSED) {
imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
NULL, 0);
break;
}
env->sc_flags |= SMTPD_MDA_PAUSED;
- imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_RUNNER_PAUSE_MDA,
+ imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_MDA_PAUSE,
0, 0, -1, NULL, 0);
imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
break;
- case IMSG_RUNNER_PAUSE_MTA:
+ case IMSG_MTA_PAUSE:
if (env->sc_flags & SMTPD_MTA_PAUSED) {
imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
NULL, 0);
break;
}
env->sc_flags |= SMTPD_MTA_PAUSED;
- imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_RUNNER_PAUSE_MTA,
+ imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_MTA_PAUSE,
0, 0, -1, NULL, 0);
imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
break;
- case IMSG_RUNNER_RESUME_MDA:
+ case IMSG_SMTP_PAUSE:
+ if (env->sc_flags & SMTPD_SMTP_PAUSED) {
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ NULL, 0);
+ break;
+ }
+ env->sc_flags |= SMTPD_SMTP_PAUSED;
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_SMTP_PAUSE,
+ 0, 0, -1, NULL, 0);
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
+ break;
+ case IMSG_MDA_RESUME:
if (! (env->sc_flags & SMTPD_MDA_PAUSED)) {
imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
NULL, 0);
break;
}
env->sc_flags &= ~SMTPD_MDA_PAUSED;
- imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_RUNNER_RESUME_MDA,
+ imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_MTA_RESUME,
0, 0, -1, NULL, 0);
imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
break;
- case IMSG_RUNNER_RESUME_MTA:
+ case IMSG_MTA_RESUME:
if (!(env->sc_flags & SMTPD_MTA_PAUSED)) {
imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
NULL, 0);
break;
}
env->sc_flags &= ~SMTPD_MTA_PAUSED;
- imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_RUNNER_RESUME_MTA,
+ imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_MTA_RESUME,
+ 0, 0, -1, NULL, 0);
+ imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
+ break;
+ case IMSG_SMTP_RESUME:
+ if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) {
+ imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ NULL, 0);
+ break;
+ }
+ env->sc_flags &= ~SMTPD_SMTP_PAUSED;
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_SMTP_RESUME,
0, 0, -1, NULL, 0);
imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
break;
-
default:
log_debug("control_dispatch_ext: "
"error handling imsg %d", imsg.hdr.type);
@@ -552,6 +575,52 @@ control_dispatch_runner(int sig, short event, void *p)
}
void
+control_dispatch_smtp(int sig, short event, void *p)
+{
+ struct smtpd *env = p;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ ssize_t n;
+
+ ibuf = env->sc_ibufs[PROC_SMTP];
+ switch (event) {
+ case EV_READ:
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read_error");
+ if (n == 0) {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&ibuf->ev);
+ event_loopexit(NULL);
+ return;
+ }
+ break;
+ case EV_WRITE:
+ if (msgbuf_write(&ibuf->w) == -1)
+ fatal("msgbuf_write");
+ imsg_event_add(ibuf);
+ return;
+ default:
+ fatalx("unknown event");
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("control_dispatch_smtp: imsg_read error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ default:
+ log_debug("control_dispatch_smtp: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ imsg_event_add(ibuf);
+}
+
+void
session_socket_blockmode(int fd, enum blockmodes bm)
{
int flags;
diff --git a/usr.sbin/smtpd/parser.c b/usr.sbin/smtpd/parser.c
index 291d2bc5272..ae1a886b307 100644
--- a/usr.sbin/smtpd/parser.c
+++ b/usr.sbin/smtpd/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.4 2009/01/04 19:37:41 gilles Exp $ */
+/* $OpenBSD: parser.c,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -78,12 +78,14 @@ static const struct token t_show[] = {
static const struct token t_pause[] = {
{KEYWORD, "local", PAUSE_MDA, NULL},
{KEYWORD, "outgoing", PAUSE_MTA, NULL},
+ {KEYWORD, "incoming", PAUSE_SMTP, NULL},
{ENDTOKEN, "", NONE, NULL}
};
static const struct token t_resume[] = {
{KEYWORD, "local", RESUME_MDA, NULL},
{KEYWORD, "outgoing", RESUME_MTA, NULL},
+ {KEYWORD, "incoming", RESUME_SMTP, NULL},
{ENDTOKEN, "", NONE, NULL}
};
diff --git a/usr.sbin/smtpd/parser.h b/usr.sbin/smtpd/parser.h
index 0b10607ef8a..7cf6e3bf94d 100644
--- a/usr.sbin/smtpd/parser.h
+++ b/usr.sbin/smtpd/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.4 2009/01/04 19:37:41 gilles Exp $ */
+/* $OpenBSD: parser.h,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -25,8 +25,10 @@ enum actions {
SHOW_RUNQUEUE,
PAUSE_MDA,
PAUSE_MTA,
+ PAUSE_SMTP,
RESUME_MDA,
RESUME_MTA,
+ RESUME_SMTP,
};
struct parse_result {
diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c
index c68b54ece15..2f5de6426f9 100644
--- a/usr.sbin/smtpd/runner.c
+++ b/usr.sbin/smtpd/runner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: runner.c,v 1.18 2009/01/04 22:18:23 gilles Exp $ */
+/* $OpenBSD: runner.c,v 1.19 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -123,16 +123,16 @@ runner_dispatch_control(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
- case IMSG_RUNNER_PAUSE_MDA:
+ case IMSG_MDA_PAUSE:
env->sc_opts |= SMTPD_MDA_PAUSED;
break;
- case IMSG_RUNNER_PAUSE_MTA:
+ case IMSG_MTA_PAUSE:
env->sc_opts |= SMTPD_MTA_PAUSED;
break;
- case IMSG_RUNNER_RESUME_MDA:
+ case IMSG_MDA_RESUME:
env->sc_opts &= ~SMTPD_MDA_PAUSED;
break;
- case IMSG_RUNNER_RESUME_MTA:
+ case IMSG_MTA_RESUME:
env->sc_opts &= ~SMTPD_MTA_PAUSED;
break;
default:
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index a9bff9a0a78..0a6dcdc98ff 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.15 2009/01/04 00:58:59 gilles Exp $ */
+/* $OpenBSD: smtp.c,v 1.16 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -39,8 +39,11 @@ void smtp_dispatch_parent(int, short, void *);
void smtp_dispatch_mfa(int, short, void *);
void smtp_dispatch_lka(int, short, void *);
void smtp_dispatch_queue(int, short, void *);
+void smtp_dispatch_control(int, short, void *);
void smtp_setup_events(struct smtpd *);
void smtp_disable_events(struct smtpd *);
+void smtp_pause(struct smtpd *);
+void smtp_resume(struct smtpd *);
void smtp_accept(int, short, void *);
void session_timeout(int, short, void *);
void session_auth_pickup(struct session *, char *, size_t);
@@ -461,6 +464,58 @@ smtp_dispatch_queue(int sig, short event, void *p)
}
void
+smtp_dispatch_control(int sig, short event, void *p)
+{
+ struct smtpd *env = p;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ ssize_t n;
+
+ ibuf = env->sc_ibufs[PROC_CONTROL];
+ switch (event) {
+ case EV_READ:
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read_error");
+ if (n == 0) {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&ibuf->ev);
+ event_loopexit(NULL);
+ return;
+ }
+ break;
+ case EV_WRITE:
+ if (msgbuf_write(&ibuf->w) == -1)
+ fatal("msgbuf_write");
+ imsg_event_add(ibuf);
+ return;
+ default:
+ fatalx("unknown event");
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("smtp_dispatch_control: imsg_read error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_SMTP_PAUSE:
+ smtp_pause(env);
+ break;
+ case IMSG_SMTP_RESUME:
+ smtp_resume(env);
+ break;
+ default:
+ log_debug("smtp_dispatch_control: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ imsg_event_add(ibuf);
+}
+
+void
smtp_shutdown(void)
{
log_info("smtp server exiting");
@@ -480,7 +535,8 @@ smtp(struct smtpd *env)
{ PROC_PARENT, smtp_dispatch_parent },
{ PROC_MFA, smtp_dispatch_mfa },
{ PROC_QUEUE, smtp_dispatch_queue },
- { PROC_LKA, smtp_dispatch_lka }
+ { PROC_LKA, smtp_dispatch_lka },
+ { PROC_CONTROL, smtp_dispatch_control }
};
switch (pid = fork()) {
@@ -525,7 +581,7 @@ smtp(struct smtpd *env)
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
- config_peers(env, peers, 4);
+ config_peers(env, peers, 5);
smtp_setup_events(env);
event_dispatch();
@@ -575,6 +631,30 @@ smtp_disable_events(struct smtpd *env)
}
void
+smtp_pause(struct smtpd *env)
+{
+ struct listener *l;
+
+ log_debug("smtp_pause_listeners: pausing listening sockets");
+ TAILQ_FOREACH(l, &env->sc_listeners, entry) {
+ event_del(&l->ev);
+ }
+ env->sc_opts |= SMTPD_SMTP_PAUSED;
+}
+
+void
+smtp_resume(struct smtpd *env)
+{
+ struct listener *l;
+
+ log_debug("smtp_pause_listeners: resuming listening sockets");
+ TAILQ_FOREACH(l, &env->sc_listeners, entry) {
+ event_add(&l->ev, NULL);
+ }
+ env->sc_opts &= ~SMTPD_SMTP_PAUSED;
+}
+
+void
smtp_accept(int fd, short event, void *p)
{
int s_fd;
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index 51a3c2c586e..534a3fe8235 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.4 2009/01/04 19:37:41 gilles Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -139,16 +139,22 @@ connected:
imsg_compose(ibuf, IMSG_CONF_RELOAD, 0, 0, -1, NULL, 0);
break;
case PAUSE_MDA:
- imsg_compose(ibuf, IMSG_RUNNER_PAUSE_MDA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_MDA_PAUSE, 0, 0, -1, NULL, 0);
break;
case PAUSE_MTA:
- imsg_compose(ibuf, IMSG_RUNNER_PAUSE_MTA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_MTA_PAUSE, 0, 0, -1, NULL, 0);
+ break;
+ case PAUSE_SMTP:
+ imsg_compose(ibuf, IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0);
break;
case RESUME_MDA:
- imsg_compose(ibuf, IMSG_RUNNER_RESUME_MDA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_MDA_RESUME, 0, 0, -1, NULL, 0);
break;
case RESUME_MTA:
- imsg_compose(ibuf, IMSG_RUNNER_RESUME_MTA, 0, 0, -1, NULL, 0);
+ imsg_compose(ibuf, IMSG_MDA_RESUME, 0, 0, -1, NULL, 0);
+ break;
+ case RESUME_SMTP:
+ imsg_compose(ibuf, IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0);
break;
case MONITOR:
/* XXX */
@@ -177,8 +183,10 @@ connected:
case SHUTDOWN:
case PAUSE_MDA:
case PAUSE_MTA:
+ case PAUSE_SMTP:
case RESUME_MDA:
case RESUME_MTA:
+ case RESUME_SMTP:
done = show_command_output(&imsg);
break;
case NONE:
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 6ab7fb8122c..1954c79e6cb 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.43 2009/01/04 19:37:41 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.44 2009/01/04 22:35:09 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -192,10 +192,13 @@ enum imsg_type {
IMSG_PARENT_AUTHENTICATE,
- IMSG_RUNNER_PAUSE_MDA,
- IMSG_RUNNER_PAUSE_MTA,
- IMSG_RUNNER_RESUME_MDA,
- IMSG_RUNNER_RESUME_MTA
+ IMSG_MDA_PAUSE,
+ IMSG_MTA_PAUSE,
+ IMSG_SMTP_PAUSE,
+
+ IMSG_MDA_RESUME,
+ IMSG_MTA_RESUME,
+ IMSG_SMTP_RESUME
};
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
@@ -592,6 +595,7 @@ struct smtpd {
#define SMTPD_EXITING 0x00000002
#define SMTPD_MDA_PAUSED 0x00000004
#define SMTPD_MTA_PAUSED 0x00000008
+#define SMTPD_SMTP_PAUSED 0x00000010
u_int32_t sc_flags;
struct timeval sc_qintval;
struct event sc_ev;