diff options
author | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-04-20 17:07:02 +0000 |
---|---|---|
committer | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-04-20 17:07:02 +0000 |
commit | 40383a8787aa6e0fef512c71f88b737e7d32d665 (patch) | |
tree | 3db0b399b070730f47fa42b070a20dda7fdecd00 | |
parent | b7e1f9e4dd4578f5cf0c85d2827a5365321c406c (diff) |
Rewrite smtp session timeouts; use evtimer_* from event(3) instead
of regularly walking session tree in search of idle clients. Gives
the smtp process a chance to become idle.
As a bonus, add smtp.sessions.timeout counter to "smtpctl show stats".
ok gilles@
-rw-r--r-- | usr.sbin/smtpd/smtp.c | 10 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 72 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl.c | 3 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 5 |
4 files changed, 41 insertions, 49 deletions
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c index 90fee941759..fe8c9cb55f7 100644 --- a/usr.sbin/smtpd/smtp.c +++ b/usr.sbin/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.34 2009/04/16 15:35:06 jacekm Exp $ */ +/* $OpenBSD: smtp.c,v 1.35 2009/04/20 17:07:01 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -556,7 +556,6 @@ smtp_dispatch_control(int sig, short event, void *p) s->s_id = queue_generate_id(); s->s_fd = fd[0]; - s->s_tm = time(NULL); s->s_env = env; s->s_l = &l; s->s_msg.flags |= F_MESSAGE_ENQUEUED; @@ -690,7 +689,6 @@ void smtp_setup_events(struct smtpd *env) { struct listener *l; - struct timeval tv; TAILQ_FOREACH(l, &env->sc_listeners, entry) { log_debug("smtp_setup_events: listen on %s port %d flags 0x%01x" @@ -705,11 +703,6 @@ smtp_setup_events(struct smtpd *env) event_add(&l->ev, NULL); ssl_setup(env, l); } - - evtimer_set(&env->sc_ev, session_timeout, env); - tv.tv_sec = 1; - tv.tv_usec = 0; - evtimer_add(&env->sc_ev, &tv); } void @@ -767,7 +760,6 @@ smtp_accept(int fd, short event, void *p) s->s_id = queue_generate_id(); s->s_fd = s_fd; - s->s_tm = time(NULL); s->s_env = l->env; s->s_l = l; diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index b896ef4a3ed..5ea42d2bae3 100644 --- a/usr.sbin/smtpd/smtp_session.c +++ b/usr.sbin/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.67 2009/04/19 12:48:27 jacekm Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.68 2009/04/20 17:07:01 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -40,6 +40,8 @@ #include "smtpd.h" +struct session_timeout; + int session_rfc5321_helo_handler(struct session *, char *); int session_rfc5321_ehlo_handler(struct session *, char *); int session_rfc5321_rset_handler(struct session *, char *); @@ -70,7 +72,9 @@ void session_error(struct bufferevent *, short, void *); void session_msg_submit(struct session *); void session_command(struct session *, char *, char *); int session_set_path(struct path *, char *); -void session_timeout(int, short, void *); +void session_set_timeout(struct session *, struct session_timeout *, + void (*)(int, short, void *)); +void smtp_timeout(int, short, void *); void session_cleanup(struct session *); void session_imsg(struct session *, enum smtp_proc_type, enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); @@ -90,7 +94,8 @@ struct session_timeout rfc5321_timeouttab[] = { { S_RCPT, 300 }, { S_DATA, 120 }, { S_DATACONTENT, 180 }, - { S_DONE, 600 } + { S_DONE, 600 }, + { 0, 0 } }; struct session_cmd { @@ -730,6 +735,8 @@ session_init(struct listener *l, struct session *s) { s->s_state = S_INIT; + session_set_timeout(s, rfc5321_timeouttab, smtp_timeout); + if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, session_error, s)) == NULL) fatalx("session_init: bufferevent_new failed"); @@ -755,7 +762,7 @@ session_read(struct bufferevent *bev, void *p) size_t nr; read: - s->s_tm = time(NULL); + session_set_timeout(s, rfc5321_timeouttab, smtp_timeout); nr = EVBUFFER_LENGTH(bev->input); line = evbuffer_readline(bev->input); if (line == NULL) { @@ -896,6 +903,7 @@ session_destroy(struct session *s) bufferevent_free(s->s_bev); } ssl_session_destroy(s); + evtimer_del(&s->s_timeout); SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s); bzero(s, sizeof(*s)); @@ -976,46 +984,36 @@ session_set_path(struct path *path, char *line) } void -session_timeout(int fd, short event, void *p) +session_set_timeout(struct session *s, struct session_timeout *tab, + void (*cb)(int, short, void *)) { - struct smtpd *env = p; - struct session *sessionp; - struct session *rmsession; - struct timeval tv; - time_t tm; - u_int8_t i; - - tm = time(NULL); - rmsession = NULL; - SPLAY_FOREACH(sessionp, sessiontree, &env->sc_sessions) { - - if (rmsession != NULL) { - session_destroy(rmsession); - rmsession = NULL; - } + struct timeval tv; - for (i = 0; i < sizeof (rfc5321_timeouttab) / - sizeof(struct session_timeout); ++i) - if (rfc5321_timeouttab[i].state == sessionp->s_state) - break; + bzero(&tv, sizeof(tv)); - if (i == sizeof (rfc5321_timeouttab) / sizeof (struct session_timeout)) { - if (tm - SMTPD_SESSION_TIMEOUT < sessionp->s_tm) - continue; - } - else if (tm - rfc5321_timeouttab[i].timeout < sessionp->s_tm) { - continue; + for (; tab->timeout; tab++) + if (s->s_state == tab->state) { + tv.tv_sec = tab->timeout; + break; } + if (! tab->timeout) + tv.tv_sec = SMTPD_SESSION_TIMEOUT; + evtimer_set(&s->s_timeout, cb, s); + evtimer_add(&s->s_timeout, &tv); +} - rmsession = sessionp; - } +void +smtp_timeout(int fd, short event, void *p) +{ + struct session *s = p; - if (rmsession != NULL) - session_destroy(rmsession); + log_debug("smtp_timeout: fd %d at state %d", s->s_fd, s->s_state); - tv.tv_sec = 1; - tv.tv_usec = 0; - evtimer_add(&env->sc_ev, &tv); + s_smtp.timeout++; + if (s->s_flags & F_EVLOCKED) + s->s_flags |= F_QUIT; + else + session_destroy(s); } void diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c index 22f7dea195c..bcbf31df1ac 100644 --- a/usr.sbin/smtpd/smtpctl.c +++ b/usr.sbin/smtpd/smtpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpctl.c,v 1.21 2009/04/16 15:35:06 jacekm Exp $ */ +/* $OpenBSD: smtpctl.c,v 1.22 2009/04/20 17:07:01 jacekm Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -294,6 +294,7 @@ show_stats_output(struct imsg *imsg) printf("smtp.sessions=%zd\n", s_smtp.sessions); printf("smtp.sessions.aborted=%zd\n", s_smtp.aborted); + printf("smtp.sessions.timeout=%zd\n", s_smtp.timeout); printf("smtp.sessions.active=%zd\n", s_smtp.sessions_active); printf("smtp.sessions.smtps=%zd\n", s_smtp.smtps); printf("smtp.sessions.smtps.active=%zd\n", s_smtp.smtps_active); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 99c6bca3455..a556f079519 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.99 2009/04/16 15:35:06 jacekm Exp $ */ +/* $OpenBSD: smtpd.h,v 1.100 2009/04/20 17:07:01 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -587,12 +587,12 @@ struct session { enum session_flags s_flags; enum session_state s_state; - time_t s_tm; int s_fd; struct sockaddr_storage s_ss; char s_hostname[MAXHOSTNAMELEN]; struct event s_ev; struct bufferevent *s_bev; + struct event s_timeout; struct listener *s_l; struct smtpd *s_env; void *s_ssl; @@ -668,6 +668,7 @@ struct s_session { size_t starttls_active; size_t aborted; + size_t timeout; }; struct stats { |