From b49dbd1d0c18dac9968e46d2973ff20add560c69 Mon Sep 17 00:00:00 2001 From: chris mikkelson Date: Wed, 1 Apr 2009 23:10:33 -0500 Subject: [PATCH] Cleaned up module interface, and provided hooks in more code. --- conn_pool.c | 16 ++++++--- module.c | 90 +++++++++++++++++++++++++++++++++++--------------- module_api.c | 5 +-- responses.inc | 1 + smtp.c | 37 ++++++++++++++++----- smtpsink-int.h | 10 +++--- smtpsink.c | 11 +++++- smtpsink.h | 27 +++++++-------- 8 files changed, 136 insertions(+), 61 deletions(-) diff --git a/conn_pool.c b/conn_pool.c index 906b958..f631f3b 100644 --- a/conn_pool.c +++ b/conn_pool.c @@ -69,7 +69,7 @@ close_conn(struct conn *c) free(c->rdata.s); bzero(&c->rdata, sizeof(c->rdata)); } - module_resetconn(c); + module_close(c); if (pthread_mutex_lock(&cp.cpmtx)) assert(0); cp.count --; STAILQ_INSERT_HEAD(&cp.c_pool, c, c_list); @@ -96,6 +96,7 @@ listener_loop(void *data) struct sockaddr_in addr; int addrlen, fd; struct linger l = {1,0}; + int ret; struct conn *c; @@ -120,9 +121,16 @@ listener_loop(void *data) c->peer = addr; c->fd = fd; io_initconn(c); - module_initconn(c); - greeting(c); - c->state = SMTP_GREET; + ret = module_connect(c); + if (SSM_ACCEPTED(ret)) + c->state = SMTP_GREET; + else + c->state = SMTP_CLOSED; + + if (!SSM_RESPONDED(ret)) { + if (SSM_ACCEPTED(ret)) greeting(c); + else respond(c, "421 connection rejected\r\n"); + } if (c->wdata.s) { c->event = EV_WRITE; } else { diff --git a/module.c b/module.c index 566f2fa..94eea33 100644 --- a/module.c +++ b/module.c @@ -44,8 +44,8 @@ module_init(char *modulespec) if (!mod) errx(1, "module %s invalid: %s\n", file, dlerror()); - mod->mod_index = nmod; - mod->module_init(t); + mod->ssm_module_index = nmod; + if (mod->ssm_module_init) mod->ssm_module_init(t); modlist = realloc(modlist, nmod + 1); if (!modlist) @@ -55,38 +55,43 @@ module_init(char *modulespec) } void -module_hup(void) +module_reload(void) { int i; for (i = 0; i < nmod; i++) - if (modlist[i]->module_hup) - modlist[i]->module_hup(); + if (modlist[i]->ssm_module_reload) + modlist[i]->ssm_module_reload(); } -void -module_initconn(struct conn *c) -{ + +int +module_connect(struct conn *c) { + int i, ret; if (!c->priv_data) { c->priv_data = calloc(1, nmod * sizeof(void *)); + if (!c->priv_data) { + respond(c, "451 out of memory\r\n"); + return SSM_REJECT; + } + + } + for (i = 0; i < nmod; i++) { + if (modlist[i]->ssm_connect) { + ret = modlist[i]->ssm_connect(c); + if ((ret & 0x0F) != SSM_PASS) return ret; + } } + return SSM_ACCEPT; } -void -module_resetconn(struct conn *c) -{ - int i; - for (i = 0; i < nmod; i++) - if (modlist[i]->reset_cdata) - modlist[i]->reset_cdata(c); -} int module_helo(struct conn *c, char *cmd, int len, int argoff) { int i, ret; for (i = 0; i < nmod; i++) { - if (modlist[i]->hook_helo) { - ret = modlist[i]->hook_helo(c,cmd,len,argoff); + if (modlist[i]->ssm_helo) { + ret = modlist[i]->ssm_helo(c,cmd,len,argoff); if ((ret & 0x0F) != SSM_PASS) return ret; } } @@ -99,8 +104,8 @@ module_mail(struct conn *c, char *cmd, int len, int argoff) { int i, ret; for (i = 0; i < nmod; i++) { - if (modlist[i]->hook_mail) { - ret = modlist[i]->hook_mail(c,cmd,len,argoff); + if (modlist[i]->ssm_mail) { + ret = modlist[i]->ssm_mail(c,cmd,len,argoff); if ((ret & 0x0F) != SSM_PASS) return ret; } } @@ -112,8 +117,21 @@ module_rcpt(struct conn *c, char *cmd, int len, int argoff) { int i, ret; for (i = 0; i < nmod; i++) { - if (modlist[i]->hook_rcpt) { - ret = modlist[i]->hook_rcpt(c,cmd,len,argoff); + if (modlist[i]->ssm_rcpt) { + ret = modlist[i]->ssm_rcpt(c,cmd,len,argoff); + if ((ret & 0x0F) != SSM_PASS) return ret; + } + } + return SSM_ACCEPT; +} + +int +module_data(struct conn *c, char *cmd, int len, int argoff) +{ + int i, ret; + for (i = 0; i < nmod; i++) { + if (modlist[i]->ssm_enddata) { + ret = modlist[i]->ssm_data(c, cmd, len, argoff); if ((ret & 0x0F) != SSM_PASS) return ret; } } @@ -121,26 +139,44 @@ module_rcpt(struct conn *c, char *cmd, int len, int argoff) } void -module_data(struct conn *c, char *data, int len) +module_body(struct conn *c, char *data, int len) { int i; for (i = 0; i < nmod; i++) { - if (modlist[i]->hook_enddata) { - modlist[i]->hook_data(c, data, len); + if (modlist[i]->ssm_body) { + modlist[i]->ssm_body(c, data, len); } } } + int module_enddata(struct conn *c) { int i, ret; for (i = 0; i < nmod; i++) { - if (modlist[i]->hook_enddata) { - ret = modlist[i]->hook_enddata(c); + if (modlist[i]->ssm_enddata) { + ret = modlist[i]->ssm_enddata(c); if ((ret & 0x0F) != SSM_PASS) return ret; } } return SSM_ACCEPT; } +void +module_abort(struct conn *c) +{ + int i; + for (i = 0; i < nmod; i++) + if (modlist[i]->ssm_abort) + modlist[i]->ssm_abort(c); +} + +void +module_close(struct conn *c) +{ + int i; + for (i = 0; i < nmod; i++) + if (modlist[i]->ssm_close) + modlist[i]->ssm_close(c); +} diff --git a/module_api.c b/module_api.c index ec0bbf3..7a2ec32 100644 --- a/module_api.c +++ b/module_api.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -42,12 +43,12 @@ void * ssm_getpriv(struct smtpsink_module *m, struct conn *c) { assert(c->priv_data); - return c->priv_data[m->mod_index]; + return c->priv_data[m->ssm_module_index]; } void ssm_setpriv(struct smtpsink_module *m, struct conn *c, void *data) { assert(c->priv_data); - c->priv_data[m->mod_index] = data; + c->priv_data[m->ssm_module_index] = data; } diff --git a/responses.inc b/responses.inc index b3b1ed1..1e15756 100644 --- a/responses.inc +++ b/responses.inc @@ -22,6 +22,7 @@ static char *rcpt_reject = "553 recipient rejected.\r\n"; /* DATA command */ static char *data_ok = "354 go ahead\r\n"; +static char *data_reject = "554 data command rejected\r\n"; /* End of DATA (timestamp, random integer) */ static char *enddata_ok = "250 ok %d qp %d\r\n"; diff --git a/smtp.c b/smtp.c index b0493e9..8634a2d 100644 --- a/smtp.c +++ b/smtp.c @@ -86,22 +86,42 @@ static int smtpd_rcpt(struct conn *c, char *cmd, int len, int argoff) { int ret; - if (c->state == SMTP_MAIL || c->state == SMTP_RCPT) { - ret = module_rcpt(c, cmd, len, argoff); + char *resp = rcpt_ok; + if (c->state != SMTP_MAIL && c->state != SMTP_RCPT) + return respond(c, err_wantmail); + + ret = module_rcpt(c, cmd, len, argoff); + if (SSM_ACCEPTED(ret)) c->state = SMTP_RCPT; - return respond(c, rcpt_ok); + else + resp = rcpt_reject; + + if (SSM_RESPONDED(ret)) { + if (c->wdata.s) return 0; + return 1; } - return respond(c, err_wantmail); + return respond(c, resp); } static int smtpd_data(struct conn *c, char *cmd, int len, int argoff) { + int ret; + char *resp = data_ok; if (c->state != SMTP_RCPT) return respond(c, err_wantrcpt); - c->state = SMTP_DATA; - c->dstate = 2; - return respond(c, data_ok); + ret = module_data(c, cmd, len, argoff); + if (SSM_ACCEPTED(ret)) { + c->state = SMTP_DATA; + c->dstate = 2; + } else + resp = data_reject; + + if (SSM_RESPONDED(ret)) { + if (c->wdata.s) return 0; + return 1; + } + return respond(c, resp); } static int @@ -126,6 +146,7 @@ static int smtpd_rset(struct conn *c, char *cmd, int len, int argoff) { c->state = SMTP_RSET; + module_abort(c); return respond(c, rset_ok); } @@ -226,7 +247,7 @@ do_smtp(struct conn *c, char **buf, int *len) } break; } - module_data(c, *buf, s - *buf); + module_body(c, *buf, s - *buf); *len -= s - *buf; *buf = s; if (c->dstate == 5) return smtpd_enddata(c); diff --git a/smtpsink-int.h b/smtpsink-int.h index 8cd64a4..bb60c57 100644 --- a/smtpsink-int.h +++ b/smtpsink-int.h @@ -21,11 +21,13 @@ extern char *banner_hostname; /* module hooks */ extern void module_init(char *); -extern void module_hup(void); -extern void module_initconn(struct conn *); -extern void module_resetconn(struct conn *); +extern void module_reload(void); +extern int module_connect(struct conn *); extern int module_helo(struct conn *, char *, int, int); extern int module_mail(struct conn *, char *, int, int); extern int module_rcpt(struct conn *, char *, int, int); -extern void module_data(struct conn *, char *, int); +extern int module_data(struct conn *, char *, int, int); +extern void module_body(struct conn *, char *, int); extern int module_enddata(struct conn *); +extern void module_abort(struct conn *); +extern void module_close(struct conn *); diff --git a/smtpsink.c b/smtpsink.c index 3bbd394..886d9ef 100644 --- a/smtpsink.c +++ b/smtpsink.c @@ -33,18 +33,27 @@ sigev_exit(int fd, short event, void *arg) exit(0); } +static void +sigev_reload(int fd, short event, void *arg) +{ + module_reload(); +} + static void * sigloop(void *data) { struct event_base *base = (struct event_base *)data; - struct event sigterm, sigint; + struct event sigterm, sigint, sighup; signal_set(&sigint, SIGINT, sigev_exit, 0); event_base_set(base, &sigint); signal_set(&sigterm, SIGTERM, sigev_exit, 0); event_base_set(base, &sigint); + signal_set(&sighup, SIGHUP, sigev_reload, 0); + event_base_set(base, &sighup); signal_add(&sigint, 0); signal_add(&sigterm, 0); + signal_add(&sighup, 0); event_base_dispatch(base); return (void *)base; } diff --git a/smtpsink.h b/smtpsink.h index f556f25..75076ae 100644 --- a/smtpsink.h +++ b/smtpsink.h @@ -50,23 +50,20 @@ int respond(struct conn *, const char *, ...); #define SSM_RESPONDED(x) (x & 0x100) struct smtpsink_module { - void (*module_init)(char *); - void (*module_hup)(void); + unsigned ssm_module_index; - /* manage connection private data */ - void (*reset_cdata)(struct conn *); + void (*ssm_module_init)(char *); + void (*ssm_module_reload)(void); - /* smtp command hooks */ - int (*hook_helo)(struct conn *, char *, int, int); - int (*hook_mail)(struct conn *, char *, int, int); - int (*hook_rcpt)(struct conn *, char *, int, int); - - /* data processing hooks */ - void (*hook_data)(struct conn *, char *, int); - int (*hook_enddata)(struct conn *); - - /* module index (filled in by module_init) */ - unsigned mod_index; + int (*ssm_connect)(struct conn *); + int (*ssm_helo)(struct conn *, char *, int, int); + int (*ssm_mail)(struct conn *, char *, int, int); + int (*ssm_rcpt)(struct conn *, char *, int, int); + int (*ssm_data)(struct conn *, char *, int, int); + void (*ssm_body)(struct conn *, char *, int); + int (*ssm_enddata)(struct conn *); + void (*ssm_abort)(struct conn *); + void (*ssm_close)(struct conn *); }; void *ssm_getpriv(struct smtpsink_module *, struct conn *); -- 2.50.1