.\" Automatically generated from an mdoc input file. Do not edit. .\" $OpenBSD$ .\" .\" Copyright (c) 2019 Martijn van Duren .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .TH "OSMTPD_RUN" "3" "June 22, 2023" "Linux 6.3.8-arch1-1" "Library Functions Manual" .nh .if n .ad l .SH "NAME" \fBosmtpd_register_filter_connect\fR, \fBosmtpd_register_filter_helo\fR, \fBosmtpd_register_filter_ehlo\fR, \fBosmtpd_register_filter_starttls\fR, \fBosmtpd_register_filter_auth\fR, \fBosmtpd_register_filter_mailfrom\fR, \fBosmtpd_register_filter_rcptto\fR, \fBosmtpd_register_filter_data\fR, \fBosmtpd_register_filter_dataline\fR, \fBosmtpd_register_filter_rset\fR, \fBosmtpd_register_filter_quit\fR, \fBosmtpd_register_filter_noop\fR, \fBosmtpd_register_filter_help\fR, \fBosmtpd_register_filter_wiz\fR, \fBosmtpd_register_filter_commit\fR, \fBosmtpd_register_report_connect\fR, \fBosmtpd_register_report_disconnect\fR, \fBosmtpd_register_report_identify\fR, \fBosmtpd_register_report_tls\fR, \fBosmtpd_register_report_begin\fR, \fBosmtpd_register_report_mail\fR, \fBosmtpd_register_report_rcpt\fR, \fBosmtpd_register_report_envelope\fR, \fBosmtpd_register_report_data\fR, \fBosmtpd_register_report_commit\fR, \fBosmtpd_register_report_rollback\fR, \fBosmtpd_register_report_client\fR, \fBosmtpd_register_report_server\fR, \fBosmtpd_register_report_response\fR, \fBosmtpd_register_report_timeout\fR, \fBosmtpd_local_session\fR, \fBosmtpd_local_message\fR, \fBosmtpd_need\fR, \fBosmtpd_filter_proceed\fR, \fBosmtpd_filter_reject\fR, \fBosmtpd_filter_disconnect\fR, \fBosmtpd_filter_rewrite\fR, \fBosmtpd_filter_dataline\fR, \fBosmtpd_run\fR, \fBosmtpd_err\fR, \fBosmtpd_errx\fR \- C filter API for smtpd(8) .SH "SYNOPSIS" \fB#include \fR .sp \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_connect\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *hostname,\ struct\ sockaddr_storage\ *ss)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_helo\fR(\fIvoid\ (cb*)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *helo)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_ehlo\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *ehlo)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_starttls\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_auth\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *auth)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_mailfrom\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *from)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_rcptto\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *rcpt)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_data\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_dataline\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *line)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_rset\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_quit\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_noop\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_help\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_wiz\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_filter_commit\fR(\fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_connect\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *rdns,\ enum\ osmtpd_status\ fcrdns,\ struct\ sockaddr_storage\ *src,\ struct\ sockaddr_storage\ *dst)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_disconnect\fR(\fIint\ incoming\fR, \fIvoid\ (*ctx)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_identify\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *identity)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_tls\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *ciphers)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_begin\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_mail\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid,\ const\ char\ *mailfrom,\ enum\ osmtpd_status\ status)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_rcpt\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid,\ const\ char\ *rcptto,\ enum\ osmtpd_status\ status)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_envelope\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid,\ uint64_t\ evpid)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_data\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid,\ enum\ osmtpd_status\ status)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_commit\fR(\fIint\fR, \fIincoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid,\ size_t\ msgsz)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_rollback\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ uint32_t\ msgid)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_client\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *cmd)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_server\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *resp)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_response\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx,\ const\ char\ *resp)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_register_report_timeout\fR(\fIint\ incoming\fR, \fIvoid\ (*cb)(struct\ osmtpd_ctx\ *ctx)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_local_session\fR(\fIvoid\ *(*oncreate)(struct\ osmtpd_ctx\ *ctx)\fR, \fIvoid\ (*ondelete)(struct\ osmtpd_ctx\ *ctx,\ void\ *data)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_local_message\fR(\fIvoid\ *(*oncreate)(struct\ osmtpd_ctx\ *ctx)\fR, \fIvoid\ (*ondelete)(struct\ osmtpd_ctx\ *ctx,\ void\ *data)\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_need\fR(\fIint\ needs\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_filter_proceed\fR(\fIstruct\ osmtpd_ctx\ *ctx\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_filter_reject\fR(\fIstruct\ osmtpd_ctx\ *ctx\fR, \fIint\ error\fR, \fIconst\ char\ *msg\fR, \fI...\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_filter_disconnect\fR(\fIstruct\ osmtpd_ctx\ *ctx\fR, \fIconst\ char\ *msg\fR, \fI...\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_filter_rewrite\fR(\fIstruct\ osmtpd_ctx\ *ctx\fR, \fIconst\ char\ *value\fR, \fI...\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_filter_dataline\fR(\fIstruct\ osmtpd_ctx\ *ctx\fR, \fIconst\ char\ *line\fR, \fI...\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_run\fR(\fIvoid\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_err\fR(\fIint\ eval\fR, \fIconst\ char\ *fmt\fR, \fI...\fR); .PD .PP \fIvoid\fR .br .PD 0 .HP 4n \fBosmtpd_errx\fR(\fIint\ eval\fR, \fIconst\ char\ *fmt\fR, \fI...\fR); .PD .SH "DESCRIPTION" The \fBosmtpd\fR API is an event based interface for writing smtpd(8) filters. Filter and report callbacks are registered via the \fBosmtpd_register\fR class of functions, followed by \fBosmtpd_run\fR. .PP \fBosmtpd_run\fR 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. .PP Each callback \fIcb\fR gets at least a pointer of the type \fIstruct\fR, \fIosmtpd_ctx\fR. It contains the following elements: .TP 8n \fIenum\ osmtpd_type\ type\fR The type of request being made. The possible values are \fROSMTPD_TYPE_FILTER\fR and \fROSMTPD_TYPE_REPORT\fR. .TP 8n \fIenum osmtpd_phase\fR \fIphase\fR The phase in the transaction which triggered the callback. The following values match their respective \fBosmtpd_register\fR function: .PD 0 .PP .RS 8n .TP 30n \fROSMTPD_PHASE_CONNECT\fR \fBosmtpd_register_filter_connect\fR .TP 30n \fROSMTPD_PHASE_HELO\fR \fBosmtpd_register_filter_helo\fR .TP 30n \fROSMTPD_PHASE_EHLO\fR \fBosmtpd_register_filter_ehlo\fR .TP 30n \fROSMTPD_PHASE_STARTTLS\fR \fBosmtpd_register_filter_starttls\fR .TP 30n \fROSMTPD_PHASE_AUTH\fR \fBosmtpd_register_filter_auth\fR .TP 30n \fROSMTPD_PHASE_MAIL_FROM\fR \fBosmtpd_register_filter_mailfrom\fR .TP 30n \fROSMTPD_PHASE_RCPT_TO\fR \fBosmtpd_register_filter_rcptto\fR .TP 30n \fROSMTPD_PHASE_DATA\fR \fBosmtpd_register_filter_data\fR .TP 30n \fROSMTPD_PHASE_DATA_LINE\fR \fBosmtpd_register_filter_dataline\fR .TP 30n \fROSMTPD_PHASE_RSET\fR \fBosmtpd_register_filter_rset\fR .TP 30n \fROSMTPD_PHASE_QUIT\fR \fBosmtpd_register_filter_quit\fR .TP 30n \fROSMTPD_PHASE_NOOP\fR \fBosmtpd_register_filter_noop\fR .TP 30n \fROSMTPD_PHASE_HELP\fR \fBosmtpd_register_filter_help\fR .TP 30n \fROSMTPD_PHASE_WIZ\fR \fBosmtpd_register_filter_wiz\fR .TP 30n \fROSMTPD_PHASE_COMMIT\fR \fBosmtpd_register_filter_commit\fR .TP 30n \fROSMTPD_PHASE_LINK_CONNECT\fR \fBosmtpd_register_report_connect\fR .TP 30n OSMTPD_PHASE_LINK_DISCONNECT \fBosmtpd_register_report_disconnect\fR .TP 30n \fROSMTPD_PHASE_LINK_IDENTIFY\fR \fBosmtpd_register_report_identify\fR .TP 30n \fROSMTPD_PHASE_LINK_TLS\fR \fBosmtpd_register_report_tls\fR .TP 30n \fROSMTPD_PHASE_TX_BEGIN\fR \fBosmtpd_register_report_begin\fR .TP 30n \fROSMTPD_PHASE_TX_MAIL\fR \fBosmtpd_register_report_mail\fR .TP 30n \fROSMTPD_PHASE_TX_RCPT\fR \fBosmtpd_register_report_rcpt\fR .TP 30n \fROSMTPD_PHASE_TX_ENVELOPE\fR \fBosmtpd_register_report_envelope\fR .TP 30n \fROSMTPD_PHASE_TX_DATA\fR \fBosmtpd_register_report_data\fR .TP 30n \fROSMTPD_PHASE_TX_COMMIT\fR \fBosmtpd_register_report_commit\fR .TP 30n \fROSMTPD_PHASE_TX_ROLLBACK\fR \fBosmtpd_register_report_rollback\fR .TP 30n \fROSMTPD_PHASE_PROTOCOL_CLIENT\fR \fBosmtpd_register_report_client\fR .TP 30n \fROSMTPD_PHASE_PROTOCOL_SERVER\fR \fBosmtpd_register_report_server\fR .TP 30n \fROSMTPD_PHASE_FILTER_RESPONSE\fR \fBosmtpd_register_report_response\fR .TP 30n \fROSMTPD_PHASE_TIMEOUT\fR. \fBosmtpd_register_report_timeout\fR .PP .RE .PD .TP 8n \fIint\fR \fIversion_major\fR The major version number of the protocol. Most filters don't need this information. .TP 8n \fIint\fR \fIversion_minor\fR The minor version number of the protocol. Most filters don't need this information. .TP 8n \fIstruct timespec\fR \fItm\fR The time the event was triggered inside smtpd(8). .TP 8n \fIint\fR \fIincoming\fR Set to 1 if the event was based on an incoming connection, 0 if it's an outgoing connection. The \fBosmtpd_register_filter\fR class of functions is always based on incoming connections. \fBosmtpd_register_report\fR can be both incoming and outgoing. .TP 8n \fIuint64_t\fR \fIreqid\fR 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 \fBosmtpd_local_session\fR and \fIlocal_session\fR. .TP 8n \fIuint64_t\fR \fItoken\fR The filter specific token. Most filters don't need this information. .TP 8n \fIstruct sockaddr_storage\fR \fIsrc\fR The source address and port of the connection. This needs to be cast to the appropriate sockaddr type based on the \fIss_family\fR attribute. It can have the following families: \fRAF_INET\fR, \fRAF_INET6\fR and \fRAF_UNIX\fR. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_SRC\fR. If not available the entire attribute is zeroed out. .TP 8n \fIstruct sockaddr_storage\fR \fIdst\fR The destination address and port of the connection. This needs to be cast to the appropriate sockaddr type based on the \fIss_family\fR attribute. It can have the following families: \fRAF_INET\fR, \fRAF_INET6\fR and \fRAF_UNIX\fR. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_DST\fR. If not available the entire attribute is zeroed out. .TP 8n \fIchar\fR \fI*rdns\fR The reverse DNS hostname of the connection. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_RDNS\fR. If not available the attribute is set to \fRNULL\fR. .TP 8n \fIenum osmtpd_status\fR \fIfcrdns\fR Whether the reverse DNS hostname is forward confirmed. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_FCRDNS\fR. If not available the attribute is set to \fROSMTPD_STATUS_TEMPFAIL\fR. .TP 8n \fIchar\fR \fI*identity\fR The identity of the remote host as presented by the HELO or EHLO SMTP command. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_IDENTITY\fR. If not available the attribute is set to \fRNULL\fR. .TP 8n \fIchar\fR \fI*ciphers\fR The ciphers used during (start)tls. To use this attribute, initialize \fBosmtpd_need\fR with \fROSMTPD_NEED_CIPHERS\fR. If not available the attribute is set to \fRNULL\fR. .TP 8n \fIuint32_t\fR \fImsgid\fR The message ID of the current message being handled in the SMTP transaction. This value can be useful for logging. \fBosmtpd_need\fR needs to be initialized with \fROSMTPD_NEED_MSGID\fR. If not available the attribute is set to \fR0\fR. Filters in need of filter specific data can use \fBosmtpd_local_message\fR and \fIlocal_message\fR. .TP 8n \fIchar\fR \fI*mailfrom\fR The envelope MAIL FROM address in the SMTP transaction. \fBosmtpd_need\fR needs to be initialized with \fROSMTPD_NEED_MAILFROM\fR. If not available the attribute is set to \fRNULL\fR. .TP 8n \fIchar\fR \fI**rcptto\fR The envelope RCPT TO address in the SMTP transaction. \fBosmtpd_need\fR needs to be initialized with \fROSMTPD_NEED_RCPTTO\fR. This attribute is a NULL-terminated array of address strings. If not available the first element in the array is set to \fRNULL\fR. .TP 8n \fIuint64_t\fR \fIevpid\fR The envelope ID we're currently working on. \fBosmtpd_need\fR needs to be initialized with \fROSMTPD_NEED_EVPID\fR. If not available the attribute is set to \fR0\fR. .TP 8n \fIvoid\fR \fI*local_session\fR Any filter specific data that needs to be stored during the session. This is initialized on \fIctx\fR creation by calling \fIoncreate\fR argument from \fBosmtpd_local_session\fR. .TP 8n \fIvoid\fR \fI*local_message\fR Any filter specific data that needs to be stored during the message transaction. This is initialized on \fIctx\fR creation by calling \fIoncreate\fR argument from \fBosmtpd_local_message\fR. .PP The \fBosmtpd_register_filter\fR class of functions must call one of \fBosmtpd_filter_proceed\fR, \fBosmtpd_filter_rewrite\fR, \fBosmtpd_filter_reject\fR and \fBosmtpd_filter_disconnect\fR. 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 \fBosmtpd_filter\fR has been called. .PP Exceptions to the above reply options are: .TP 8n \fB\(bu\fR \fBosmtpd_register_filter_connect\fR's and \fBosmtpd_register_filter\fR functions' callbacks without argument can't use \fBosmtpd_filter_rewrite\fR. .PD 0 .TP 8n \fB\(bu\fR \fBosmtpd_register_filter_dataline\fR's callback can only use osmtpd_filter_dataline. .PD .PP \fBosmtpd_err\fR and \fBosmtpd_errx\fR can be used as a standin for err(3) and errx(3) without printing the program name to stderr. .SH "SEE ALSO" event_init(3), smtpd.conf(5) .SH "HISTORY" The \fBosmtpd_run\fR API first appeared in OpenBSD\ 6.6. .SH "AUTHORS" Martijn van Duren <\fImartijn@openbsd.org\fR>