Commit Diff


commit - d308c5316d2dd25d9253d8a24cde1359412ee466
commit + 5129e9c051c47a24edecd792157817fdf99112bf
blob - cafadc22a92a1f5dd4d21bc646410b61dc7ea04a
blob + a1e0cfb4a13324f479e90d29462ef19121fa7a44
--- opensmtpd.c
+++ opensmtpd.c
@@ -594,7 +594,7 @@ osmtpd_register_conf(void (*cb)(const char *, const ch
 }
 
 void
-osmtpd_register_filter_connect(void (*cb)(struct osmtpd_ctx *, const char *,
+osmtpd_register_filter_connect(int (*cb)(struct osmtpd_ctx *, const char *,
     struct sockaddr_storage *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_CONNECT, 1, 0,
@@ -604,7 +604,7 @@ osmtpd_register_filter_connect(void (*cb)(struct osmtp
 }
 
 void
-osmtpd_register_filter_helo(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_helo(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELO, 1, 0,
 	    (void *)cb);
@@ -613,7 +613,7 @@ osmtpd_register_filter_helo(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_ehlo(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_EHLO, 1, 0,
 	    (void *)cb);
@@ -622,7 +622,7 @@ osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_starttls(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_starttls(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_STARTTLS, 1, 0,
 	    (void *)cb);
@@ -631,7 +631,7 @@ osmtpd_register_filter_starttls(void (*cb)(struct osmt
 }
 
 void
-osmtpd_register_filter_auth(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_auth(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_AUTH, 1, 0,
 	    (void *)cb);
@@ -640,7 +640,7 @@ osmtpd_register_filter_auth(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_mailfrom(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_mailfrom(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_MAIL_FROM, 1, 0,
 	    (void *)cb);
@@ -649,7 +649,7 @@ osmtpd_register_filter_mailfrom(void (*cb)(struct osmt
 }
 
 void
-osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_rcptto(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RCPT_TO, 1, 0,
 	    (void *)cb);
@@ -658,7 +658,7 @@ osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd
 }
 
 void
-osmtpd_register_filter_data(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_data(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA, 1, 0,
 	    (void *)cb);
@@ -667,7 +667,7 @@ osmtpd_register_filter_data(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_dataline(void (*cb)(struct osmtpd_ctx *, const char *))
+osmtpd_register_filter_dataline(int (*cb)(struct osmtpd_ctx *, const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA_LINE, 1, 0,
 	    (void *)cb);
@@ -676,7 +676,7 @@ osmtpd_register_filter_dataline(void (*cb)(struct osmt
 }
 
 void
-osmtpd_register_filter_rset(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_rset(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RSET, 1, 0,
 	    (void *)cb);
@@ -685,7 +685,7 @@ osmtpd_register_filter_rset(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_quit(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_quit(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_QUIT, 1, 0,
 	    (void *)cb);
@@ -694,7 +694,7 @@ osmtpd_register_filter_quit(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_noop(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_noop(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_NOOP, 1, 0,
 	    (void *)cb);
@@ -703,7 +703,7 @@ osmtpd_register_filter_noop(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_help(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_help(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELP, 1, 0,
 	    (void *)cb);
@@ -712,7 +712,7 @@ osmtpd_register_filter_help(void (*cb)(struct osmtpd_c
 }
 
 void
-osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_wiz(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_WIZ, 1, 0,
 	    (void *)cb);
@@ -721,7 +721,7 @@ osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ct
 }
 
 void
-osmtpd_register_filter_commit(void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_filter_commit(int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_COMMIT, 1, 0,
 	    (void *)cb);
@@ -730,7 +730,7 @@ osmtpd_register_filter_commit(void (*cb)(struct osmtpd
 }
 
 void
-osmtpd_register_report_connect(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_connect(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *, enum osmtpd_status, struct sockaddr_storage *,
     struct sockaddr_storage *))
 {
@@ -741,14 +741,14 @@ osmtpd_register_report_connect(int incoming, void (*cb
 }
 
 void
-osmtpd_register_report_disconnect(int incoming, void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_report_disconnect(int incoming, int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
 	    incoming, 0, (void *)cb);
 }
 
 void
-osmtpd_register_report_identify(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_identify(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
@@ -758,7 +758,7 @@ osmtpd_register_report_identify(int incoming, void (*c
 }
 
 void
-osmtpd_register_report_tls(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_tls(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS, incoming, 0,
@@ -768,7 +768,7 @@ osmtpd_register_report_tls(int incoming, void (*cb)(st
 }
 
 void
-osmtpd_register_report_auth(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_auth(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *, enum osmtpd_auth_status))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH, incoming, 0,
@@ -778,7 +778,7 @@ osmtpd_register_report_auth(int incoming, void (*cb)(s
 }
 
 void
-osmtpd_register_report_reset(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_reset(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET, incoming, 0,
@@ -788,7 +788,7 @@ osmtpd_register_report_reset(int incoming, void (*cb)(
 }
 
 void
-osmtpd_register_report_begin(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_begin(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN, incoming, 0,
@@ -798,7 +798,7 @@ osmtpd_register_report_begin(int incoming, void (*cb)(
 }
 
 void
-osmtpd_register_report_mail(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_mail(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t, const char *, enum osmtpd_status))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL, incoming, 0,
@@ -808,7 +808,7 @@ osmtpd_register_report_mail(int incoming, void (*cb)(s
 }
 
 void
-osmtpd_register_report_rcpt(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_rcpt(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t, const char *, enum osmtpd_status))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT, incoming, 0,
@@ -818,7 +818,7 @@ osmtpd_register_report_rcpt(int incoming, void (*cb)(s
 }
 
 void
-osmtpd_register_report_envelope(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_envelope(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t, uint64_t))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE, incoming,
@@ -828,7 +828,7 @@ osmtpd_register_report_envelope(int incoming, void (*c
 }
 
 void
-osmtpd_register_report_data(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_data(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t, enum osmtpd_status))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_DATA, incoming, 0,
@@ -838,7 +838,7 @@ osmtpd_register_report_data(int incoming, void (*cb)(s
 }
 
 void
-osmtpd_register_report_commit(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_commit(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t, size_t))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT, incoming, 0,
@@ -848,7 +848,7 @@ osmtpd_register_report_commit(int incoming, void (*cb)
 }
 
 void
-osmtpd_register_report_rollback(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_rollback(int incoming, int (*cb)(struct osmtpd_ctx *,
     uint32_t))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK, incoming,
@@ -858,7 +858,7 @@ osmtpd_register_report_rollback(int incoming, void (*c
 }
 
 void
-osmtpd_register_report_client(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_client(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_CLIENT,
@@ -868,7 +868,7 @@ osmtpd_register_report_client(int incoming, void (*cb)
 }
 
 void
-osmtpd_register_report_server(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_server(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_SERVER,
@@ -878,7 +878,7 @@ osmtpd_register_report_server(int incoming, void (*cb)
 }
 
 void
-osmtpd_register_report_response(int incoming, void (*cb)(struct osmtpd_ctx *,
+osmtpd_register_report_response(int incoming, int (*cb)(struct osmtpd_ctx *,
     const char *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_FILTER_RESPONSE,
@@ -888,7 +888,7 @@ osmtpd_register_report_response(int incoming, void (*c
 }
 
 void
-osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *))
+osmtpd_register_report_timeout(int incoming, int (*cb)(struct osmtpd_ctx *))
 {
 	osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TIMEOUT, incoming, 0,
 	    (void *)cb);
@@ -1305,20 +1305,22 @@ static void
 osmtpd_noargs(struct osmtpd_callback *cb, struct osmtpd_session *session,
     __unused char *params, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *);
+	int (*f)(struct osmtpd_ctx *);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx);
+		if (f(&session->ctx))
+			session->status = SESSION_ERROR;
 }
 
 static void
 osmtpd_onearg(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *line, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *);
+	int (*f)(struct osmtpd_ctx *, const char *);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, line);
+		if (f(&session->ctx, line))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1328,7 +1330,7 @@ osmtpd_connect(struct osmtpd_callback *cb, struct osmt
 	struct sockaddr_storage ss;
 	char *hostname;
 	char *address;
-	void (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
+	int (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
 
 	hostname = params;
 	if ((address = strchr(params, '|')) == NULL)
@@ -1339,14 +1341,15 @@ osmtpd_connect(struct osmtpd_callback *cb, struct osmt
 	osmtpd_addrtoss(address, &ss, 0, linedup);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, hostname, &ss);
+		if (f(&session->ctx, hostname, &ss))
+			session->status = SESSION_ERROR;
 }
 
 static void
 osmtpd_identify(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *identity, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *);
+	int (*f)(struct osmtpd_ctx *, const char *);
 
 	if (cb->storereport) {
 		free(session->ctx.identity);
@@ -1355,7 +1358,8 @@ osmtpd_identify(struct osmtpd_callback *cb, struct osm
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, identity);
+		if (f(&session->ctx, identity))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1365,7 +1369,7 @@ osmtpd_link_connect(struct osmtpd_callback *cb, struct
 	char *end, *rdns;
 	enum osmtpd_status fcrdns;
 	struct sockaddr_storage src, dst;
-	void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_status,
+	int (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_status,
 	    struct sockaddr_storage *, struct sockaddr_storage *);
 
 	if ((end = strchr(params, '|')) == NULL)
@@ -1403,7 +1407,8 @@ osmtpd_link_connect(struct osmtpd_callback *cb, struct
 		memcpy(&session->ctx.dst, &dst, sizeof(session->ctx.dst));
 	}
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, rdns, fcrdns, &src, &dst);
+		if (f(&session->ctx, rdns, fcrdns, &src, &dst))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1411,11 +1416,12 @@ osmtpd_link_disconnect(struct osmtpd_callback *cb,
     struct osmtpd_session *session, __unused char *param,
     __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *);
+	int (*f)(struct osmtpd_ctx *);
 	size_t i;
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx);
+		if (f(&session->ctx))
+			session->status = SESSION_ERROR;
 
 	RB_REMOVE(osmtpd_sessions, &osmtpd_sessions, session);
 	if (ondeletecb_session != NULL && session->ctx.local_session != NULL)
@@ -1436,7 +1442,7 @@ static void
 osmtpd_link_greeting(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *identity, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *);
+	int (*f)(struct osmtpd_ctx *, const char *);
 
 	if (cb->storereport) {
 		free(session->ctx.greeting.identity);
@@ -1445,14 +1451,15 @@ osmtpd_link_greeting(struct osmtpd_callback *cb, struc
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, identity);
+		if (f(&session->ctx, identity))
+			session->status = SESSION_ERROR;
 }
 
 static void
 osmtpd_link_identify(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *identity, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *);
+	int (*f)(struct osmtpd_ctx *, const char *);
 
 	if (cb->storereport) {
 		free(session->ctx.identity);
@@ -1461,14 +1468,15 @@ osmtpd_link_identify(struct osmtpd_callback *cb, struc
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, identity);
+		if (f(&session->ctx, identity))
+			session->status = SESSION_ERROR;
 }
 
 static void
 osmtpd_link_tls(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *ciphers, __unused char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *);
+	int (*f)(struct osmtpd_ctx *, const char *);
 
 	if (cb->storereport) {
 		if ((session->ctx.ciphers = strdup(ciphers)) == NULL)
@@ -1476,14 +1484,15 @@ osmtpd_link_tls(struct osmtpd_callback *cb, struct osm
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, ciphers);
+		if (f(&session->ctx, ciphers))
+			session->status = SESSION_ERROR;
 }
 
 static void
 osmtpd_link_auth(struct osmtpd_callback *cb, struct osmtpd_session *session,
     char *username, char *linedup)
 {
-	void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_auth_status);
+	int (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_auth_status);
 	char *status;
 	enum osmtpd_auth_status s;
 
@@ -1506,7 +1515,8 @@ osmtpd_link_auth(struct osmtpd_callback *cb, struct os
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, username, s);
+		if (f(&session->ctx, username, s))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1517,7 +1527,7 @@ osmtpd_tx_reset(struct osmtpd_callback *cb, struct osm
 	unsigned long imsgid;
 	uint32_t msgid;
 	size_t i;
-	void (*f)(struct osmtpd_ctx *, uint32_t);
+	int (*f)(struct osmtpd_ctx *, uint32_t);
 
 	errno = 0;
 	imsgid = strtoul(params, &end, 16);
@@ -1533,7 +1543,8 @@ osmtpd_tx_reset(struct osmtpd_callback *cb, struct osm
 		    linedup);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid);
+		if (f(&session->ctx, msgid))
+			session->status = SESSION_ERROR;
 
 	if (ondeletecb_message != NULL && session->ctx.local_message != NULL) {
 		ondeletecb_message(&session->ctx, session->ctx.local_message);
@@ -1556,7 +1567,7 @@ osmtpd_tx_begin(struct osmtpd_callback *cb, struct osm
 {
 	unsigned long imsgid;
 	char *endptr;
-	void (*f)(struct osmtpd_ctx *, uint32_t);
+	int (*f)(struct osmtpd_ctx *, uint32_t);
 
 	errno = 0;
 	imsgid = strtoul(msgid, &endptr, 16);
@@ -1579,7 +1590,8 @@ osmtpd_tx_begin(struct osmtpd_callback *cb, struct osm
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, imsgid);
+		if (f(&session->ctx, imsgid))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1590,7 +1602,7 @@ osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmt
 	enum osmtpd_status status;
 	unsigned long imsgid;
 	uint32_t msgid;
-	void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
+	int (*f)(struct osmtpd_ctx *, uint32_t, const char *,
 	    enum osmtpd_status);
 
 	errno = 0;
@@ -1624,7 +1636,8 @@ osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmt
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid, mailfrom, status);
+		if (f(&session->ctx, msgid, mailfrom, status))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1636,7 +1649,7 @@ osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmt
 	unsigned long imsgid;
 	uint32_t msgid;
 	size_t i;
-	void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
+	int (*f)(struct osmtpd_ctx *, uint32_t, const char *,
 	    enum osmtpd_status);
 
 	errno = 0;
@@ -1680,7 +1693,8 @@ osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmt
 	}
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid, rcptto, status);
+		if (f(&session->ctx, msgid, rcptto, status))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1691,7 +1705,7 @@ osmtpd_tx_envelope(struct osmtpd_callback *cb, struct 
 	uint32_t msgid;
 	uint64_t evpid;
 	char *end;
-	void (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
+	int (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
 
 	errno = 0;
 	imsgid = strtoul(params, &end, 16);
@@ -1715,7 +1729,8 @@ osmtpd_tx_envelope(struct osmtpd_callback *cb, struct 
 		session->ctx.evpid = evpid;
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid, evpid);
+		if (f(&session->ctx, msgid, evpid))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1725,7 +1740,7 @@ osmtpd_tx_data(struct osmtpd_callback *cb, struct osmt
 	char *end;
 	unsigned long imsgid;
 	uint32_t msgid;
-	void (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
+	int (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
 
 	errno = 0;
 	imsgid = strtoul(params, &end, 16);
@@ -1742,7 +1757,8 @@ osmtpd_tx_data(struct osmtpd_callback *cb, struct osmt
 	params = end + 1;
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid, osmtpd_strtostatus(params, linedup));
+		if (f(&session->ctx, msgid, osmtpd_strtostatus(params, linedup)))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1754,7 +1770,7 @@ osmtpd_tx_commit(struct osmtpd_callback *cb, struct os
 	unsigned long imsgid;
 	uint32_t msgid;
 	size_t msgsz;
-	void (*f)(struct osmtpd_ctx *, uint32_t, size_t);
+	int (*f)(struct osmtpd_ctx *, uint32_t, size_t);
 
 	errno = 0;
 	imsgid = strtoul(params, &end, 16);
@@ -1776,7 +1792,8 @@ osmtpd_tx_commit(struct osmtpd_callback *cb, struct os
 		    linedup);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid, msgsz);
+		if (f(&session->ctx, msgid, msgsz))
+			session->status = SESSION_ERROR;
 }
 
 static void
@@ -1786,7 +1803,7 @@ osmtpd_tx_rollback(struct osmtpd_callback *cb, struct 
 	char *end;
 	unsigned long imsgid;
 	uint32_t msgid;
-	void (*f)(struct osmtpd_ctx *, uint32_t);
+	int (*f)(struct osmtpd_ctx *, uint32_t);
 
 	errno = 0;
 	imsgid = strtoul(params, &end, 16);
@@ -1802,7 +1819,8 @@ osmtpd_tx_rollback(struct osmtpd_callback *cb, struct 
 		    linedup);
 
 	if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-		f(&session->ctx, msgid);
+		if (f(&session->ctx, msgid))
+			session->status = SESSION_ERROR;
 }
 
 void
blob - f10b1b40489a1200391eae13016d8770f1b81ab9
blob + 896e673647d159912ecf1f58dbe22bef9c4abe33
--- opensmtpd.h
+++ opensmtpd.h
@@ -118,57 +118,57 @@ struct osmtpd_ctx {
 };
 
 void osmtpd_register_conf(void (*)(const char *, const char *));
-void osmtpd_register_filter_connect(void (*)(struct osmtpd_ctx *, const char *,
+void osmtpd_register_filter_connect(int (*)(struct osmtpd_ctx *, const char *,
     struct sockaddr_storage *));
-void osmtpd_register_filter_helo(void (*)(struct osmtpd_ctx *, const char *));
-void osmtpd_register_filter_ehlo(void (*)(struct osmtpd_ctx *, const char *));
-void osmtpd_register_filter_starttls(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_auth(void (*)(struct osmtpd_ctx *, const char *));
-void osmtpd_register_filter_mailfrom(void (*)(struct osmtpd_ctx *,
+void osmtpd_register_filter_helo(int (*)(struct osmtpd_ctx *, const char *));
+void osmtpd_register_filter_ehlo(int (*)(struct osmtpd_ctx *, const char *));
+void osmtpd_register_filter_starttls(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_auth(int (*)(struct osmtpd_ctx *, const char *));
+void osmtpd_register_filter_mailfrom(int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_filter_rcptto(void (*)(struct osmtpd_ctx *, const char *));
-void osmtpd_register_filter_data(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_dataline(void (*)(struct osmtpd_ctx *,
+void osmtpd_register_filter_rcptto(int (*)(struct osmtpd_ctx *, const char *));
+void osmtpd_register_filter_data(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_dataline(int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_filter_rset(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_quit(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_noop(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_help(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_wiz(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_filter_commit(void (*)(struct osmtpd_ctx *));
-void osmtpd_register_report_connect(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_filter_rset(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_quit(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_noop(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_help(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_wiz(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_filter_commit(int (*)(struct osmtpd_ctx *));
+void osmtpd_register_report_connect(int, int (*)(struct osmtpd_ctx *,
     const char *, enum osmtpd_status, struct sockaddr_storage *,
     struct sockaddr_storage *));
-void osmtpd_register_report_disconnect(int, void (*)(struct osmtpd_ctx *));
-void osmtpd_register_report_greeting(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_disconnect(int, int (*)(struct osmtpd_ctx *));
+void osmtpd_register_report_greeting(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_identify(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_identify(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_tls(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_tls(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_auth(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_auth(int, int (*)(struct osmtpd_ctx *,
     const char *, enum osmtpd_auth_status));
-void osmtpd_register_report_reset(int, void (*)(struct osmtpd_ctx *, uint32_t));
-void osmtpd_register_report_begin(int, void (*)(struct osmtpd_ctx *, uint32_t));
-void osmtpd_register_report_mail(int, void (*)(struct osmtpd_ctx *, uint32_t,
+void osmtpd_register_report_reset(int, int (*)(struct osmtpd_ctx *, uint32_t));
+void osmtpd_register_report_begin(int, int (*)(struct osmtpd_ctx *, uint32_t));
+void osmtpd_register_report_mail(int, int (*)(struct osmtpd_ctx *, uint32_t,
     const char *, enum osmtpd_status));
-void osmtpd_register_report_rcpt(int, void (*)(struct osmtpd_ctx *, uint32_t,
+void osmtpd_register_report_rcpt(int, int (*)(struct osmtpd_ctx *, uint32_t,
     const char *, enum osmtpd_status));
-void osmtpd_register_report_envelope(int, void (*)(struct osmtpd_ctx *, uint32_t,
+void osmtpd_register_report_envelope(int, int (*)(struct osmtpd_ctx *, uint32_t,
     uint64_t));
-void osmtpd_register_report_data(int, void (*)(struct osmtpd_ctx *, uint32_t,
+void osmtpd_register_report_data(int, int (*)(struct osmtpd_ctx *, uint32_t,
     enum osmtpd_status));
-void osmtpd_register_report_commit(int, void (*)(struct osmtpd_ctx *, uint32_t,
+void osmtpd_register_report_commit(int, int (*)(struct osmtpd_ctx *, uint32_t,
     size_t));
-void osmtpd_register_report_rollback(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_rollback(int, int (*)(struct osmtpd_ctx *,
     uint32_t));
-void osmtpd_register_report_client(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_client(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_server(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_server(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_response(int, void (*)(struct osmtpd_ctx *,
+void osmtpd_register_report_response(int, int (*)(struct osmtpd_ctx *,
     const char *));
-void osmtpd_register_report_timeout(int, void (*)(struct osmtpd_ctx *));
+void osmtpd_register_report_timeout(int, int (*)(struct osmtpd_ctx *));
 void osmtpd_local_session(void *(*)(struct osmtpd_ctx *),
     void (*)(struct osmtpd_ctx *, void *));
 void osmtpd_local_message(void *(*)(struct osmtpd_ctx *),
blob - 58ce153580d9714e5b5f3df2f1a0d4b39846598f
blob + 98ade0c44055b00bdb115603bcbddcacfa13c999
--- osmtpd_run.3
+++ osmtpd_run.3
@@ -69,148 +69,148 @@
 .In opensmtpd.h
 .Ft void
 .Fo osmtpd_register_filter_connect
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_helo
-.Fa "void (cb*)(struct osmtpd_ctx *ctx, const char *helo)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *helo)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_ehlo
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *ehlo)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *ehlo)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_starttls
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_auth
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *auth)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *auth)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_mailfrom
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *from)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *from)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_rcptto
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *rcpt)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *rcpt)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_data
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_dataline
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *line)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *line)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_rset
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_quit
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_noop
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_help
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_wiz
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_filter_commit
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_connect
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns, struct sockaddr_storage *src, struct sockaddr_storage *dst)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns, struct sockaddr_storage *src, struct sockaddr_storage *dst)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_disconnect
 .Fa "int incoming"
-.Fa "void (*ctx)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_identify
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *identity)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *identity)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_tls
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *ciphers)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *ciphers)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_auth
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *username, enum osmtpd_auth_status status)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *username, enum osmtpd_auth_status status)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_reset
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_begin
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_mail
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_rcpt
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_envelope
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_data
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_commit
 .Fa int incoming
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_rollback
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_client
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *cmd)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *cmd)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_server
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_response
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
 .Fc
 .Ft void
 .Fo osmtpd_register_report_timeout
 .Fa "int incoming"
-.Fa "void (*cb)(struct osmtpd_ctx *ctx)"
+.Fa "int (*cb)(struct osmtpd_ctx *ctx)"
 .Fc
 .Ft void
 .Fo osmtpd_local_session
@@ -254,6 +254,11 @@ Filter and report callbacks are registered via the
 .Nm osmtpd_register
 class of functions, followed by
 .Nm osmtpd_run .
+A callback should return
+.Dv 0
+in the case of success, or
+.Dv -1
+in the case of error which leads to disconnect of this session.
 .Pp
 .Nm osmtpd_run
 starts the communication with the server and transforms network queries to
blob - 893819d18ff600f2540b3b482cfb014d1dc7e66d
blob + b52599a164f6872e7c8b55a4df1f1c6e25ae4012
--- shlib_version
+++ shlib_version
@@ -1,2 +1,2 @@
-major=1
-minor=1
+major=2
+minor=0