* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Definitions of various structures. In addition, those that are visible for
struct transport_info;
struct router_info;
+/* Growable-string */
+typedef struct gstring {
+ int size; /* Current capacity of string memory */
+ int ptr; /* Offset at which to append further chars */
+ uschar * s; /* The string memory */
+} gstring;
+
/* Structure for remembering macros for the configuration file */
typedef struct macro_item {
- struct macro_item *next;
- BOOL command_line;
- uschar *replacement;
- uschar name[1];
+ struct macro_item * next;
+ BOOL command_line;
+ unsigned namelen;
+ unsigned replen;
+ const uschar * name;
+ const uschar * replacement;
} macro_item;
/* Structure for bit tables for debugging and logging */
BOOL initgroups;
} ugid_block;
+typedef enum { CHUNKING_NOT_OFFERED = -1,
+ CHUNKING_OFFERED,
+ CHUNKING_ACTIVE,
+ CHUNKING_LAST} chunking_state_t;
+
+typedef enum { TFO_NOT_USED = 0,
+ TFO_ATTEMPTED_NODATA,
+ TFO_ATTEMPTED_DATA,
+ TFO_USED_NODATA,
+ TFO_USED_DATA } tfo_state_t;
+
/* Structure for holding information about a host for use mainly by routers,
but also used when checking lists of hosts and when transporting. Looking up
host addresses is done using this structure. */
typedef struct host_item {
struct host_item *next;
- const uschar *name; /* Host name */
- const uschar *address; /* IP address in text form */
- int port; /* port value in host order (if SRV lookup) */
- int mx; /* MX value if found via MX records */
- int sort_key; /* MX*1000 plus random "fraction" */
- int status; /* Usable, unusable, or unknown */
- int why; /* Why host is unusable */
- int last_try; /* Time of last try if known */
+ const uschar *name; /* Host name */
+#ifndef DISABLE_TLS
+ const uschar *certname; /* Name used for certificate checks */
+#endif
+ const uschar *address; /* IP address in text form */
+ int port; /* port value in host order (if SRV lookup) */
+ int mx; /* MX value if found via MX records */
+ int sort_key; /* MX*1000 plus random "fraction" */
+ int status; /* Usable, unusable, or unknown */
+ int why; /* Why host is unusable */
+ int last_try; /* Time of last try if known */
dnssec_status_t dnssec;
} host_item;
uschar *name; /* Instance name */
struct driver_info *info; /* Points to info for this driver */
void *options_block; /* Pointer to private options */
+
uschar *driver_name; /* All start with this generic option */
+ const uschar *srcfile; /* and config source info for errors */
+ int srcline;
} driver_instance;
typedef struct driver_info {
uschar *driver_name; /* Name of driver */
+
optionlist *options; /* Table of private options names */
int *options_count; /* -> Number of entries in table */
void *options_block; /* Points to default private block */
struct transport_info *info; /* Info for this driver */
void *options_block; /* Pointer to private options */
uschar *driver_name; /* Must be first */
+ const uschar *srcfile;
+ int srcline;
+
int (*setup)( /* Setup entry point */
struct transport_instance *,
struct address_item *,
uschar *expand_multi_domain; /* ) */
BOOL multi_domain; /* ) */
BOOL overrides_hosts; /* ) Used only for remote transports */
- int max_addresses; /* ) */
+ uschar *max_addresses; /* ) */
int connection_max_messages;/* ) */
/**************************************/
BOOL deliver_as_creator; /* Used only by pipe at present */
} transport_info;
+/* smtp transport datachunk callback */
+
+#define tc_reap_prev BIT(0) /* Flags: reap previous SMTP cmd responses */
+#define tc_chunk_last BIT(1) /* annotate chunk SMTP cmd as LAST */
+
+struct transport_context;
+typedef int (*tpt_chunk_cmd_cb)(struct transport_context *, unsigned, unsigned);
+
/* Structure for information about a delivery-in-progress */
typedef struct transport_context {
- transport_instance * tblock;
- struct address_item * addr;
- uschar * check_string;
- uschar * escape_string;
- int options; /* topt_* */
+ union { /* discriminated by option topt_output_string */
+ int fd; /* file descriptor to write message to */
+ gstring * msg; /* allocated string with written message */
+ } u;
+ transport_instance * tblock; /* transport */
+ struct address_item * addr;
+ uschar * check_string; /* string replacement */
+ uschar * escape_string;
+ int options; /* output processing topt_* */
+
+ /* items below only used with option topt_use_bdat */
+ tpt_chunk_cmd_cb chunk_cb; /* per-datachunk callback */
+ void * smtp_context;
} transport_ctx;
struct router_info *info;
void *options_block; /* Pointer to private options */
uschar *driver_name; /* Must be first */
+ const uschar *srcfile;
+ int srcline;
uschar *address_data; /* Arbitrary data */
#ifdef EXPERIMENTAL_BRIGHTMAIL
BOOL retry_use_local_part; /* Just what it says */
BOOL same_domain_copy_routing; /* TRUE => copy routing for same domain */
BOOL self_rewrite; /* TRUE to rewrite headers if making local */
+ uschar *set; /* Variable = value to set; list */
BOOL suffix_optional; /* As it says */
BOOL verify_only; /* Skip this router if not verifying */
BOOL verify_recipient; /* Use this router when verifying a recipient*/
struct auth_info *info; /* Pointer to driver info block */
void *options_block; /* Pointer to private options */
uschar *driver_name; /* Must be first */
+ const uschar *srcfile;
+ int srcline;
+
uschar *advertise_condition; /* Are we going to advertise this?*/
uschar *client_condition; /* Should the client try this? */
uschar *public_name; /* Advertised name */
uschar *); /* rest of AUTH command */
int (*clientcode)( /* client function */
struct auth_instance *,
- struct smtp_inblock *, /* socket and input buffer */
- struct smtp_outblock *, /* socket and output buffer */
+ void *, /* smtp conn, with socket, output and input buffers */
int, /* command timeout */
uschar *, /* buffer for reading response */
int); /* sizeof buffer */
- void (*version_report)( /* diagnostic version reporting */
- FILE *); /* I/O stream to print to */
+ gstring * (*version_report)( /* diagnostic version reporting */
+ gstring *); /* string to append to */
+ void (*macros_create)(void); /* feature-macro creation */
} auth_info;
int port;
BOOL v6_include_v4; /* Used in the daemon */
uschar address[46];
+ uschar * log; /* portion of "listening on" log line */
} ip_address_item;
/* Structure for chaining together arbitrary strings. */
typedef struct string_item {
- struct string_item *next;
- uschar *text;
+ struct string_item * next;
+ uschar * text;
} string_item;
/* Information about a soft delivery failure, for use when calculating
uschar *errors_address; /* where to send errors (NULL => sender) */
header_line *extra_headers; /* additional headers */
uschar *remove_headers; /* list of those to remove */
+ void *variables; /* router-vasriables */
- #ifdef EXPERIMENTAL_SRS
- uschar *srs_sender; /* Change return path when delivering */
- #endif
- #ifdef SUPPORT_I18N
+ BOOL ignore_error:1; /* ignore delivery error */
+#ifdef SUPPORT_I18N
BOOL utf8_msg:1; /* requires SMTPUTF8 processing */
BOOL utf8_downcvt:1; /* mandatory downconvert on delivery */
BOOL utf8_downcvt_maybe:1; /* optional downconvert on delivery */
- #endif
-} address_item_propagated;
-
-/* Bits for the flags field below */
-
-#define af_allow_file 0x00000001 /* allow file in generated address */
-#define af_allow_pipe 0x00000002 /* allow pipe in generated address */
-#define af_allow_reply 0x00000004 /* allow autoreply in generated address */
-#define af_dr_retry_exists 0x00000008 /* router retry record exists */
-#define af_expand_pipe 0x00000010 /* expand pipe arguments */
-#define af_file 0x00000020 /* file delivery; always with pfr */
-#define af_gid_set 0x00000040 /* gid field is set */
-#define af_home_expanded 0x00000080 /* home_dir is already expanded */
-#define af_ignore_error 0x00000100 /* ignore delivery error */
-#define af_initgroups 0x00000200 /* use initgroups() for local transporting */
-#define af_local_host_removed 0x00000400 /* local host was backup */
-#define af_lt_retry_exists 0x00000800 /* local transport retry exists */
-#define af_pfr 0x00001000 /* pipe or file or reply delivery */
-#define af_retry_skipped 0x00002000 /* true if retry caused some skipping */
-#define af_retry_timedout 0x00004000 /* true if retry timed out */
-#define af_uid_set 0x00008000 /* uid field is set */
-#define af_hide_child 0x00010000 /* hide child in bounce/defer msgs */
-#define af_sverify_told 0x00020000 /* sender verify failure notified */
-#define af_verify_pmfail 0x00040000 /* verify failure was postmaster callout */
-#define af_verify_nsfail 0x00080000 /* verify failure was null sender callout */
-#define af_homonym 0x00100000 /* an ancestor has same address */
-#define af_verify_routed 0x00200000 /* for cached sender verify: routed OK */
-#define af_verify_callout 0x00400000 /* for cached sender verify: callout was specified */
-#define af_include_affixes 0x00800000 /* delivered with affixes in RCPT */
-#define af_cert_verified 0x01000000 /* delivered with verified TLS cert */
-#define af_pass_message 0x02000000 /* pass message in bounces */
-#define af_bad_reply 0x04000000 /* filter could not generate autoreply */
-#ifndef DISABLE_PRDR
-# define af_prdr_used 0x08000000 /* delivery used SMTP PRDR */
-#endif
-#define af_force_command 0x10000000 /* force_command in pipe transport */
-#ifdef EXPERIMENTAL_DANE
-# define af_dane_verified 0x20000000 /* TLS cert verify done with DANE */
#endif
-#ifdef SUPPORT_I18N
-# define af_utf8_downcvt 0x40000000 /* downconvert was done for delivery */
-#endif
-
-/* These flags must be propagated when a child is created */
+} address_item_propagated;
-#define af_propagate (af_ignore_error)
/* The main address structure. Note that fields that are to be copied to
generated addresses should be put in the address_item_propagated structure (see
uschar *lc_local_part; /* lowercased local part */
uschar *local_part; /* points to cc or lc version */
uschar *prefix; /* stripped prefix of local part */
+ uschar *prefix_v; /* variable part of above */
uschar *suffix; /* stripped suffix of local part */
+ uschar *suffix_v; /* variable part of above */
const uschar *domain; /* working domain (lower cased) */
uschar *address_retry_key; /* retry key including full address */
uschar *self_hostname; /* after self=pass */
uschar *shadow_message; /* info about shadow transporting */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
+ const uschar *tlsver; /* version used for transport */
uschar *cipher; /* Cipher used for transport */
void *ourcert; /* Certificate offered to peer, binary */
void *peercert; /* Certificate from peer, binary */
uid_t uid; /* uid for transporting */
gid_t gid; /* gid for transporting */
- unsigned int flags; /* a row of bits, defined above */
+ /* flags */
+ struct {
+ BOOL af_allow_file:1; /* allow file in generated address */
+ BOOL af_allow_pipe:1; /* allow pipe in generated address */
+ BOOL af_allow_reply:1; /* allow autoreply in generated address */
+ BOOL af_dr_retry_exists:1; /* router retry record exists */
+ BOOL af_expand_pipe:1; /* expand pipe arguments */
+ BOOL af_file:1; /* file delivery; always with pfr */
+ BOOL af_gid_set:1; /* gid field is set */
+ BOOL af_home_expanded:1; /* home_dir is already expanded */
+ BOOL af_initgroups:1; /* use initgroups() for local transporting */
+ BOOL af_local_host_removed:1; /* local host was backup */
+ BOOL af_lt_retry_exists:1; /* local transport retry exists */
+ BOOL af_pfr:1; /* pipe or file or reply delivery */
+ BOOL af_retry_skipped:1; /* true if retry caused some skipping */
+ BOOL af_retry_timedout:1; /* true if retry timed out */
+ BOOL af_uid_set:1; /* uid field is set */
+ BOOL af_hide_child:1; /* hide child in bounce/defer msgs */
+ BOOL af_sverify_told:1; /* sender verify failure notified */
+ BOOL af_verify_pmfail:1; /* verify failure was postmaster callout */
+ BOOL af_verify_nsfail:1; /* verify failure was null sender callout */
+ BOOL af_homonym:1; /* an ancestor has same address */
+ BOOL af_verify_routed:1; /* for cached sender verify: routed OK */
+ BOOL af_verify_callout:1; /* for cached sender verify: callout was specified */
+ BOOL af_include_affixes:1; /* delivered with affixes in RCPT */
+ BOOL af_new_conn:1; /* delivered on an fresh TCP conn */
+ BOOL af_cont_conn:1; /* delivered (with new MAIL cmd) on an existing TCP conn */
+ BOOL af_cert_verified:1; /* delivered with verified TLS cert */
+ BOOL af_pass_message:1; /* pass message in bounces */
+ BOOL af_bad_reply:1; /* filter could not generate autoreply */
+ BOOL af_tcp_fastopen_conn:1; /* delivery connection used TCP Fast Open */
+ BOOL af_tcp_fastopen:1; /* delivery usefully used TCP Fast Open */
+ BOOL af_tcp_fastopen_data:1; /* delivery sent SMTP commands on TCP Fast Open */
+ BOOL af_pipelining:1; /* delivery used (traditional) pipelining */
+#ifndef DISABLE_PIPE_CONNECT
+ BOOL af_early_pipe:1; /* delivery used connect-time pipelining */
+#endif
+#ifndef DISABLE_PRDR
+ BOOL af_prdr_used:1; /* delivery used SMTP PRDR */
+#endif
+ BOOL af_chunking_used:1; /* delivery used SMTP CHUNKING */
+ BOOL af_force_command:1; /* force_command in pipe transport */
+#ifdef SUPPORT_DANE
+ BOOL af_dane_verified:1; /* TLS cert verify done with DANE */
+#endif
+#ifdef SUPPORT_I18N
+ BOOL af_utf8_downcvt:1; /* downconvert was done for delivery */
+#endif
+#ifndef DISABLE_TLS_RESUME
+ BOOL af_tls_resume:1; /* TLS used a resumed session */
+#endif
+ } flags;
+
unsigned int domain_cache[(MAX_NAMED_LIST * 2)/32];
unsigned int localpart_cache[(MAX_NAMED_LIST * 2)/32];
int mode; /* mode for local transporting to a file */
+ int basic_errno; /* status after failure */
int more_errno; /* additional error information */
- /* (may need to hold a timestamp) */
+ struct timeval delivery_time; /* time taken to do delivery/attempt */
- short int basic_errno; /* status after failure */
- short int child_count; /* number of child addresses */
+ unsigned short child_count; /* number of child addresses */
short int return_file; /* fileno of return data file */
short int special_action; /* ( used when when deferred or failed */
/* ( also */
/* Structure for holding time-limited data such as DNS returns.
We use this rather than extending tree_node to avoid wasting
space for most tree use (variables...) at the cost of complexity
-for the lookups cache */
+for the lookups cache.
+We also store any options used for the lookup. */
typedef struct expiring_data {
- time_t expiry; /* if nonzero, data invalid after this time */
- void *ptr; /* pointer to data */
+ time_t expiry; /* if nonzero, data invalid after this time */
+ const uschar * opts; /* options, or NULL */
+ union
+ {
+ void * ptr; /* pointer to data */
+ int val; /* or integer data */
+ } data;
} expiring_data;
/* Structure for holding the handle and the cached last lookup for searches.
uncompressed, but the data pointer is into the raw data. */
typedef struct {
- uschar name[DNS_MAXNAME]; /* domain name */
- int type; /* record type */
- unsigned short ttl; /* time-to-live, seconds */
- int size; /* size of data */
- uschar *data; /* pointer to data */
+ uschar name[DNS_MAXNAME]; /* domain name */
+ int type; /* record type */
+ unsigned short ttl; /* time-to-live, seconds */
+ int size; /* size of data */
+ const uschar *data; /* pointer to data */
} dns_record;
-/* Structure for holding the result of a DNS query. */
+/* Structure for holding the result of a DNS query. A touch over
+64k big, so take care to release as soon as possible. */
typedef struct {
int answerlen; /* length of the answer */
- uschar answer[MAXPACKET]; /* the answer itself */
+ uschar answer[NS_MAXMSG]; /* the answer itself */
} dns_answer;
/* Structure for holding the intermediate data while scanning a DNS answer
block. */
typedef struct {
- int rrcount; /* count of RRs in the answer */
- uschar *aptr; /* pointer in the answer while scanning */
- dns_record srr; /* data from current record in scan */
+ int rrcount; /* count of RRs in the answer */
+ const uschar *aptr; /* pointer in the answer while scanning */
+ dns_record srr; /* data from current record in scan */
} dns_scan;
/* Structure for holding a chain of IP addresses that are extracted from
typedef struct sha1 {
unsigned int H[5];
unsigned int length;
- }
-sha1;
+} sha1;
+
+/* Information for making an smtp connection */
+typedef struct {
+ transport_instance * tblock;
+ void * ob; /* smtp_transport_options_block * */
+ host_item * host;
+ int host_af;
+ uschar * interface;
+
+ int sock; /* used for a bound but not connected socket */
+ uschar * sending_ip_address; /* used for TLS resumption */
+ const uschar * host_lbserver; /* ditto, for server-behind LB */
+ BOOL have_lbserver:1; /* host_lbserver is valid */
+
+#ifdef SUPPORT_DANE
+ BOOL dane:1; /* connection must do dane */
+ dns_answer tlsa_dnsa; /* strictly, this should use tainted mem */
+#endif
+} smtp_connect_args;
+
+/* A client-initiated connection. If TLS, the second element is non-NULL */
+typedef struct {
+ int sock;
+ void * tls_ctx;
+} client_conn_ctx;
+
/* Structure used to hold incoming packets of SMTP responses for a specific
socket. The packets which may contain multiple lines (and in some cases,
multiple responses). */
typedef struct smtp_inblock {
- int sock; /* the socket */
+ client_conn_ctx * cctx; /* the connection */
int buffersize; /* the size of the buffer */
uschar *ptr; /* current position in the buffer */
uschar *ptrend; /* end of data in the buffer */
is in use. */
typedef struct smtp_outblock {
- int sock; /* the socket */
+ client_conn_ctx * cctx; /* the connection */
int cmd_count; /* count of buffered commands */
int buffersize; /* the size of the buffer */
BOOL authenticating; /* TRUE when authenticating */
uschar *ptr; /* current position in the buffer */
uschar *buffer; /* the buffer itself */
+
+ smtp_connect_args * conn_args; /* to make connection, if not yet made */
} smtp_outblock;
/* Structure to hold information about the source of redirection information */
const uschar *host_name;
const uschar *host_address;
const uschar *host_ipv4;
- BOOL negative;
+ mcs_flags flags;
} check_host_block;
/* Structure for remembering lookup data when caching the result of
/* Structure for holding data for an entry in a named list */
typedef struct namedlist_block {
- const uschar *string; /* the list string */
- namedlist_cacheblock *cache_data; /* cached domain_data or localpart_data */
- int number; /* the number of the list for caching */
+ const uschar *string; /* the list string */
+ namedlist_cacheblock *cache_data; /* cached domain_data or localpart_data */
+ short number; /* the number of the list for caching */
+ BOOL hide; /* -bP does not display value */
} namedlist_block;
/* Structures for Access Control Lists */
typedef struct acl_condition_block {
- struct acl_condition_block *next;
- uschar *arg;
- int type;
+ struct acl_condition_block * next;
+ uschar * arg;
+ int type;
union {
- BOOL negated;
- uschar *varname;
+ BOOL negated;
+ uschar * varname;
} u;
} acl_condition_block;
typedef struct acl_block {
- struct acl_block *next;
- acl_condition_block *condition;
- int verb;
+ struct acl_block * next;
+ acl_condition_block * condition;
+ int verb;
+ int srcline;
+ const uschar * srcfile;
} acl_block;
/* smtp transport calc outbound_ip */
/* DKIM information for transport */
struct ob_dkim {
uschar *dkim_domain;
+ uschar *dkim_identity;
uschar *dkim_private_key;
uschar *dkim_selector;
uschar *dkim_canon;
uschar *dkim_sign_headers;
uschar *dkim_strict;
-} dkim;
+ uschar *dkim_hash;
+ uschar *dkim_timestamps;
+ BOOL dot_stuffed;
+ BOOL force_bodyhash;
+#ifdef EXPERIMENTAL_ARC
+ uschar *arc_signspec;
+#endif
+};
+
+
+/* per-queue-runner info */
+typedef struct qrunner {
+ struct qrunner * next; /* list sorted by next tick */
+
+ uschar * name; /* NULL for the default queue */
+ unsigned interval; /* tick rate, seconds */
+ time_t next_tick; /* next run should, or should have, start(ed) */
+ unsigned run_max; /* concurrent queue runner limit */
+ unsigned run_count; /* current runners */
+
+ BOOL queue_run_force :1;
+ BOOL deliver_force_thaw :1;
+ BOOL queue_run_first_delivery :1;
+ BOOL queue_run_local :1;
+ BOOL queue_2stage :1;
+} qrunner;
/* End of structs.h */