osmtpd_run3
C filter api for smtpd(8)
Usage
#include <opensmtpd.h>
void
osmtpd_register_filter_connect(int (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss));
void
osmtpd_register_filter_helo(int (*cb)(struct osmtpd_ctx *ctx, const char *helo));
void
osmtpd_register_filter_ehlo(int (*cb)(struct osmtpd_ctx *ctx, const char *ehlo));
void
osmtpd_register_filter_starttls(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_auth(int (*cb)(struct osmtpd_ctx *ctx, const char *auth));
void
osmtpd_register_filter_mailfrom(int (*cb)(struct osmtpd_ctx *ctx, const char *from));
void
osmtpd_register_filter_rcptto(int (*cb)(struct osmtpd_ctx *ctx, const char *rcpt));
void
osmtpd_register_filter_data(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_dataline(int (*cb)(struct osmtpd_ctx *ctx, const char *line));
void
osmtpd_register_filter_rset(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_quit(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_noop(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_help(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_wiz(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_filter_commit(int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_report_connect(int incoming, int (*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, int (*cb)(struct osmtpd_ctx *ctx));
void
osmtpd_register_report_identify(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *identity));
void
osmtpd_register_report_tls(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *ciphers));
void
osmtpd_register_report_auth(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *username, enum osmtpd_auth_status status));
void
osmtpd_register_report_reset(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid));
void
osmtpd_register_report_begin(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid));
void
osmtpd_register_report_mail(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status));
void
osmtpd_register_report_rcpt(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status));
void
osmtpd_register_report_envelope(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid));
void
osmtpd_register_report_data(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status));
void
osmtpd_register_report_commit(int, incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz));
void
osmtpd_register_report_rollback(int incoming, int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid));
void
osmtpd_register_report_client(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *cmd));
void
osmtpd_register_report_server(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *resp));
void
osmtpd_register_report_response(int incoming, int (*cb)(struct osmtpd_ctx *ctx, const char *resp));
void
osmtpd_register_report_timeout(int incoming, int (*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_warn(struct osmtpd_ctx *ctx, const char *fmt, ...);
void
osmtpd_warnx(struct osmtpd_ctx *ctx, const char *fmt, ...);
void
osmtpd_err(int eval, const char *fmt, ...);
void
osmtpd_errx(int eval, const char *fmt, ...);
Overview
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. A callback should return 0 in the case of success, or -1 in the case of error which leads to disconnect of this session.
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_registerfunction:
OSMTPD_PHASE_CONNECT
|
|
|---|---|
OSMTPD_PHASE_HELO
|
|
OSMTPD_PHASE_EHLO
|
|
OSMTPD_PHASE_STARTTLS
|
|
OSMTPD_PHASE_AUTH
|
|
OSMTPD_PHASE_MAIL_FROM
|
|
OSMTPD_PHASE_RCPT_TO
|
|
OSMTPD_PHASE_DATA
|
|
OSMTPD_PHASE_DATA_LINE
|
|
OSMTPD_PHASE_RSET
|
|
OSMTPD_PHASE_QUIT
|
|
OSMTPD_PHASE_NOOP
|
|
OSMTPD_PHASE_HELP
|
|
OSMTPD_PHASE_WIZ
|
|
OSMTPD_PHASE_COMMIT
|
|
OSMTPD_PHASE_LINK_CONNECT
|
|
OSMTPD_PHASE_LINK_DISCONNECT
|
|
OSMTPD_PHASE_LINK_IDENTIFY
|
|
OSMTPD_PHASE_LINK_TLS
|
|
OSMTPD_PHASE_LINK_AUTH
|
|
OSMTPD_PHASE_TX_RESET
|
|
OSMTPD_PHASE_TX_BEGIN
|
|
OSMTPD_PHASE_TX_MAIL
|
|
OSMTPD_PHASE_TX_RCPT
|
|
OSMTPD_PHASE_TX_ENVELOPE
|
|
OSMTPD_PHASE_TX_DATA
|
|
OSMTPD_PHASE_TX_COMMIT
|
|
OSMTPD_PHASE_TX_ROLLBACK
|
|
OSMTPD_PHASE_PROTOCOL_CLIENT
|
|
OSMTPD_PHASE_PROTOCOL_SERVER
|
|
OSMTPD_PHASE_FILTER_RESPONSE
|
|
OSMTPD_PHASE_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_filterclass of functions is always based on incoming connections.osmtpd_register_reportcan 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_sessionand 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_needwith 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_needwith 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_needwith 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_needwith 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_needwith 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_needwith 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_needneeds to be initialized with OSMTPD_NEED_MSGID. If not available the attribute is set to 0. Filters in need of filter specific data can useosmtpd_local_messageand local_message.
- char *username
-
The username with which the session was successfully authenticated.
osmtpd_needneeds to be initialized with If not available or authentication failed is set to NULL.
- char *mailfrom
-
The envelope MAIL FROM address in the SMTP transaction.
osmtpd_needneeds 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_needneeds 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_needneeds 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 andosmtpd_register_filterfunctions' callbacks without argument can't useosmtpd_filter_rewrite.
- •
-
osmtpd_register_filter_dataline's callback can only use osmtpd_filter_dataline.
osmtpd_warn, osmtpd_warnx, osmtpd_err and osmtpd_errx can be used as a standin for warn(3) , warnx(3) , err(3) and errx(3) without printing the program name to stderr. Additionally, osmtpd_warn and osmtpd_warnx prints the request ID on the logline when ctx is not NULL.
Releases
3 releases since Debian 12 (Bookworm); the text changed 2 times.