diff options
Diffstat (limited to 'smtpd/smtpd.h')
-rw-r--r-- | smtpd/smtpd.h | 1784 |
1 files changed, 1784 insertions, 0 deletions
diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h new file mode 100644 index 00000000..4385f747 --- /dev/null +++ b/smtpd/smtpd.h @@ -0,0 +1,1784 @@ +/* $OpenBSD: smtpd.h,v 1.656 2020/04/08 07:30:44 eric Exp $ */ + +/* + * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> + * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> + * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> + * + * 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. + */ + +#include <event.h> + +#include <imsg.h> + +#include "openbsd-compat.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +#include <netinet/in.h> +#include <netdb.h> +#include <event.h> + +#include "smtpd-defines.h" +#include "smtpd-api.h" +#include "ioev.h" + +#define CHECK_IMSG_DATA_SIZE(imsg, expected_sz) do { \ + if ((imsg)->hdr.len - IMSG_HEADER_SIZE != (expected_sz)) \ + fatalx("smtpd: imsg %d: data size expected %zd got %zd",\ + (imsg)->hdr.type, \ + (expected_sz), (imsg)->hdr.len - IMSG_HEADER_SIZE); \ +} while (0) + +#ifndef SMTPD_CONFDIR +#define SMTPD_CONFDIR "/etc" +#endif +#define CONF_FILE SMTPD_CONFDIR "/smtpd.conf" +#define MAILNAME_FILE SMTPD_CONFDIR "/mailname" +#ifndef CA_FILE +#define CA_FILE "/etc/ssl/cert.pem" +#endif + +#define PROC_COUNT 7 + +#define MAX_HOPS_COUNT 100 +#define DEFAULT_MAX_BODY_SIZE (35*1024*1024) + +#define EXPAND_BUFFER 1024 + +#define SMTPD_QUEUE_EXPIRY (4 * 24 * 60 * 60) +#ifndef SMTPD_USER +#define SMTPD_USER "_smtpd" +#endif +#ifndef SMTPD_QUEUE_USER +#define SMTPD_QUEUE_USER "_smtpq" +#endif +#ifndef SMTPD_SOCKDIR +#define SMTPD_SOCKDIR "/var/run" +#endif +#define SMTPD_SOCKET SMTPD_SOCKDIR "/smtpd.sock" +#ifndef SMTPD_NAME +#define SMTPD_NAME "OpenSMTPD" +#endif +#define SMTPD_VERSION "6.7.0-portable" +#define SMTPD_SESSION_TIMEOUT 300 +#define SMTPD_BACKLOG 5 + +#ifndef PATH_SMTPCTL +#define PATH_SMTPCTL "/usr/sbin/smtpctl" +#endif + +#define PATH_OFFLINE "/offline" +#define PATH_PURGE "/purge" +#define PATH_TEMPORARY "/temporary" + +#ifndef PATH_LIBEXEC +#define PATH_LIBEXEC "/usr/local/libexec/smtpd" +#endif + + +/* + * RFC 5322 defines these characters as valid, some of them are + * potentially dangerous and need to be escaped. + */ +#define MAILADDR_ALLOWED "!#$%&'*/?^`{|}~+-=_" +#define MAILADDR_ESCAPE "!#$%&'*?`{|}~" + + +#define F_STARTTLS 0x01 +#define F_SMTPS 0x02 +#define F_SSL (F_STARTTLS | F_SMTPS) +#define F_AUTH 0x08 +#define F_STARTTLS_REQUIRE 0x20 +#define F_AUTH_REQUIRE 0x40 +#define F_MASK_SOURCE 0x100 +#define F_TLS_VERIFY 0x200 +#define F_EXT_DSN 0x400 +#define F_RECEIVEDAUTH 0x800 +#define F_MASQUERADE 0x1000 +#define F_FILTERED 0x2000 +#define F_PROXY 0x4000 + +#define RELAY_TLS_OPPORTUNISTIC 0 +#define RELAY_TLS_STARTTLS 1 +#define RELAY_TLS_SMTPS 2 +#define RELAY_TLS_NO 3 + +#define RELAY_AUTH 0x08 +#define RELAY_LMTP 0x80 +#define RELAY_TLS_VERIFY 0x200 + +#define MTA_EXT_DSN 0x400 + + +#define P_SENDMAIL 0 +#define P_NEWALIASES 1 +#define P_MAKEMAP 2 + +#define CERT_ERROR -1 +#define CERT_OK 0 +#define CERT_NOCA 1 +#define CERT_NOCERT 2 +#define CERT_INVALID 3 + +struct userinfo { + char username[SMTPD_VUSERNAME_SIZE]; + char directory[PATH_MAX]; + uid_t uid; + gid_t gid; +}; + +struct netaddr { + struct sockaddr_storage ss; + int bits; +}; + +struct relayhost { + uint16_t flags; + int tls; + char hostname[HOST_NAME_MAX+1]; + uint16_t port; + char authlabel[PATH_MAX]; +}; + +struct credentials { + char username[LINE_MAX]; + char password[LINE_MAX]; +}; + +struct destination { + char name[HOST_NAME_MAX+1]; +}; + +struct source { + struct sockaddr_storage addr; +}; + +struct addrname { + struct sockaddr_storage addr; + char name[HOST_NAME_MAX+1]; +}; + +union lookup { + struct expand *expand; + struct credentials creds; + struct netaddr netaddr; + struct source source; + struct destination domain; + struct userinfo userinfo; + struct mailaddr mailaddr; + struct addrname addrname; + struct maddrmap *maddrmap; + char relayhost[LINE_MAX]; +}; + +/* + * Bump IMSG_VERSION whenever a change is made to enum imsg_type. + * This will ensure that we can never use a wrong version of smtpctl with smtpd. + */ +#define IMSG_VERSION 16 + +enum imsg_type { + IMSG_NONE, + + IMSG_CTL_OK, + IMSG_CTL_FAIL, + + IMSG_CTL_GET_DIGEST, + IMSG_CTL_GET_STATS, + IMSG_CTL_LIST_MESSAGES, + IMSG_CTL_LIST_ENVELOPES, + IMSG_CTL_MTA_SHOW_HOSTS, + IMSG_CTL_MTA_SHOW_RELAYS, + IMSG_CTL_MTA_SHOW_ROUTES, + IMSG_CTL_MTA_SHOW_HOSTSTATS, + IMSG_CTL_MTA_BLOCK, + IMSG_CTL_MTA_UNBLOCK, + IMSG_CTL_MTA_SHOW_BLOCK, + IMSG_CTL_PAUSE_EVP, + IMSG_CTL_PAUSE_MDA, + IMSG_CTL_PAUSE_MTA, + IMSG_CTL_PAUSE_SMTP, + IMSG_CTL_PROFILE, + IMSG_CTL_PROFILE_DISABLE, + IMSG_CTL_PROFILE_ENABLE, + IMSG_CTL_RESUME_EVP, + IMSG_CTL_RESUME_MDA, + IMSG_CTL_RESUME_MTA, + IMSG_CTL_RESUME_SMTP, + IMSG_CTL_RESUME_ROUTE, + IMSG_CTL_REMOVE, + IMSG_CTL_SCHEDULE, + IMSG_CTL_SHOW_STATUS, + IMSG_CTL_TRACE_DISABLE, + IMSG_CTL_TRACE_ENABLE, + IMSG_CTL_UPDATE_TABLE, + IMSG_CTL_VERBOSE, + IMSG_CTL_DISCOVER_EVPID, + IMSG_CTL_DISCOVER_MSGID, + + IMSG_CTL_SMTP_SESSION, + + IMSG_GETADDRINFO, + IMSG_GETADDRINFO_END, + IMSG_GETNAMEINFO, + IMSG_RES_QUERY, + + IMSG_CERT_INIT, + IMSG_CERT_CERTIFICATE, + IMSG_CERT_VERIFY, + + IMSG_SETUP_KEY, + IMSG_SETUP_PEER, + IMSG_SETUP_DONE, + + IMSG_CONF_START, + IMSG_CONF_END, + + IMSG_STAT_INCREMENT, + IMSG_STAT_DECREMENT, + IMSG_STAT_SET, + + IMSG_LKA_AUTHENTICATE, + IMSG_LKA_OPEN_FORWARD, + IMSG_LKA_ENVELOPE_SUBMIT, + IMSG_LKA_ENVELOPE_COMMIT, + + IMSG_QUEUE_DELIVER, + IMSG_QUEUE_DELIVERY_OK, + IMSG_QUEUE_DELIVERY_TEMPFAIL, + IMSG_QUEUE_DELIVERY_PERMFAIL, + IMSG_QUEUE_DELIVERY_LOOP, + IMSG_QUEUE_DISCOVER_EVPID, + IMSG_QUEUE_DISCOVER_MSGID, + IMSG_QUEUE_ENVELOPE_ACK, + IMSG_QUEUE_ENVELOPE_COMMIT, + IMSG_QUEUE_ENVELOPE_REMOVE, + IMSG_QUEUE_ENVELOPE_SCHEDULE, + IMSG_QUEUE_ENVELOPE_SUBMIT, + IMSG_QUEUE_HOLDQ_HOLD, + IMSG_QUEUE_HOLDQ_RELEASE, + IMSG_QUEUE_MESSAGE_COMMIT, + IMSG_QUEUE_MESSAGE_ROLLBACK, + IMSG_QUEUE_SMTP_SESSION, + IMSG_QUEUE_TRANSFER, + + IMSG_MDA_DELIVERY_OK, + IMSG_MDA_DELIVERY_TEMPFAIL, + IMSG_MDA_DELIVERY_PERMFAIL, + IMSG_MDA_DELIVERY_LOOP, + IMSG_MDA_DELIVERY_HOLD, + IMSG_MDA_DONE, + IMSG_MDA_FORK, + IMSG_MDA_HOLDQ_RELEASE, + IMSG_MDA_LOOKUP_USERINFO, + IMSG_MDA_KILL, + IMSG_MDA_OPEN_MESSAGE, + + IMSG_MTA_DELIVERY_OK, + IMSG_MTA_DELIVERY_TEMPFAIL, + IMSG_MTA_DELIVERY_PERMFAIL, + IMSG_MTA_DELIVERY_LOOP, + IMSG_MTA_DELIVERY_HOLD, + IMSG_MTA_DNS_HOST, + IMSG_MTA_DNS_HOST_END, + IMSG_MTA_DNS_MX, + IMSG_MTA_DNS_MX_PREFERENCE, + IMSG_MTA_HOLDQ_RELEASE, + IMSG_MTA_LOOKUP_CREDENTIALS, + IMSG_MTA_LOOKUP_SOURCE, + IMSG_MTA_LOOKUP_HELO, + IMSG_MTA_LOOKUP_SMARTHOST, + IMSG_MTA_OPEN_MESSAGE, + IMSG_MTA_SCHEDULE, + + IMSG_SCHED_ENVELOPE_BOUNCE, + IMSG_SCHED_ENVELOPE_DELIVER, + IMSG_SCHED_ENVELOPE_EXPIRE, + IMSG_SCHED_ENVELOPE_INJECT, + IMSG_SCHED_ENVELOPE_REMOVE, + IMSG_SCHED_ENVELOPE_TRANSFER, + + IMSG_SMTP_AUTHENTICATE, + IMSG_SMTP_MESSAGE_COMMIT, + IMSG_SMTP_MESSAGE_CREATE, + IMSG_SMTP_MESSAGE_ROLLBACK, + IMSG_SMTP_MESSAGE_OPEN, + IMSG_SMTP_CHECK_SENDER, + IMSG_SMTP_EXPAND_RCPT, + IMSG_SMTP_LOOKUP_HELO, + + IMSG_SMTP_REQ_CONNECT, + IMSG_SMTP_REQ_HELO, + IMSG_SMTP_REQ_MAIL, + IMSG_SMTP_REQ_RCPT, + IMSG_SMTP_REQ_DATA, + IMSG_SMTP_REQ_EOM, + IMSG_SMTP_EVENT_RSET, + IMSG_SMTP_EVENT_COMMIT, + IMSG_SMTP_EVENT_ROLLBACK, + IMSG_SMTP_EVENT_DISCONNECT, + + IMSG_LKA_PROCESSOR_FORK, + IMSG_LKA_PROCESSOR_ERRFD, + + IMSG_REPORT_SMTP_LINK_CONNECT, + IMSG_REPORT_SMTP_LINK_DISCONNECT, + IMSG_REPORT_SMTP_LINK_GREETING, + IMSG_REPORT_SMTP_LINK_IDENTIFY, + IMSG_REPORT_SMTP_LINK_TLS, + IMSG_REPORT_SMTP_LINK_AUTH, + IMSG_REPORT_SMTP_TX_RESET, + IMSG_REPORT_SMTP_TX_BEGIN, + IMSG_REPORT_SMTP_TX_MAIL, + IMSG_REPORT_SMTP_TX_RCPT, + IMSG_REPORT_SMTP_TX_ENVELOPE, + IMSG_REPORT_SMTP_TX_DATA, + IMSG_REPORT_SMTP_TX_COMMIT, + IMSG_REPORT_SMTP_TX_ROLLBACK, + IMSG_REPORT_SMTP_PROTOCOL_CLIENT, + IMSG_REPORT_SMTP_PROTOCOL_SERVER, + IMSG_REPORT_SMTP_FILTER_RESPONSE, + IMSG_REPORT_SMTP_TIMEOUT, + + IMSG_FILTER_SMTP_BEGIN, + IMSG_FILTER_SMTP_END, + IMSG_FILTER_SMTP_PROTOCOL, + IMSG_FILTER_SMTP_DATA_BEGIN, + IMSG_FILTER_SMTP_DATA_END, + + IMSG_CA_RSA_PRIVENC, + IMSG_CA_RSA_PRIVDEC, + IMSG_CA_ECDSA_SIGN, +}; + +enum smtp_proc_type { + PROC_PARENT = 0, + PROC_LKA, + PROC_QUEUE, + PROC_CONTROL, + PROC_SCHEDULER, + PROC_PONY, + PROC_CA, + PROC_PROCESSOR, + PROC_CLIENT, +}; + +enum table_type { + T_NONE = 0, + T_DYNAMIC = 0x01, /* table with external source */ + T_LIST = 0x02, /* table holding a list */ + T_HASH = 0x04, /* table holding a hash table */ +}; + +struct table { + char t_name[LINE_MAX]; + enum table_type t_type; + char t_config[PATH_MAX]; + + void *t_handle; + struct table_backend *t_backend; +}; + +struct table_backend { + const char *name; + const unsigned int services; + int (*config)(struct table *); + int (*add)(struct table *, const char *, const char *); + void (*dump)(struct table *); + int (*open)(struct table *); + int (*update)(struct table *); + void (*close)(struct table *); + int (*lookup)(struct table *, enum table_service, const char *, char **); + int (*fetch)(struct table *, enum table_service, char **); +}; + + +enum bounce_type { + B_FAILED, + B_DELAYED, + B_DELIVERED +}; + +enum dsn_ret { + DSN_RETFULL = 1, + DSN_RETHDRS +}; + +struct delivery_bounce { + enum bounce_type type; + time_t delay; + time_t ttl; + enum dsn_ret dsn_ret; + int mta_without_dsn; +}; + +enum expand_type { + EXPAND_INVALID, + EXPAND_USERNAME, + EXPAND_FILENAME, + EXPAND_FILTER, + EXPAND_INCLUDE, + EXPAND_ADDRESS, + EXPAND_ERROR, +}; + +enum filter_phase { + FILTER_CONNECT, + FILTER_HELO, + FILTER_EHLO, + FILTER_STARTTLS, + FILTER_AUTH, + FILTER_MAIL_FROM, + FILTER_RCPT_TO, + FILTER_DATA, + FILTER_DATA_LINE, + FILTER_RSET, + FILTER_QUIT, + FILTER_NOOP, + FILTER_HELP, + FILTER_WIZ, + FILTER_COMMIT, + FILTER_PHASES_COUNT /* must be last */ +}; + +struct expandnode { + RB_ENTRY(expandnode) entry; + TAILQ_ENTRY(expandnode) tq_entry; + enum expand_type type; + int sameuser; + int realuser; + int forwarded; + struct rule *rule; + struct expandnode *parent; + unsigned int depth; + union { + /* + * user field handles both expansion user and system user + * so we MUST make it large enough to fit a mailaddr user + */ + char user[SMTPD_MAXLOCALPARTSIZE]; + char buffer[EXPAND_BUFFER]; + struct mailaddr mailaddr; + } u; + char subaddress[SMTPD_SUBADDRESS_SIZE]; +}; + +struct expand { + RB_HEAD(expandtree, expandnode) tree; + TAILQ_HEAD(xnodes, expandnode) *queue; + size_t nb_nodes; + struct rule *rule; + struct expandnode *parent; +}; + +struct maddrnode { + TAILQ_ENTRY(maddrnode) entries; + struct mailaddr mailaddr; +}; + +struct maddrmap { + TAILQ_HEAD(xmaddr, maddrnode) queue; +}; + +#define DSN_SUCCESS 0x01 +#define DSN_FAILURE 0x02 +#define DSN_DELAY 0x04 +#define DSN_NEVER 0x08 + +#define DSN_ENVID_LEN 100 + +#define SMTPD_ENVELOPE_VERSION 3 +struct envelope { + TAILQ_ENTRY(envelope) entry; + + char dispatcher[HOST_NAME_MAX+1]; + + char tag[SMTPD_TAG_SIZE]; + + uint32_t version; + uint64_t id; + enum envelope_flags flags; + + char smtpname[HOST_NAME_MAX+1]; + char helo[HOST_NAME_MAX+1]; + char hostname[HOST_NAME_MAX+1]; + char username[SMTPD_MAXMAILADDRSIZE]; + char errorline[LINE_MAX]; + struct sockaddr_storage ss; + + struct mailaddr sender; + struct mailaddr rcpt; + struct mailaddr dest; + + char mda_user[SMTPD_VUSERNAME_SIZE]; + char mda_subaddress[SMTPD_SUBADDRESS_SIZE]; + char mda_exec[LINE_MAX]; + + enum delivery_type type; + union { + struct delivery_bounce bounce; + } agent; + + uint16_t retry; + time_t creation; + time_t ttl; + time_t lasttry; + time_t nexttry; + time_t lastbounce; + + struct mailaddr dsn_orcpt; + char dsn_envid[DSN_ENVID_LEN+1]; + uint8_t dsn_notify; + enum dsn_ret dsn_ret; + + uint8_t esc_class; + uint8_t esc_code; +}; + +struct listener { + uint16_t flags; + int fd; + struct sockaddr_storage ss; + in_port_t port; + struct timeval timeout; + struct event ev; + char filter_name[PATH_MAX]; + char pki_name[PATH_MAX]; + char ca_name[PATH_MAX]; + char tag[SMTPD_TAG_SIZE]; + char authtable[LINE_MAX]; + char hostname[HOST_NAME_MAX+1]; + char hostnametable[PATH_MAX]; + char sendertable[PATH_MAX]; + + TAILQ_ENTRY(listener) entry; + + int local; /* there must be a better way */ +}; + +struct smtpd { + char sc_conffile[PATH_MAX]; + size_t sc_maxsize; + +#define SMTPD_OPT_VERBOSE 0x00000001 +#define SMTPD_OPT_NOACTION 0x00000002 + uint32_t sc_opts; + +#define SMTPD_EXITING 0x00000001 /* unused */ +#define SMTPD_MDA_PAUSED 0x00000002 +#define SMTPD_MTA_PAUSED 0x00000004 +#define SMTPD_SMTP_PAUSED 0x00000008 +#define SMTPD_MDA_BUSY 0x00000010 +#define SMTPD_MTA_BUSY 0x00000020 +#define SMTPD_BOUNCE_BUSY 0x00000040 +#define SMTPD_SMTP_DISABLED 0x00000080 + uint32_t sc_flags; + +#define QUEUE_COMPRESSION 0x00000001 +#define QUEUE_ENCRYPTION 0x00000002 +#define QUEUE_EVPCACHE 0x00000004 + uint32_t sc_queue_flags; + char *sc_queue_key; + size_t sc_queue_evpcache_size; + + size_t sc_session_max_rcpt; + size_t sc_session_max_mails; + + struct dict *sc_mda_wrappers; + size_t sc_mda_max_session; + size_t sc_mda_max_user_session; + size_t sc_mda_task_hiwat; + size_t sc_mda_task_lowat; + size_t sc_mda_task_release; + + size_t sc_mta_max_deferred; + + size_t sc_scheduler_max_inflight; + size_t sc_scheduler_max_evp_batch_size; + size_t sc_scheduler_max_msg_batch_size; + size_t sc_scheduler_max_schedule; + + struct dict *sc_filter_processes_dict; + + int sc_ttl; +#define MAX_BOUNCE_WARN 4 + time_t sc_bounce_warn[MAX_BOUNCE_WARN]; + char sc_hostname[HOST_NAME_MAX+1]; + struct stat_backend *sc_stat; + struct compress_backend *sc_comp; + + time_t sc_uptime; + + /* This is a listener for a local socket used by smtp_enqueue(). */ + struct listener *sc_sock_listener; + + TAILQ_HEAD(listenerlist, listener) *sc_listeners; + + TAILQ_HEAD(rulelist, rule) *sc_rules; + + + struct dict *sc_filters_dict; + struct dict *sc_dispatchers; + struct dispatcher *sc_dispatcher_bounce; + + struct dict *sc_ca_dict; + struct dict *sc_pki_dict; + struct dict *sc_ssl_dict; + + struct dict *sc_tables_dict; /* keyed lookup */ + + struct dict *sc_limits_dict; + + char *sc_tls_ciphers; + + char *sc_subaddressing_delim; + + char *sc_srs_key; + char *sc_srs_key_backup; + int sc_srs_ttl; +}; + +#define TRACE_DEBUG 0x0001 +#define TRACE_IMSG 0x0002 +#define TRACE_IO 0x0004 +#define TRACE_SMTP 0x0008 +#define TRACE_FILTERS 0x0010 +#define TRACE_MTA 0x0020 +#define TRACE_BOUNCE 0x0040 +#define TRACE_SCHEDULER 0x0080 +#define TRACE_LOOKUP 0x0100 +#define TRACE_STAT 0x0200 +#define TRACE_RULES 0x0400 +#define TRACE_MPROC 0x0800 +#define TRACE_EXPAND 0x1000 +#define TRACE_TABLES 0x2000 +#define TRACE_QUEUE 0x4000 + +#define PROFILE_TOSTAT 0x0001 +#define PROFILE_IMSG 0x0002 +#define PROFILE_QUEUE 0x0004 + +struct forward_req { + uint64_t id; + uint8_t status; + + char user[SMTPD_VUSERNAME_SIZE]; + uid_t uid; + gid_t gid; + char directory[PATH_MAX]; +}; + +struct deliver { + char dispatcher[EXPAND_BUFFER]; + + struct mailaddr sender; + struct mailaddr rcpt; + struct mailaddr dest; + + char mda_subaddress[SMTPD_SUBADDRESS_SIZE]; + char mda_exec[LINE_MAX]; + + struct userinfo userinfo; +}; + +struct mta_host { + SPLAY_ENTRY(mta_host) entry; + struct sockaddr *sa; + char *ptrname; + int refcount; + size_t nconn; + time_t lastconn; + time_t lastptrquery; + +#define HOST_IGNORE 0x01 + int flags; +}; + +struct mta_mx { + TAILQ_ENTRY(mta_mx) entry; + struct mta_host *host; + char *mxname; + int preference; +}; + +struct mta_domain { + SPLAY_ENTRY(mta_domain) entry; + char *name; + int as_host; + TAILQ_HEAD(, mta_mx) mxs; + int mxstatus; + int refcount; + size_t nconn; + time_t lastconn; + time_t lastmxquery; +}; + +struct mta_source { + SPLAY_ENTRY(mta_source) entry; + struct sockaddr *sa; + int refcount; + size_t nconn; + time_t lastconn; +}; + +struct mta_connector { + struct mta_source *source; + struct mta_relay *relay; + +#define CONNECTOR_ERROR_FAMILY 0x0001 +#define CONNECTOR_ERROR_SOURCE 0x0002 +#define CONNECTOR_ERROR_MX 0x0004 +#define CONNECTOR_ERROR_ROUTE_NET 0x0008 +#define CONNECTOR_ERROR_ROUTE_SMTP 0x0010 +#define CONNECTOR_ERROR_ROUTE 0x0018 +#define CONNECTOR_ERROR_BLOCKED 0x0020 +#define CONNECTOR_ERROR 0x00ff + +#define CONNECTOR_LIMIT_HOST 0x0100 +#define CONNECTOR_LIMIT_ROUTE 0x0200 +#define CONNECTOR_LIMIT_SOURCE 0x0400 +#define CONNECTOR_LIMIT_RELAY 0x0800 +#define CONNECTOR_LIMIT_CONN 0x1000 +#define CONNECTOR_LIMIT_DOMAIN 0x2000 +#define CONNECTOR_LIMIT 0xff00 + +#define CONNECTOR_NEW 0x10000 +#define CONNECTOR_WAIT 0x20000 + int flags; + + int refcount; + size_t nconn; + time_t lastconn; +}; + +struct mta_route { + SPLAY_ENTRY(mta_route) entry; + uint64_t id; + struct mta_source *src; + struct mta_host *dst; +#define ROUTE_NEW 0x01 +#define ROUTE_RUNQ 0x02 +#define ROUTE_KEEPALIVE 0x04 +#define ROUTE_DISABLED 0xf0 +#define ROUTE_DISABLED_NET 0x10 +#define ROUTE_DISABLED_SMTP 0x20 + int flags; + int nerror; + int penalty; + int refcount; + size_t nconn; + time_t lastconn; + time_t lastdisc; + time_t lastpenalty; +}; + +struct mta_limits { + size_t maxconn_per_host; + size_t maxconn_per_route; + size_t maxconn_per_source; + size_t maxconn_per_connector; + size_t maxconn_per_relay; + size_t maxconn_per_domain; + + time_t conndelay_host; + time_t conndelay_route; + time_t conndelay_source; + time_t conndelay_connector; + time_t conndelay_relay; + time_t conndelay_domain; + + time_t discdelay_route; + + size_t max_mail_per_session; + time_t sessdelay_transaction; + time_t sessdelay_keepalive; + + size_t max_failures_per_session; + + int family; + + int task_hiwat; + int task_lowat; + int task_release; +}; + +struct mta_relay { + SPLAY_ENTRY(mta_relay) entry; + uint64_t id; + + struct dispatcher *dispatcher; + struct mta_domain *domain; + struct mta_limits *limits; + int tls; + int flags; + char *backupname; + int backuppref; + char *sourcetable; + uint16_t port; + char *pki_name; + char *ca_name; + char *authtable; + char *authlabel; + char *helotable; + char *heloname; + char *secret; + int srs; + + int state; + size_t ntask; + TAILQ_HEAD(, mta_task) tasks; + + struct tree connectors; + size_t sourceloop; + time_t lastsource; + time_t nextsource; + + int fail; + char *failstr; + +#define RELAY_WAIT_MX 0x01 +#define RELAY_WAIT_PREFERENCE 0x02 +#define RELAY_WAIT_SECRET 0x04 +#define RELAY_WAIT_LIMITS 0x08 +#define RELAY_WAIT_SOURCE 0x10 +#define RELAY_WAIT_CONNECTOR 0x20 +#define RELAY_WAIT_SMARTHOST 0x40 +#define RELAY_WAITMASK 0x7f + int status; + + int refcount; + size_t nconn; + size_t nconn_ready; + time_t lastconn; +}; + +struct mta_envelope { + TAILQ_ENTRY(mta_envelope) entry; + uint64_t id; + uint64_t session; + time_t creation; + char *smtpname; + char *dest; + char *rcpt; + struct mta_task *task; + int delivery; + + int ext; + char *dsn_orcpt; + char dsn_envid[DSN_ENVID_LEN+1]; + uint8_t dsn_notify; + enum dsn_ret dsn_ret; + + char status[LINE_MAX]; +}; + +struct mta_task { + TAILQ_ENTRY(mta_task) entry; + struct mta_relay *relay; + uint32_t msgid; + TAILQ_HEAD(, mta_envelope) envelopes; + char *sender; +}; + +struct passwd; + +struct queue_backend { + int (*init)(struct passwd *, int, const char *); +}; + +struct compress_backend { + size_t (*compress_chunk)(void *, size_t, void *, size_t); + size_t (*uncompress_chunk)(void *, size_t, void *, size_t); + int (*compress_file)(FILE *, FILE *); + int (*uncompress_file)(FILE *, FILE *); +}; + +/* auth structures */ +enum auth_type { + AUTH_BSD, + AUTH_PWD, +}; + +struct auth_backend { + int (*authenticate)(char *, char *); +}; + +struct scheduler_backend { + int (*init)(const char *); + + int (*insert)(struct scheduler_info *); + size_t (*commit)(uint32_t); + size_t (*rollback)(uint32_t); + + int (*update)(struct scheduler_info *); + int (*delete)(uint64_t); + int (*hold)(uint64_t, uint64_t); + int (*release)(int, uint64_t, int); + + int (*batch)(int, int*, size_t*, uint64_t*, int*); + + size_t (*messages)(uint32_t, uint32_t *, size_t); + size_t (*envelopes)(uint64_t, struct evpstate *, size_t); + int (*schedule)(uint64_t); + int (*remove)(uint64_t); + int (*suspend)(uint64_t); + int (*resume)(uint64_t); + int (*query)(uint64_t); +}; + +enum stat_type { + STAT_COUNTER, + STAT_TIMESTAMP, + STAT_TIMEVAL, + STAT_TIMESPEC, +}; + +struct stat_value { + enum stat_type type; + union stat_v { + size_t counter; + time_t timestamp; + struct timeval tv; + struct timespec ts; + } u; +}; + +#define STAT_KEY_SIZE 1024 +struct stat_kv { + void *iter; + char key[STAT_KEY_SIZE]; + struct stat_value val; +}; + +struct stat_backend { + void (*init)(void); + void (*close)(void); + void (*increment)(const char *, size_t); + void (*decrement)(const char *, size_t); + void (*set)(const char *, const struct stat_value *); + int (*iter)(void **, char **, struct stat_value *); +}; + +struct stat_digest { + time_t startup; + time_t timestamp; + + size_t clt_connect; + size_t clt_disconnect; + + size_t evp_enqueued; + size_t evp_dequeued; + + size_t evp_expired; + size_t evp_removed; + size_t evp_bounce; + + size_t dlv_ok; + size_t dlv_permfail; + size_t dlv_tempfail; + size_t dlv_loop; +}; + + +struct mproc { + pid_t pid; + char *name; + int proc; + void (*handler)(struct mproc *, struct imsg *); + struct imsgbuf imsgbuf; + + char *m_buf; + size_t m_alloc; + size_t m_pos; + uint32_t m_type; + uint32_t m_peerid; + pid_t m_pid; + int m_fd; + + int enable; + short events; + struct event ev; + void *data; +}; + +struct msg { + const uint8_t *pos; + const uint8_t *end; +}; + +extern enum smtp_proc_type smtpd_process; + +extern int tracing; +extern int foreground_log; +extern int profiling; + +extern struct mproc *p_control; +extern struct mproc *p_parent; +extern struct mproc *p_lka; +extern struct mproc *p_queue; +extern struct mproc *p_scheduler; +extern struct mproc *p_pony; +extern struct mproc *p_ca; + +extern struct smtpd *env; +extern void (*imsg_callback)(struct mproc *, struct imsg *); + +/* inter-process structures */ + +struct bounce_req_msg { + uint64_t evpid; + time_t timestamp; + struct delivery_bounce bounce; +}; + +enum dns_error { + DNS_OK = 0, + DNS_RETRY, + DNS_EINVAL, + DNS_ENONAME, + DNS_ENOTFOUND, +}; + +enum lka_resp_status { + LKA_OK, + LKA_TEMPFAIL, + LKA_PERMFAIL +}; + +enum filter_type { + FILTER_TYPE_BUILTIN, + FILTER_TYPE_PROC, + FILTER_TYPE_CHAIN, +}; + +enum filter_subsystem { + FILTER_SUBSYSTEM_SMTP_IN = 1<<0, + FILTER_SUBSYSTEM_SMTP_OUT = 1<<1, +}; + +struct filter_proc { + const char *command; + const char *user; + const char *group; + const char *chroot; + int errfd; + enum filter_subsystem filter_subsystem; +}; + +struct filter_config { + char *name; + enum filter_subsystem filter_subsystem; + enum filter_type filter_type; + enum filter_phase phase; + char *reject; + char *disconnect; + char *rewrite; + char *report; + uint8_t junk; + uint8_t bypass; + char *proc; + + const char **chain; + size_t chain_size; + struct dict chain_procs; + + int8_t not_fcrdns; + int8_t fcrdns; + + int8_t not_rdns; + int8_t rdns; + + int8_t not_rdns_table; + struct table *rdns_table; + + int8_t not_rdns_regex; + struct table *rdns_regex; + + int8_t not_src_table; + struct table *src_table; + + int8_t not_src_regex; + struct table *src_regex; + + int8_t not_helo_table; + struct table *helo_table; + + int8_t not_helo_regex; + struct table *helo_regex; + + int8_t not_auth; + int8_t auth; + + int8_t not_auth_table; + struct table *auth_table; + + int8_t not_auth_regex; + struct table *auth_regex; + + int8_t not_mail_from_table; + struct table *mail_from_table; + + int8_t not_mail_from_regex; + struct table *mail_from_regex; + + int8_t not_rcpt_to_table; + struct table *rcpt_to_table; + + int8_t not_rcpt_to_regex; + struct table *rcpt_to_regex; + +}; + +enum filter_status { + FILTER_PROCEED, + FILTER_REWRITE, + FILTER_REJECT, + FILTER_DISCONNECT, + FILTER_JUNK, +}; + +enum ca_resp_status { + CA_OK, + CA_FAIL +}; + +enum mda_resp_status { + MDA_OK, + MDA_TEMPFAIL, + MDA_PERMFAIL +}; + +struct msg_walkinfo { + struct event ev; + uint32_t msgid; + uint32_t peerid; + size_t n_evp; + void *data; + int done; +}; + + +enum dispatcher_type { + DISPATCHER_LOCAL, + DISPATCHER_REMOTE, + DISPATCHER_BOUNCE, +}; + +struct dispatcher_local { + uint8_t is_mbox; /* only for MBOX */ + + uint8_t expand_only; + uint8_t forward_only; + + char *mda_wrapper; + char *command; + + char *table_alias; + char *table_virtual; + char *table_userbase; + + char *user; +}; + +struct dispatcher_remote { + char *helo; + char *helo_source; + + char *source; + + char *ca; + char *pki; + + char *mail_from; + + char *smarthost; + int smarthost_domain; + + char *auth; + int tls_required; + int tls_noverify; + + int backup; + char *backupmx; + + char *filtername; + + int srs; +}; + +struct dispatcher_bounce { +}; + +struct dispatcher { + enum dispatcher_type type; + union dispatcher_agent { + struct dispatcher_local local; + struct dispatcher_remote remote; + struct dispatcher_bounce bounce; + } u; + + time_t ttl; +}; + +struct rule { + TAILQ_ENTRY(rule) r_entry; + + uint8_t reject; + + int8_t flag_tag; + int8_t flag_from; + int8_t flag_for; + int8_t flag_from_rdns; + int8_t flag_from_socket; + + int8_t flag_tag_regex; + int8_t flag_from_regex; + int8_t flag_for_regex; + + int8_t flag_smtp_helo; + int8_t flag_smtp_starttls; + int8_t flag_smtp_auth; + int8_t flag_smtp_mail_from; + int8_t flag_smtp_rcpt_to; + + int8_t flag_smtp_helo_regex; + int8_t flag_smtp_starttls_regex; + int8_t flag_smtp_auth_regex; + int8_t flag_smtp_mail_from_regex; + int8_t flag_smtp_rcpt_to_regex; + + + char *table_tag; + char *table_from; + char *table_for; + + char *table_smtp_helo; + char *table_smtp_auth; + char *table_smtp_mail_from; + char *table_smtp_rcpt_to; + + char *dispatcher; +}; + + +/* aliases.c */ +int aliases_get(struct expand *, const char *); +int aliases_virtual_get(struct expand *, const struct mailaddr *); +int alias_parse(struct expandnode *, const char *); + + +/* auth.c */ +struct auth_backend *auth_backend_lookup(enum auth_type); + + +/* bounce.c */ +void bounce_add(uint64_t); +void bounce_fd(int); + + +/* ca.c */ +int ca(void); +int ca_X509_verify(void *, void *, const char *, const char *, const char **); +void ca_imsg(struct mproc *, struct imsg *); +void ca_init(void); +void ca_engine_init(void); + + +/* cert.c */ +int cert_init(const char *, int, + void (*)(void *, int, const char *, const void *, size_t), void *); +int cert_verify(const void *, const char *, int, void (*)(void *, int), void *); +void cert_dispatch_request(struct mproc *, struct imsg *); +void cert_dispatch_result(struct mproc *, struct imsg *); + + +/* compress_backend.c */ +struct compress_backend *compress_backend_lookup(const char *); +size_t compress_chunk(void *, size_t, void *, size_t); +size_t uncompress_chunk(void *, size_t, void *, size_t); +int compress_file(FILE *, FILE *); +int uncompress_file(FILE *, FILE *); + +/* config.c */ +#define PURGE_LISTENERS 0x01 +#define PURGE_TABLES 0x02 +#define PURGE_RULES 0x04 +#define PURGE_PKI 0x08 +#define PURGE_PKI_KEYS 0x10 +#define PURGE_DISPATCHERS 0x20 +#define PURGE_EVERYTHING 0xff +struct smtpd *config_default(void); +void purge_config(uint8_t); +void config_process(enum smtp_proc_type); +void config_peer(enum smtp_proc_type); + + +/* control.c */ +int control(void); +int control_create_socket(void); + + +/* crypto.c */ +int crypto_setup(const char *, size_t); +int crypto_encrypt_file(FILE *, FILE *); +int crypto_decrypt_file(FILE *, FILE *); +size_t crypto_encrypt_buffer(const char *, size_t, char *, size_t); +size_t crypto_decrypt_buffer(const char *, size_t, char *, size_t); + + +/* dns.c */ +void dns_imsg(struct mproc *, struct imsg *); + + +/* enqueue.c */ +int enqueue(int, char **, FILE *); + + +/* envelope.c */ +void envelope_set_errormsg(struct envelope *, char *, ...); +void envelope_set_esc_class(struct envelope *, enum enhanced_status_class); +void envelope_set_esc_code(struct envelope *, enum enhanced_status_code); +int envelope_load_buffer(struct envelope *, const char *, size_t); +int envelope_dump_buffer(const struct envelope *, char *, size_t); + + +/* expand.c */ +int expand_cmp(struct expandnode *, struct expandnode *); +void expand_insert(struct expand *, struct expandnode *); +struct expandnode *expand_lookup(struct expand *, struct expandnode *); +void expand_clear(struct expand *); +void expand_free(struct expand *); +int expand_line(struct expand *, const char *, int); +int expand_to_text(struct expand *, char *, size_t); +RB_PROTOTYPE(expandtree, expandnode, nodes, expand_cmp); + + +/* forward.c */ +int forwards_get(int, struct expand *); + + +/* limit.c */ +void limit_mta_set_defaults(struct mta_limits *); +int limit_mta_set(struct mta_limits *, const char*, int64_t); + + +/* lka.c */ +int lka(void); + + +/* lka_proc.c */ +int lka_proc_ready(void); +void lka_proc_forked(const char *, uint32_t, int); +void lka_proc_errfd(const char *, int); +struct io *lka_proc_get_io(const char *); + + +/* lka_report.c */ +void lka_report_init(void); +void lka_report_register_hook(const char *, const char *); +void lka_report_smtp_link_connect(const char *, struct timeval *, uint64_t, const char *, int, + const struct sockaddr_storage *, const struct sockaddr_storage *); +void lka_report_smtp_link_disconnect(const char *, struct timeval *, uint64_t); +void lka_report_smtp_link_greeting(const char *, uint64_t, struct timeval *, + const char *); +void lka_report_smtp_link_identify(const char *, struct timeval *, uint64_t, const char *, const char *); +void lka_report_smtp_link_tls(const char *, struct timeval *, uint64_t, const char *); +void lka_report_smtp_link_auth(const char *, struct timeval *, uint64_t, const char *, const char *); +void lka_report_smtp_tx_reset(const char *, struct timeval *, uint64_t, uint32_t); +void lka_report_smtp_tx_begin(const char *, struct timeval *, uint64_t, uint32_t); +void lka_report_smtp_tx_mail(const char *, struct timeval *, uint64_t, uint32_t, const char *, int); +void lka_report_smtp_tx_rcpt(const char *, struct timeval *, uint64_t, uint32_t, const char *, int); +void lka_report_smtp_tx_envelope(const char *, struct timeval *, uint64_t, uint32_t, uint64_t); +void lka_report_smtp_tx_commit(const char *, struct timeval *, uint64_t, uint32_t, size_t); +void lka_report_smtp_tx_data(const char *, struct timeval *, uint64_t, uint32_t, int); +void lka_report_smtp_tx_rollback(const char *, struct timeval *, uint64_t, uint32_t); +void lka_report_smtp_protocol_client(const char *, struct timeval *, uint64_t, const char *); +void lka_report_smtp_protocol_server(const char *, struct timeval *, uint64_t, const char *); +void lka_report_smtp_filter_response(const char *, struct timeval *, uint64_t, + int, int, const char *); +void lka_report_smtp_timeout(const char *, struct timeval *, uint64_t); +void lka_report_filter_report(uint64_t, const char *, int, const char *, + struct timeval *, const char *); +void lka_report_proc(const char *, const char *); + + +/* lka_filter.c */ +void lka_filter_init(void); +void lka_filter_register_hook(const char *, const char *); +void lka_filter_ready(void); +int lka_filter_proc_in_session(uint64_t, const char *); +void lka_filter_begin(uint64_t, const char *); +void lka_filter_end(uint64_t); +void lka_filter_protocol(uint64_t, enum filter_phase, const char *); +void lka_filter_data_begin(uint64_t); +void lka_filter_data_end(uint64_t); +int lka_filter_response(uint64_t, const char *, const char *); + + +/* lka_session.c */ +void lka_session(uint64_t, struct envelope *); +void lka_session_forward_reply(struct forward_req *, int); + + +/* log.c */ +void vlog(int, const char *, va_list); +void logit(int, const char *, ...) __attribute__((format (printf, 2, 3))); + + +/* mda.c */ +void mda_postfork(void); +void mda_postprivdrop(void); +void mda_imsg(struct mproc *, struct imsg *); + + +/* mda_mbox.c */ +void mda_mbox_init(struct deliver *); +void mda_mbox(struct deliver *); + + +/* mda_unpriv.c */ +void mda_unpriv(struct dispatcher *, struct deliver *, const char *, const char *); + + +/* mda_variables.c */ +ssize_t mda_expand_format(char *, size_t, const struct deliver *, + const struct userinfo *, const char *); + + +/* makemap.c */ +int makemap(int, int, char **); + + +/* mailaddr.c */ +int mailaddr_line(struct maddrmap *, const char *); +void maddrmap_init(struct maddrmap *); +void maddrmap_insert(struct maddrmap *, struct maddrnode *); +void maddrmap_free(struct maddrmap *); + + +/* mproc.c */ +int mproc_fork(struct mproc *, const char*, char **); +void mproc_init(struct mproc *, int); +void mproc_clear(struct mproc *); +void mproc_enable(struct mproc *); +void mproc_disable(struct mproc *); +void mproc_event_add(struct mproc *); +void m_compose(struct mproc *, uint32_t, uint32_t, pid_t, int, void *, size_t); +void m_composev(struct mproc *, uint32_t, uint32_t, pid_t, int, + const struct iovec *, int); +void m_forward(struct mproc *, struct imsg *); +void m_create(struct mproc *, uint32_t, uint32_t, pid_t, int); +void m_add(struct mproc *, const void *, size_t); +void m_add_int(struct mproc *, int); +void m_add_u32(struct mproc *, uint32_t); +void m_add_size(struct mproc *, size_t); +void m_add_time(struct mproc *, time_t); +void m_add_timeval(struct mproc *, struct timeval *tv); +void m_add_string(struct mproc *, const char *); +void m_add_data(struct mproc *, const void *, size_t); +void m_add_evpid(struct mproc *, uint64_t); +void m_add_msgid(struct mproc *, uint32_t); +void m_add_id(struct mproc *, uint64_t); +void m_add_sockaddr(struct mproc *, const struct sockaddr *); +void m_add_mailaddr(struct mproc *, const struct mailaddr *); +void m_add_envelope(struct mproc *, const struct envelope *); +void m_add_params(struct mproc *, struct dict *); +void m_close(struct mproc *); +void m_flush(struct mproc *); + +void m_msg(struct msg *, struct imsg *); +int m_is_eom(struct msg *); +void m_end(struct msg *); +void m_get_int(struct msg *, int *); +void m_get_size(struct msg *, size_t *); +void m_get_u32(struct msg *, uint32_t *); +void m_get_time(struct msg *, time_t *); +void m_get_timeval(struct msg *, struct timeval *); +void m_get_string(struct msg *, const char **); +void m_get_data(struct msg *, const void **, size_t *); +void m_get_evpid(struct msg *, uint64_t *); +void m_get_msgid(struct msg *, uint32_t *); +void m_get_id(struct msg *, uint64_t *); +void m_get_sockaddr(struct msg *, struct sockaddr *); +void m_get_mailaddr(struct msg *, struct mailaddr *); +void m_get_envelope(struct msg *, struct envelope *); +void m_get_params(struct msg *, struct dict *); +void m_clear_params(struct dict *); + + +/* mta.c */ +void mta_postfork(void); +void mta_postprivdrop(void); +void mta_imsg(struct mproc *, struct imsg *); +void mta_route_ok(struct mta_relay *, struct mta_route *); +void mta_route_error(struct mta_relay *, struct mta_route *); +void mta_route_down(struct mta_relay *, struct mta_route *); +void mta_route_collect(struct mta_relay *, struct mta_route *); +void mta_source_error(struct mta_relay *, struct mta_route *, const char *); +void mta_delivery_log(struct mta_envelope *, const char *, const char *, int, const char *); +void mta_delivery_notify(struct mta_envelope *); +struct mta_task *mta_route_next_task(struct mta_relay *, struct mta_route *); +const char *mta_host_to_text(struct mta_host *); +const char *mta_relay_to_text(struct mta_relay *); + + +/* mta_session.c */ +void mta_session(struct mta_relay *, struct mta_route *, const char *); +void mta_session_imsg(struct mproc *, struct imsg *); + + +/* parse.y */ +int parse_config(struct smtpd *, const char *, int); +int cmdline_symset(char *); + + +/* queue.c */ +int queue(void); + + +/* queue_backend.c */ +uint32_t queue_generate_msgid(void); +uint64_t queue_generate_evpid(uint32_t); +int queue_init(const char *, int); +int queue_close(void); +int queue_message_create(uint32_t *); +int queue_message_delete(uint32_t); +int queue_message_commit(uint32_t); +int queue_message_fd_r(uint32_t); +int queue_message_fd_rw(uint32_t); +int queue_envelope_create(struct envelope *); +int queue_envelope_delete(uint64_t); +int queue_envelope_load(uint64_t, struct envelope *); +int queue_envelope_update(struct envelope *); +int queue_envelope_walk(struct envelope *); +int queue_message_walk(struct envelope *, uint32_t, int *, void **); + + +/* report_smtp.c */ +void report_smtp_link_connect(const char *, uint64_t, const char *, int, + const struct sockaddr_storage *, const struct sockaddr_storage *); +void report_smtp_link_disconnect(const char *, uint64_t); +void report_smtp_link_greeting(const char *, uint64_t, const char *); +void report_smtp_link_identify(const char *, uint64_t, const char *, const char *); +void report_smtp_link_tls(const char *, uint64_t, const char *); +void report_smtp_link_auth(const char *, uint64_t, const char *, const char *); +void report_smtp_tx_reset(const char *, uint64_t, uint32_t); +void report_smtp_tx_begin(const char *, uint64_t, uint32_t); +void report_smtp_tx_mail(const char *, uint64_t, uint32_t, const char *, int); +void report_smtp_tx_rcpt(const char *, uint64_t, uint32_t, const char *, int); +void report_smtp_tx_envelope(const char *, uint64_t, uint32_t, uint64_t); +void report_smtp_tx_data(const char *, uint64_t, uint32_t, int); +void report_smtp_tx_commit(const char *, uint64_t, uint32_t, size_t); +void report_smtp_tx_rollback(const char *, uint64_t, uint32_t); +void report_smtp_protocol_client(const char *, uint64_t, const char *); +void report_smtp_protocol_server(const char *, uint64_t, const char *); +void report_smtp_filter_response(const char *, uint64_t, int, int, const char *); +void report_smtp_timeout(const char *, uint64_t); + + +/* ruleset.c */ +struct rule *ruleset_match(const struct envelope *); + + +/* scheduler.c */ +int scheduler(void); + + +/* scheduler_bakend.c */ +struct scheduler_backend *scheduler_backend_lookup(const char *); +void scheduler_info(struct scheduler_info *, struct envelope *); + + +/* pony.c */ +int pony(void); +void pony_imsg(struct mproc *, struct imsg *); + + +/* resolver.c */ +void resolver_getaddrinfo(const char *, const char *, const struct addrinfo *, + void(*)(void *, int, struct addrinfo*), void *); +void resolver_getnameinfo(const struct sockaddr *, int, + void(*)(void *, int, const char *, const char *), void *); +void resolver_res_query(const char *, int, int, + void (*cb)(void *, int, int, int, const void *, int), void *); +void resolver_dispatch_request(struct mproc *, struct imsg *); +void resolver_dispatch_result(struct mproc *, struct imsg *); + + +/* smtp.c */ +void smtp_postfork(void); +void smtp_postprivdrop(void); +void smtp_imsg(struct mproc *, struct imsg *); +void smtp_configure(void); +void smtp_collect(void); + + +/* smtp_session.c */ +int smtp_session(struct listener *, int, const struct sockaddr_storage *, + const char *, struct io *); +void smtp_session_imsg(struct mproc *, struct imsg *); + + +/* smtpf_session.c */ +int smtpf_session(struct listener *, int, const struct sockaddr_storage *, + const char *); +void smtpf_session_imsg(struct mproc *, struct imsg *); + + +/* smtpd.c */ +void imsg_dispatch(struct mproc *, struct imsg *); +const char *proc_name(enum smtp_proc_type); +const char *proc_title(enum smtp_proc_type); +const char *imsg_to_str(int); +void log_imsg(int, int, struct imsg *); +int fork_proc_backend(const char *, const char *, const char *); + + +/* srs.c */ +const char *srs_encode(const char *, const char *); +const char *srs_decode(const char *); + + +/* ssl_smtpd.c */ +void *ssl_mta_init(void *, char *, off_t, const char *); +void *ssl_smtp_init(void *, int); + + +/* stat_backend.c */ +struct stat_backend *stat_backend_lookup(const char *); +void stat_increment(const char *, size_t); +void stat_decrement(const char *, size_t); +void stat_set(const char *, const struct stat_value *); +struct stat_value *stat_counter(size_t); +struct stat_value *stat_timestamp(time_t); +struct stat_value *stat_timeval(struct timeval *); +struct stat_value *stat_timespec(struct timespec *); + + +/* table.c */ +struct table *table_find(struct smtpd *, const char *); +struct table *table_create(struct smtpd *, const char *, const char *, + const char *); +int table_config(struct table *); +int table_open(struct table *); +int table_update(struct table *); +void table_close(struct table *); +void table_dump(struct table *); +int table_check_use(struct table *, uint32_t, uint32_t); +int table_check_type(struct table *, uint32_t); +int table_check_service(struct table *, uint32_t); +int table_match(struct table *, enum table_service, const char *); +int table_lookup(struct table *, enum table_service, const char *, + union lookup *); +int table_fetch(struct table *, enum table_service, union lookup *); +void table_destroy(struct smtpd *, struct table *); +void table_add(struct table *, const char *, const char *); +int table_domain_match(const char *, const char *); +int table_netaddr_match(const char *, const char *); +int table_mailaddr_match(const char *, const char *); +int table_regex_match(const char *, const char *); +void table_open_all(struct smtpd *); +void table_dump_all(struct smtpd *); +void table_close_all(struct smtpd *); + + +/* to.c */ +int email_to_mailaddr(struct mailaddr *, char *); +int text_to_netaddr(struct netaddr *, const char *); +int text_to_mailaddr(struct mailaddr *, const char *); +int text_to_relayhost(struct relayhost *, const char *); +int text_to_userinfo(struct userinfo *, const char *); +int text_to_credentials(struct credentials *, const char *); +int text_to_expandnode(struct expandnode *, const char *); +uint64_t text_to_evpid(const char *); +uint32_t text_to_msgid(const char *); +const char *sa_to_text(const struct sockaddr *); +const char *ss_to_text(const struct sockaddr_storage *); +const char *time_to_text(time_t); +const char *duration_to_text(time_t); +const char *rule_to_text(struct rule *); +const char *sockaddr_to_text(struct sockaddr *); +const char *mailaddr_to_text(const struct mailaddr *); +const char *expandnode_to_text(struct expandnode *); + + +/* util.c */ +typedef struct arglist arglist; +struct arglist { + char **list; + uint num; + uint nalloc; +}; +void addargs(arglist *, char *, ...) + __attribute__((format(printf, 2, 3))); +int bsnprintf(char *, size_t, const char *, ...) + __attribute__((format (printf, 3, 4))); +int safe_fclose(FILE *); +int hostname_match(const char *, const char *); +int mailaddr_match(const struct mailaddr *, const struct mailaddr *); +int valid_localpart(const char *); +int valid_domainpart(const char *); +int valid_domainname(const char *); +int valid_smtp_response(const char *); +int secure_file(int, char *, char *, uid_t, int); +int lowercase(char *, const char *, size_t); +void xlowercase(char *, const char *, size_t); +int uppercase(char *, const char *, size_t); +uint64_t generate_uid(void); +int availdesc(void); +int ckdir(const char *, mode_t, uid_t, gid_t, int); +int rmtree(char *, int); +int mvpurge(char *, char *); +int mktmpfile(void); +const char *parse_smtp_response(char *, size_t, char **, int *); +int xasprintf(char **, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void *xmalloc(size_t); +void *xcalloc(size_t, size_t); +char *xstrdup(const char *); +void *xmemdup(const void *, size_t); +char *strip(char *); +int io_xprint(struct io *, const char *); +int io_xprintf(struct io *, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void log_envelope(const struct envelope *, const char *, const char *, + const char *); +int session_socket_error(int); +int getmailname(char *, size_t); +int base64_encode(unsigned char const *, size_t, char *, size_t); +int base64_decode(char const *, unsigned char *, size_t); +int base64_encode_rfc3548(unsigned char const *, size_t, + char *, size_t); +void xclosefrom(int); + +void log_trace_verbose(int); +void log_trace(int, const char *, ...) + __attribute__((format (printf, 2, 3))); + +/* waitq.c */ +int waitq_wait(void *, void (*)(void *, void *, void *), void *); +void waitq_run(void *, void *); + + +/* runq.c */ +struct runq; + +int runq_init(struct runq **, void (*)(struct runq *, void *)); +int runq_schedule(struct runq *, time_t, void *); +int runq_schedule_at(struct runq *, time_t, void *); +int runq_cancel(struct runq *, void *); +int runq_pending(struct runq *, void *, time_t *); |