aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2013-12-14 20:32:41 +0100
committerGilles Chehade <gilles@poolp.org>2013-12-14 20:32:41 +0100
commit7fc42b3c47578617e1129a592bb51c9dd6104170 (patch)
tree42a95f055ddfa6c7029401280c426770462ffaa9
parentMerge branch 'master' into portable (diff)
parentwoops, API change not propagated to mda.c (diff)
downloadOpenSMTPD-7fc42b3c47578617e1129a592bb51c9dd6104170.tar.xz
OpenSMTPD-7fc42b3c47578617e1129a592bb51c9dd6104170.zip
Merge branch 'master' into portable
-rw-r--r--smtpd/limit.c5
-rw-r--r--smtpd/mda.c12
-rw-r--r--smtpd/mta.c7
-rw-r--r--smtpd/mta_session.c65
-rw-r--r--smtpd/queue.c6
-rw-r--r--smtpd/scheduler.c6
-rw-r--r--smtpd/scheduler_backend.c5
-rw-r--r--smtpd/smtpd-api.h1
-rw-r--r--smtpd/smtpd.h9
9 files changed, 39 insertions, 77 deletions
diff --git a/smtpd/limit.c b/smtpd/limit.c
index 49200325..5461e699 100644
--- a/smtpd/limit.c
+++ b/smtpd/limit.c
@@ -58,6 +58,8 @@ limit_mta_set_defaults(struct mta_limits *limits)
limits->sessdelay_transaction = 1;
limits->sessdelay_keepalive = 10;
+ limits->max_failures_per_session = 25;
+
limits->family = AF_UNSPEC;
limits->task_hiwat = 50;
@@ -104,6 +106,9 @@ limit_mta_set(struct mta_limits *limits, const char *key, int64_t value)
else if (!strcmp(key, "session-keepalive"))
limits->sessdelay_keepalive = value;
+ else if (!strcmp(key, "max-failures-per-session"))
+ limits->max_failures_per_session = value;
+
else if (!strcmp(key, "task-hiwat"))
limits->task_hiwat = value;
else if (!strcmp(key, "task-lowat"))
diff --git a/smtpd/mda.c b/smtpd/mda.c
index 111f82a2..3dc4425e 100644
--- a/smtpd/mda.c
+++ b/smtpd/mda.c
@@ -209,7 +209,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
if (imsg->fd == -1) {
log_debug("debug: mda: cannot get message fd");
- queue_tempfail(e->id, 0, "Cannot get message fd");
+ queue_tempfail(e->id, "Cannot get message fd");
mda_log(e, "TempFail", "Cannot get message fd");
mda_done(s);
return;
@@ -222,7 +222,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
if ((s->datafp = fdopen(imsg->fd, "r")) == NULL) {
log_warn("warn: mda: fdopen");
close(imsg->fd);
- queue_tempfail(e->id, 0, "fdopen failed");
+ queue_tempfail(e->id, "fdopen failed");
mda_log(e, "TempFail", "fdopen failed");
mda_done(s);
return;
@@ -250,7 +250,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
if (n == -1) {
log_warn("warn: mda: "
"fail to write delivery info");
- queue_tempfail(e->id, 0, "Out of memory");
+ queue_tempfail(e->id, "Out of memory");
mda_log(e, "TempFail", "Out of memory");
mda_done(s);
return;
@@ -341,7 +341,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
e = s->evp;
if (imsg->fd == -1) {
log_warn("warn: mda: fail to retrieve mda fd");
- queue_tempfail(e->id, 0, "Cannot get mda fd");
+ queue_tempfail(e->id, "Cannot get mda fd");
mda_log(e, "TempFail", "Cannot get mda fd");
mda_done(s);
return;
@@ -384,7 +384,7 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
/* update queue entry */
if (error) {
- queue_tempfail(e->id, 0, error);
+ queue_tempfail(e->id, error);
snprintf(buf, sizeof buf, "Error (%s)", error);
mda_log(e, "TempFail", buf);
}
@@ -679,7 +679,7 @@ mda_fail(struct mda_user *user, int permfail, const char *error)
}
else {
mda_log(e, "TempFail", error);
- queue_tempfail(e->id, 0, error);
+ queue_tempfail(e->id, error);
}
mda_envelope_free(e);
}
diff --git a/smtpd/mta.c b/smtpd/mta.c
index 0b0e02ef..80f124b0 100644
--- a/smtpd/mta.c
+++ b/smtpd/mta.c
@@ -716,7 +716,7 @@ mta_delivery_flush_event(int fd, short event, void *arg)
if (e->delivery == IMSG_DELIVERY_OK)
queue_ok(e->id);
else if (e->delivery == IMSG_DELIVERY_TEMPFAIL)
- queue_tempfail(e->id, e->penalty, e->status);
+ queue_tempfail(e->id, e->status);
else if (e->delivery == IMSG_DELIVERY_PERMFAIL)
queue_permfail(e->id, e->status);
else if (e->delivery == IMSG_DELIVERY_LOOP)
@@ -763,11 +763,10 @@ mta_delivery_log(struct mta_envelope *e, const char *source, const char *relay,
}
void
-mta_delivery_notify(struct mta_envelope *e, uint32_t penalty)
+mta_delivery_notify(struct mta_envelope *e)
{
struct timeval tv;
- e->penalty = penalty;
tree_xset(&flush_evp, e->id, e);
if (tree_count(&flush_evp) == 1) {
tv.tv_sec = 0;
@@ -1359,7 +1358,7 @@ mta_flush(struct mta_relay *relay, int fail, const char *error)
}
mta_delivery_log(e, NULL, relay->domain->name, fail, error);
- mta_delivery_notify(e, 0);
+ mta_delivery_notify(e);
n++;
}
diff --git a/smtpd/mta_session.c b/smtpd/mta_session.c
index ab791193..53f5c2c4 100644
--- a/smtpd/mta_session.c
+++ b/smtpd/mta_session.c
@@ -128,9 +128,7 @@ struct mta_session {
struct mta_envelope *currevp;
FILE *datafp;
-#define MAX_FAILED_ENVELOPES 15
- struct mta_envelope *failed[MAX_FAILED_ENVELOPES];
- int failedcount;
+ size_t failures;
};
static void mta_session_init(void);
@@ -151,7 +149,6 @@ static int mta_check_loop(FILE *);
static void mta_start_tls(struct mta_session *);
static int mta_verify_certificate(struct mta_session *);
static struct mta_session *mta_tree_pop(struct tree *, uint64_t);
-static void mta_flush_failedqueue(struct mta_session *);
void mta_hoststat_update(const char *, const char *);
void mta_hoststat_reschedule(const char *);
void mta_hoststat_cache(const char *, uint64_t);
@@ -434,8 +431,6 @@ mta_free(struct mta_session *s)
runq_cancel(hangon, NULL, s);
}
- mta_flush_failedqueue(s);
-
io_clear(&s->io);
iobuf_clear(&s->iobuf);
@@ -962,7 +957,7 @@ mta_response(struct mta_session *s, char *line)
s->currevp = TAILQ_NEXT(s->currevp, entry);
if (line[0] == '2') {
- mta_flush_failedqueue(s);
+ s->failures = 0;
/*
* this host is up, reschedule envelopes that
* were cached for reschedule.
@@ -975,6 +970,7 @@ mta_response(struct mta_session *s, char *line)
delivery = IMSG_DELIVERY_PERMFAIL;
else
delivery = IMSG_DELIVERY_TEMPFAIL;
+ s->failures++;
/* remove failed envelope from task list */
TAILQ_REMOVE(&s->task->envelopes, e, entry);
@@ -998,24 +994,17 @@ mta_response(struct mta_session *s, char *line)
mta_delivery_log(e, sa_to_text(sa),
buf, delivery, line);
- /* push failed envelope to the session fail queue */
- s->failed[s->failedcount] = e;
- s->failedcount++;
-
- /*
- * if session fail queue is full:
- * - flush failed queue (failure w/ penalty)
- * - flush remaining tasks with TempFail
- * - mark route down
- */
- if (s->failedcount == MAX_FAILED_ENVELOPES) {
- mta_flush_failedqueue(s);
- mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL,
- "Host temporarily disabled", 0, 1);
- mta_route_down(s->relay, s->route);
- mta_enter_state(s, MTA_QUIT);
- break;
- }
+ if (domain)
+ mta_hoststat_update(domain + 1, e->status);
+ mta_delivery_notify(e);
+
+ if (s->relay->limits->max_failures_per_session &&
+ s->failures == s->relay->limits->max_failures_per_session) {
+ mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL,
+ "Too many consecutive errors, closing connection", 0, 1);
+ mta_enter_state(s, MTA_QUIT);
+ break;
+ }
/*
* if no more envelopes, flush failed queue
@@ -1035,7 +1024,6 @@ mta_response(struct mta_session *s, char *line)
break;
case MTA_DATA:
- mta_flush_failedqueue(s);
if (line[0] == '2' || line[0] == '3') {
mta_enter_state(s, MTA_BODY);
break;
@@ -1080,7 +1068,6 @@ mta_response(struct mta_session *s, char *line)
break;
case MTA_RSET:
- mta_flush_failedqueue(s);
s->rcptcount = 0;
if (s->relay->limits->sessdelay_transaction) {
log_debug("debug: mta: waiting for %llds after reset",
@@ -1361,7 +1348,7 @@ mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t co
mta_delivery_log(e, sa_to_text(sa),
relay, delivery, error);
- mta_delivery_notify(e, 0);
+ mta_delivery_notify(e);
domain = strchr(e->dest, '@');
if (domain) {
@@ -1388,28 +1375,6 @@ mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t co
}
static void
-mta_flush_failedqueue(struct mta_session *s)
-{
- int i;
- struct mta_envelope *e;
- const char *domain;
- uint32_t penalty;
-
- penalty = s->failedcount == MAX_FAILED_ENVELOPES ? 1 : 0;
- for (i = 0; i < s->failedcount; ++i) {
- e = s->failed[i];
-
- domain = strchr(e->dest, '@');
- if (domain)
- mta_hoststat_update(domain + 1, e->status);
-
- mta_delivery_notify(e, penalty);
- }
-
- s->failedcount = 0;
-}
-
-static void
mta_error(struct mta_session *s, const char *fmt, ...)
{
va_list ap;
diff --git a/smtpd/queue.c b/smtpd/queue.c
index 5beb4b59..8051aa32 100644
--- a/smtpd/queue.c
+++ b/smtpd/queue.c
@@ -71,7 +71,6 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
const char *reason;
uint64_t reqid, evpid, holdq;
uint32_t msgid;
- uint32_t penalty;
time_t nexttry;
int fd, ret, v, flags;
@@ -350,7 +349,6 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
case IMSG_DELIVERY_TEMPFAIL:
m_msg(&m, imsg);
m_get_evpid(&m, &evpid);
- m_get_u32(&m, &penalty);
m_get_string(&m, &reason);
m_end(&m);
if (queue_envelope_load(evpid, &evp) == 0) {
@@ -367,7 +365,6 @@ queue_imsg(struct mproc *p, struct imsg *imsg)
log_warnx("warn: could not update envelope %016"PRIx64, evpid);
m_create(p_scheduler, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1);
m_add_envelope(p_scheduler, &evp);
- m_add_u32(p_scheduler, penalty);
m_close(p_scheduler);
return;
@@ -666,11 +663,10 @@ queue_ok(uint64_t evpid)
}
void
-queue_tempfail(uint64_t evpid, uint32_t penalty, const char *reason)
+queue_tempfail(uint64_t evpid, const char *reason)
{
m_create(p_queue, IMSG_DELIVERY_TEMPFAIL, 0, 0, -1);
m_add_evpid(p_queue, evpid);
- m_add_u32(p_queue, penalty);
m_add_string(p_queue, reason);
m_close(p_queue);
}
diff --git a/smtpd/scheduler.c b/smtpd/scheduler.c
index 24ab51a8..49f73b35 100644
--- a/smtpd/scheduler.c
+++ b/smtpd/scheduler.c
@@ -78,7 +78,6 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
uint64_t evpid, id, holdq;
uint32_t msgid;
uint32_t inflight;
- uint32_t penalty;
size_t n, i;
time_t timestamp;
int v, r, type;
@@ -91,7 +90,7 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
m_end(&m);
log_trace(TRACE_SCHEDULER,
"scheduler: inserting evp:%016" PRIx64, evp.id);
- scheduler_info(&si, &evp, 0);
+ scheduler_info(&si, &evp);
stat_increment("scheduler.envelope.incoming", 1);
backend->insert(&si);
return;
@@ -156,11 +155,10 @@ scheduler_imsg(struct mproc *p, struct imsg *imsg)
case IMSG_DELIVERY_TEMPFAIL:
m_msg(&m, imsg);
m_get_envelope(&m, &evp);
- m_get_u32(&m, &penalty);
m_end(&m);
log_trace(TRACE_SCHEDULER,
"scheduler: updating evp:%016" PRIx64, evp.id);
- scheduler_info(&si, &evp, penalty);
+ scheduler_info(&si, &evp);
backend->update(&si);
ninflight -= 1;
stat_increment("scheduler.delivery.tempfail", 1);
diff --git a/smtpd/scheduler_backend.c b/smtpd/scheduler_backend.c
index e836954f..1be11b51 100644
--- a/smtpd/scheduler_backend.c
+++ b/smtpd/scheduler_backend.c
@@ -53,7 +53,7 @@ scheduler_backend_lookup(const char *name)
}
void
-scheduler_info(struct scheduler_info *sched, struct envelope *evp, uint32_t penalty)
+scheduler_info(struct scheduler_info *sched, struct envelope *evp)
{
sched->evpid = evp->id;
sched->type = evp->type;
@@ -63,7 +63,6 @@ scheduler_info(struct scheduler_info *sched, struct envelope *evp, uint32_t pena
sched->lasttry = evp->lasttry;
sched->lastbounce = evp->lastbounce;
sched->nexttry = 0;
- sched->penalty = penalty;
}
time_t
@@ -77,7 +76,7 @@ scheduler_compute_schedule(struct scheduler_info *sched)
else
delay = 10;
- retry = sched->retry + sched->penalty;
+ retry = sched->retry;
delay = ((delay * retry) * retry) / 2;
return (sched->creation + delay);
diff --git a/smtpd/smtpd-api.h b/smtpd/smtpd-api.h
index 803b60b0..dae36a95 100644
--- a/smtpd/smtpd-api.h
+++ b/smtpd/smtpd-api.h
@@ -164,7 +164,6 @@ struct scheduler_info {
time_t lasttry;
time_t lastbounce;
time_t nexttry;
- uint8_t penalty;
};
#define SCHED_NONE 0x00
diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h
index 8f084f63..ae057ef9 100644
--- a/smtpd/smtpd.h
+++ b/smtpd/smtpd.h
@@ -722,6 +722,8 @@ struct mta_limits {
time_t sessdelay_transaction;
time_t sessdelay_keepalive;
+ size_t max_failures_per_session;
+
int family;
int task_hiwat;
@@ -783,7 +785,6 @@ struct mta_envelope {
char *rcpt;
struct mta_task *task;
int delivery;
- int penalty;
char status[SMTPD_MAXLINESIZE];
};
@@ -1211,7 +1212,7 @@ void mta_route_down(struct mta_relay *, struct mta_route *);
void mta_route_collect(struct mta_relay *, struct mta_route *);
void mta_source_error(struct mta_relay *, struct mta_route *, const char *);
void mta_delivery_log(struct mta_envelope *, const char *, const char *, int, const char *);
-void mta_delivery_notify(struct mta_envelope *, uint32_t);
+void mta_delivery_notify(struct mta_envelope *);
struct mta_task *mta_route_next_task(struct mta_relay *, struct mta_route *);
const char *mta_host_to_text(struct mta_host *);
const char *mta_relay_to_text(struct mta_relay *);
@@ -1229,7 +1230,7 @@ int cmdline_symset(char *);
/* queue.c */
pid_t queue(void);
void queue_ok(uint64_t);
-void queue_tempfail(uint64_t, uint32_t, const char *);
+void queue_tempfail(uint64_t, const char *);
void queue_permfail(uint64_t, const char *);
void queue_loop(uint64_t);
void queue_flow_control(void);
@@ -1262,7 +1263,7 @@ pid_t scheduler(void);
/* scheduler_bakend.c */
struct scheduler_backend *scheduler_backend_lookup(const char *);
-void scheduler_info(struct scheduler_info *, struct envelope *, uint32_t);
+void scheduler_info(struct scheduler_info *, struct envelope *);
time_t scheduler_compute_schedule(struct scheduler_info *);