misc@,

I'd like to suggest a breaking change in libopensmtpd and this list seems
like the right place for it.

Right now a filter inside a callback like dataline has no way to report that
something is wrong and it mail needs to be rejected. The only way is to
crash.

The diff changes the definition of the callback so that it should return 0
on success or -1 on error, which leads to disconnect of this session.

Unfortunately, this breaks the API and requires updating all filters that
use the library. It's trivial, but it's something that needs to be done.

The code is available in this branch:
https://src.imperialat.at/?action=summary&headref=callback-error-code&path=libopensmtpd.git

Or as the diff which is inlined into this email for v0.8


diff --git opensmtpd.c opensmtpd.c
index cafadc2..a1e0cfb 100644
--- opensmtpd.c
+++ opensmtpd.c
@@ -594,7 +594,7 @@ osmtpd_register_conf(void (*cb)(const char *, const char *))
 }
 
 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 osmtpd_ctx 
*, const char *,
 }
 
 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_ctx *, 
const char *))
 }
 
 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_ctx *, 
const char *))
 }
 
 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 
osmtpd_ctx *))
 }
 
 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_ctx *, 
const char *))
 }
 
 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 
osmtpd_ctx *, const char *))
 }
 
 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_ctx 
*, const char *))
 }
 
 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_ctx *))
 }
 
 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 
osmtpd_ctx *, const char *))
 }
 
 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_ctx *))
 }
 
 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_ctx *))
 }
 
 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_ctx *))
 }
 
 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_ctx *))
 }
 
 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_ctx *))
 }
 
 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_ctx 
*))
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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 
(*cb)(struct osmtpd_ctx *,
 }
 
 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)(struct 
osmtpd_ctx *,
 }
 
 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)(struct 
osmtpd_ctx *,
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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)(struct 
osmtpd_ctx *,
 }
 
 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)(struct 
osmtpd_ctx *,
 }
 
 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 
(*cb)(struct osmtpd_ctx *,
 }
 
 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)(struct 
osmtpd_ctx *,
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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 
(*cb)(struct osmtpd_ctx *,
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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)(struct osmtpd_ctx *,
 }
 
 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 
(*cb)(struct osmtpd_ctx *,
 }
 
 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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
                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, struct 
osmtpd_session *session,
        }
 
        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, struct 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
                    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 
osmtpd_session *session,
 {
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        }
 
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
                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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
        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 
osmtpd_session *session,
                    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 
osmtpd_session *session,
        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 
osmtpd_session *session,
                    linedup);
 
        if ((f = cb->cb) != NULL && session->status == SESSION_OK)
-               f(&session->ctx, msgid);
+               if (f(&session->ctx, msgid))
+                       session->status = SESSION_ERROR;
 }
 
 void
diff --git opensmtpd.h opensmtpd.h
index f10b1b4..896e673 100644
--- 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 *),
diff --git osmtpd_run.3 osmtpd_run.3
index 58ce153..98ade0c 100644
--- 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
diff --git shlib_version shlib_version
index 893819d..b52599a 100644
--- shlib_version
+++ shlib_version
@@ -1,2 +1,2 @@
-major=1
-minor=1
+major=2
+minor=0



-- 
wbr, Kirill


Reply via email to