OSMTPD_RUN(3) Library Functions Manual OSMTPD_RUN(3)

osmtpd_register_filter_connect, osmtpd_register_filter_helo, osmtpd_register_filter_ehlo, osmtpd_register_filter_starttls, osmtpd_register_filter_auth, osmtpd_register_filter_mailfrom, osmtpd_register_filter_rcptto, osmtpd_register_filter_data, osmtpd_register_filter_dataline, osmtpd_register_filter_rset, osmtpd_register_filter_quit, osmtpd_register_filter_noop, osmtpd_register_filter_help, osmtpd_register_filter_wiz, osmtpd_register_filter_commit, osmtpd_register_report_connect, osmtpd_register_report_disconnect, osmtpd_register_report_identify, osmtpd_register_report_tls, osmtpd_register_report_begin, osmtpd_register_report_mail, osmtpd_register_report_rcpt, osmtpd_register_report_envelope, osmtpd_register_report_data, osmtpd_register_report_commit, osmtpd_register_report_rollback, osmtpd_register_report_client, osmtpd_register_report_server, osmtpd_register_report_response, osmtpd_register_report_timeout, osmtpd_local_session, osmtpd_local_message, osmtpd_need, osmtpd_filter_proceed, osmtpd_filter_reject, osmtpd_filter_disconnect, osmtpd_filter_rewrite, osmtpd_filter_dataline, osmtpd_run, osmtpd_err, osmtpd_errx - C filter API for smtpd(8)

#include <opensmtpd.h>

void

osmtpd_register_filter_connect(void (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss));

void

osmtpd_register_filter_helo(void (cb*)(struct osmtpd_ctx *ctx, const char *helo));

void

osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_ctx *ctx, const char *ehlo));

void

osmtpd_register_filter_starttls(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_auth(void (*cb)(struct osmtpd_ctx *ctx, const char *auth));

void

osmtpd_register_filter_mailfrom(void (*cb)(struct osmtpd_ctx *ctx, const char *from));

void

osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd_ctx *ctx, const char *rcpt));

void

osmtpd_register_filter_data(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_dataline(void (*cb)(struct osmtpd_ctx *ctx, const char *line));

void

osmtpd_register_filter_rset(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_quit(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_noop(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_help(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_filter_commit(void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_register_report_connect(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns, struct sockaddr_storage *src, struct sockaddr_storage *dst));

void

osmtpd_register_report_disconnect(int incoming, void (*ctx)(struct osmtpd_ctx *ctx));

void

osmtpd_register_report_identify(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *identity));

void

osmtpd_register_report_tls(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *ciphers));

void

osmtpd_register_report_begin(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid));

void

osmtpd_register_report_mail(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status));

void

osmtpd_register_report_rcpt(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status));

void

osmtpd_register_report_envelope(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid));

void

osmtpd_register_report_data(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status));

void

osmtpd_register_report_commit(int, incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz));

void

osmtpd_register_report_rollback(int incoming, void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid));

void

osmtpd_register_report_client(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *cmd));

void

osmtpd_register_report_server(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *resp));

void

osmtpd_register_report_response(int incoming, void (*cb)(struct osmtpd_ctx *ctx, const char *resp));

void

osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *ctx));

void

osmtpd_local_session(void *(*oncreate)(struct osmtpd_ctx *ctx), void (*ondelete)(struct osmtpd_ctx *ctx, void *data));

void

osmtpd_local_message(void *(*oncreate)(struct osmtpd_ctx *ctx), void (*ondelete)(struct osmtpd_ctx *ctx, void *data));

void

osmtpd_need(int needs);

void

osmtpd_filter_proceed(struct osmtpd_ctx *ctx);

void

osmtpd_filter_reject(struct osmtpd_ctx *ctx, int error, const char *msg, ...);

void

osmtpd_filter_disconnect(struct osmtpd_ctx *ctx, const char *msg, ...);

void

osmtpd_filter_rewrite(struct osmtpd_ctx *ctx, const char *value, ...);

void

osmtpd_filter_dataline(struct osmtpd_ctx *ctx, const char *line, ...);

void

osmtpd_run(void);

void

osmtpd_err(int eval, const char *fmt, ...);

void

osmtpd_errx(int eval, const char *fmt, ...);

The osmtpd API is an event based interface for writing smtpd(8) filters. Filter and report callbacks are registered via the osmtpd_register class of functions, followed by osmtpd_run.

osmtpd_run starts the communication with the server and transforms network queries to callbacks. Internally it uses event_dispatch(3), which allows filters to be written fully asynchronously.

Each callback cb gets at least a pointer of the type struct, osmtpd_ctx. It contains the following elements:

The type of request being made. The possible values are OSMTPD_TYPE_FILTER and OSMTPD_TYPE_REPORT.
The phase in the transaction which triggered the callback. The following values match their respective osmtpd_register function:
osmtpd_register_filter_connect
osmtpd_register_filter_helo
osmtpd_register_filter_ehlo
osmtpd_register_filter_starttls
osmtpd_register_filter_auth
osmtpd_register_filter_mailfrom
osmtpd_register_filter_rcptto
osmtpd_register_filter_data
osmtpd_register_filter_dataline
osmtpd_register_filter_rset
osmtpd_register_filter_quit
osmtpd_register_filter_noop
osmtpd_register_filter_help
osmtpd_register_filter_wiz
osmtpd_register_filter_commit
osmtpd_register_report_connect
osmtpd_register_report_disconnect
osmtpd_register_report_identify
osmtpd_register_report_tls
osmtpd_register_report_begin
osmtpd_register_report_mail
osmtpd_register_report_rcpt
osmtpd_register_report_envelope
osmtpd_register_report_data
osmtpd_register_report_commit
osmtpd_register_report_rollback
osmtpd_register_report_client
osmtpd_register_report_server
osmtpd_register_report_response
osmtpd_register_report_timeout
The major version number of the protocol. Most filters don't need this information.
The minor version number of the protocol. Most filters don't need this information.
The time the event was triggered inside smtpd(8).
Set to 1 if the event was based on an incoming connection, 0 if it's an outgoing connection. The osmtpd_register_filter class of functions is always based on incoming connections. osmtpd_register_report can be both incoming and outgoing.
The request ID of the connection the event was issued on. This value can be useful for logging. Filters in need of filter specific data can use osmtpd_local_session and local_session.
The filter specific token. Most filters don't need this information.
The source address and port of the connection. This needs to be cast to the appropriate sockaddr type based on the ss_family attribute. It can have the following families: AF_INET, AF_INET6 and AF_UNIX. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_SRC. If not available the entire attribute is zeroed out.
The destination address and port of the connection. This needs to be cast to the appropriate sockaddr type based on the ss_family attribute. It can have the following families: AF_INET, AF_INET6 and AF_UNIX. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_DST. If not available the entire attribute is zeroed out.
The reverse DNS hostname of the connection. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_RDNS. If not available the attribute is set to NULL.
Whether the reverse DNS hostname is forward confirmed. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_FCRDNS. If not available the attribute is set to OSMTPD_STATUS_TEMPFAIL.
The identity of the remote host as presented by the HELO or EHLO SMTP command. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_IDENTITY. If not available the attribute is set to NULL.
The ciphers used during (start)tls. To use this attribute, initialize osmtpd_need with OSMTPD_NEED_CIPHERS. If not available the attribute is set to NULL.
The message ID of the current message being handled in the SMTP transaction. This value can be useful for logging. osmtpd_need needs to be initialized with OSMTPD_NEED_MSGID. If not available the attribute is set to 0. Filters in need of filter specific data can use osmtpd_local_message and local_message.
The envelope MAIL FROM address in the SMTP transaction. osmtpd_need needs to be initialized with OSMTPD_NEED_MAILFROM. If not available the attribute is set to NULL.
The envelope RCPT TO address in the SMTP transaction. osmtpd_need needs to be initialized with OSMTPD_NEED_RCPTTO. This attribute is a NULL-terminated array of address strings. If not available the first element in the array is set to NULL.
The envelope ID we're currently working on. osmtpd_need needs to be initialized with OSMTPD_NEED_EVPID. If not available the attribute is set to 0.
Any filter specific data that needs to be stored during the session. This is initialized on ctx creation by calling oncreate argument from osmtpd_local_session.
Any filter specific data that needs to be stored during the message transaction. This is initialized on ctx creation by calling oncreate argument from osmtpd_local_message.

The osmtpd_register_filter class of functions must call one of osmtpd_filter_proceed, osmtpd_filter_rewrite, osmtpd_filter_reject and osmtpd_filter_disconnect. This can be done either in the callback function itself, or at a later moment through another callback. Note that the session stalls until the osmtpd_filter has been called.

Exceptions to the above reply options are:

osmtpd_register_filter_connect's and osmtpd_register_filter functions' callbacks without argument can't use osmtpd_filter_rewrite.
osmtpd_register_filter_dataline's callback can only use osmtpd_filter_dataline.

osmtpd_err and osmtpd_errx can be used as a standin for err(3) and errx(3) without printing the program name to stderr.

event_init(3), smtpd.conf(5)

The osmtpd_run API first appeared in OpenBSD 6.6.

Martijn van Duren <martijn@openbsd.org>

June 22, 2023 Linux 6.3.8-arch1-1