I've already talked with kirill about this change and am OK with the
diff. However the motivation doesn't seem quite right to me. Right
now on error the application needs to cache the error state and
"manually" instruct the library to disconnect with what error.
Simply returning -1 simplifies the behaviour and also puts
libopensmtpd in control of when the disconnect is returned.

This particularly helps simplify things inside filter-dkimsign.

martijn@

On Thu, 2025-04-10 at 17:32 +0200, Kirill A.Korinsky wrote:
> 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
> 
> 
> 



  • [no subject] Kirill A . Korinsky
    • Re: ABI bump for libopensmtpd: Allow filters to r... Martijn van Duren

Reply via email to