OSMTPD_RUN(3)

NAME
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)

SYNOPSIS
#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, ...);

DESCRIPTION
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:

enum osmtpd_type type
    The type of request being made. The possible values are OSMTPD_TYPE_FILTER and OSMTPD_TYPE_REPORT.

enum osmtpd_phase phase
    The phase in the transaction which triggered the callback. The following values match their respective osmtpd_register function:
    OSMTPD_PHASE_CONNECT
        osmtpd_register_filter_connect
    OSMTPD_PHASE_HELO
        osmtpd_register_filter_helo
    OSMTPD_PHASE_EHLO
        osmtpd_register_filter_ehlo
    OSMTPD_PHASE_STARTTLS
        osmtpd_register_filter_starttls
    OSMTPD_PHASE_AUTH
        osmtpd_register_filter_auth
    OSMTPD_PHASE_MAIL_FROM
        osmtpd_register_filter_mailfrom
    OSMTPD_PHASE_RCPT_TO
        osmtpd_register_filter_rcptto
    OSMTPD_PHASE_DATA
        osmtpd_register_filter_data
    OSMTPD_PHASE_DATA_LINE
        osmtpd_register_filter_dataline
    OSMTPD_PHASE_RSET
        osmtpd_register_filter_rset
    OSMTPD_PHASE_QUIT
        osmtpd_register_filter_quit
    OSMTPD_PHASE_NOOP
        osmtpd_register_filter_noop
    OSMTPD_PHASE_HELP
        osmtpd_register_filter_help
    OSMTPD_PHASE_WIZ
        osmtpd_register_filter_wiz
    OSMTPD_PHASE_COMMIT
        osmtpd_register_filter_commit
    OSMTPD_PHASE_LINK_CONNECT
        osmtpd_register_report_connect
    OSMTPD_PHASE_LINK_DISCONNECT
        osmtpd_register_report_disconnect
    OSMTPD_PHASE_LINK_IDENTIFY
        osmtpd_register_report_identify
    OSMTPD_PHASE_LINK_TLS
        osmtpd_register_report_tls
    OSMTPD_PHASE_TX_BEGIN
        osmtpd_register_report_begin
    OSMTPD_PHASE_TX_MAIL
        osmtpd_register_report_mail
    OSMTPD_PHASE_TX_RCPT
        osmtpd_register_report_rcpt
    OSMTPD_PHASE_TX_ENVELOPE
        osmtpd_register_report_envelope
    OSMTPD_PHASE_TX_DATA
        osmtpd_register_report_data
    OSMTPD_PHASE_TX_COMMIT
        osmtpd_register_report_commit
    OSMTPD_PHASE_TX_ROLLBACK
        osmtpd_register_report_rollback
    OSMTPD_PHASE_PROTOCOL_CLIENT
        osmtpd_register_report_client
    OSMTPD_PHASE_PROTOCOL_SERVER
        osmtpd_register_report_server
    OSMTPD_PHASE_FILTER_RESPONSE
        osmtpd_register_report_response
    OSMTPD_PHASE_TIMEOUT.
        osmtpd_register_report_timeout

int version_major
    The major version number of the protocol. Most filters don't need this information.

int version_minor
    The minor version number of the protocol. Most filters don't need this information.

struct timespec tm
    The time the event was triggered inside smtpd(8).

int incoming
    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.

uint64_t reqid
    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.

uint64_t token
    The filter specific token. Most filters don't need this information.

struct sockaddr_storage src
    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.

struct sockaddr_storage dst
    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.

char *rdns
    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.

enum osmtpd_status fcrdns
    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.

char *identity
    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.

char *ciphers
    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.

uint32_t msgid
    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.

char *mailfrom
    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.

char **rcptto
    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.

uint64_t evpid
    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.

void *local_session
    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.

void *local_message
    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.

SEE ALSO
event_init(3), smtpd.conf(5)

HISTORY
The osmtpd_run API first appeared in OpenBSD 6.6.

AUTHORS
Martijn van Duren <martijn@openbsd.org>