-/* $Cambridge: exim/src/src/exim.h,v 1.13 2005/05/10 22:39:20 tom Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) The Exim Maintainers 2021 - 2022 */
+/* 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 */
/* Source files for exim all #include this header, which drags in everything
messy to have each one importing its own list, and anyway, most of them need
most of these includes. */
+#ifndef EXIM_H
+#define EXIM_H
+
/* Assume most systems have statfs() unless os.h undefines this macro */
#define HAVE_STATFS
+/* Similarly, assume most systems have srandom() unless os.h undefines it.
+This call dates back at least as far as SUSv2. */
+
+#define HAVE_SRANDOM
+
+/* This is primarily for the Gnu C library; we define it before os.h so that
+os.h has a chance to hurriedly undef it, Just In Case. We need C99 for some
+64-bit math support, and defining _ISOC99_SOURCE breaks <resolv.h> and friends.
+*/
+
+#define _GNU_SOURCE 1
+
/* First of all include the os-specific header, which might set things that
are needed by any of the other headers, including system headers. */
/* If it didn't define os_find_running_interfaces, use the common function. */
#ifndef os_find_running_interfaces
-#define os_find_running_interfaces os_common_find_running_interfaces
+# define os_find_running_interfaces os_common_find_running_interfaces
#endif
/* If it didn't define the base for "base 62" numbers, we really do use 62.
making unique names. */
#ifndef BASE_62
-#define BASE_62 62
+# define BASE_62 62
#endif
/* The maximum value of localhost_number depends on the base being used */
#if BASE_62 == 62
-#define LOCALHOST_MAX 16
+# define LOCALHOST_MAX 16
#else
-#define LOCALHOST_MAX 10
+# define LOCALHOST_MAX 10
+#endif
+
+/* If not overridden by os.h, dynamic libraries have filenames ending .so */
+#ifndef DYNLIB_FN_EXT
+# define DYNLIB_FN_EXT "so"
#endif
/* ANSI C standard includes */
#include <ctype.h>
#include <locale.h>
+#include <math.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <errno.h>
#if defined(__svr4__) && defined(__sparc) && ! defined(__EXTENSIONS__)
-#define __EXTENSIONS__ /* so that SunOS 5 gets NGROUPS_MAX */
-#include <limits.h>
-#undef __EXTENSIONS__
+# define __EXTENSIONS__ /* so that SunOS 5 gets NGROUPS_MAX */
+# include <limits.h>
+# undef __EXTENSIONS__
#else
-#include <limits.h>
+# include <limits.h>
+#endif
+
+#ifdef EXIM_HAVE_INOTIFY
+# include <sys/inotify.h>
+#endif
+#ifdef EXIM_HAVE_KEVENT
+# include <sys/event.h>
#endif
+/* C99 integer types, figure out how to undo this if needed for older systems */
+
+#include <inttypes.h>
+
/* Just in case some aged system doesn't define them... */
#ifndef INT_MAX
-#define INT_MAX 2147483647
+# define INT_MAX 2147483647
+#endif
+
+#ifndef INT_MIN
+# define INT_MIN (-INT_MAX - 1)
+#endif
+
+#ifndef SHRT_MAX
+# define SHRT_MAX 32767
#endif
#ifndef UCHAR_MAX
-#define UCHAR_MAX 255
+# define UCHAR_MAX 255
#endif
-/* Some systems have PATH_MAX and some have MAX_PATH_LEN. */
-#ifndef PATH_MAX
-#ifdef MAX_PATH_LEN
-#define PATH_MAX MAX_PATH_LEN
-#else
-#define PATH_MAX 1024
+/* To match int_eximarith_t. Define in OS/os.h-<your-system> to override. */
+#ifndef EXIM_ARITH_MAX
+# define EXIM_ARITH_MAX ((int_eximarith_t)9223372036854775807LL)
#endif
+#ifndef EXIM_ARITH_MIN
+# define EXIM_ARITH_MIN (-EXIM_ARITH_MAX - 1)
#endif
+/* Some systems have PATH_MAX and some have MAX_PATH_LEN. */
+
+#ifndef PATH_MAX
+# ifdef MAX_PATH_LEN
+# define PATH_MAX MAX_PATH_LEN
+# else
+# define PATH_MAX 1024
+# endif
+#endif
+
+/* RFC 5321 specifies that the maximum length of a local-part is 64 octets
+and the maximum length of a domain is 255 octets, but then also defines
+the maximum length of a forward/reverse path as 256 not 64+1+255.
+For an IP address, the maximum is 45 without a scope and we don't work
+with scoped addresses, so go with that. (IPv6 with mapped IPv4).
+
+A hostname maximum length is in practice the same as the domainname, for
+the same core reasons (maximum length of a DNS name), but the semantics
+are different and seeing "DOMAIN" in source is confusing when talking about
+hostnames; so we define a second macro. We'll use RFC 2181 as the reference
+for this one.
+
+There is no known (to me) specification on the maximum length of a human name
+in email addresses and we should be careful about imposing such a limit on
+received email, but in terms of limiting what untrusted callers specify, or
+local generation, having a limit makes sense. Err on the side of generosity.
+
+For a display mail address, we have a human name, an email in brackets,
+possibly some (Comments), so it needs to be at least 512+3 and some more to
+avoid extraneous errors.
+Since the sane SMTP line length limit is 998, constraining such parameters to
+be 1024 seems generous and unlikely to spuriously reject legitimate
+invocations.
+
+The driver name is a name of a router/transport/authenticator etc in the
+configuration file. We also use this for some other short strings, such
+as queue names.
+Also TLS ciphersuite name (no real known limit since the protocols use
+integers, but max seen in reality is 45 octets).
+
+RFC 1413 gives us the 512 limit on IDENT protocol userids.
+*/
+
+#define EXIM_EMAILADDR_MAX 256
+#define EXIM_LOCALPART_MAX 64
+#define EXIM_DOMAINNAME_MAX 255
+#define EXIM_IPADDR_MAX 45
+#define EXIM_HOSTNAME_MAX 255
+#define EXIM_HUMANNAME_MAX 256
+#define EXIM_DISPLAYMAIL_MAX 1024
+#define EXIM_DRIVERNAME_MAX 64
+#define EXIM_CIPHERNAME_MAX 64
+#define EXIM_IDENTUSER_MAX 512
+
+
#include <sys/types.h>
#include <sys/file.h>
#include <dirent.h>
#include <netdb.h>
#ifndef NO_POLL_H
-#include <poll.h>
+# include <poll.h>
#endif
#include <pwd.h>
#include <grp.h>
in sys/file.h. */
#ifndef LOCK_SH
-#define NO_FLOCK
+# define NO_FLOCK
#endif
#ifndef NO_SYSEXITS /* some OS don't have this */
-#include <sysexits.h>
+# include <sysexits.h>
#endif
/* A few OS don't have socklen_t; their os.h files define EXIM_SOCKLEN_T to
that this is used by the AIX include files. */
#ifndef EXIM_SOCKLEN_T
-#define EXIM_SOCKLEN_T socklen_t
+# define EXIM_SOCKLEN_T socklen_t
#endif
/* Ensure that the sysexits we reference are defined */
#ifndef EX_UNAVAILABLE
-#define EX_UNAVAILABLE 69 /* service unavailable; used for execv fail */
+# define EX_UNAVAILABLE 69 /* service unavailable; used for execv fail */
#endif
#ifndef EX_CANTCREAT
-#define EX_CANTCREAT 73 /* can't create file: treat as temporary */
+# define EX_CANTCREAT 73 /* can't create file: treat as temporary */
#endif
#ifndef EX_TEMPFAIL
-#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#endif
#ifndef EX_CONFIG
-#define EX_CONFIG 78 /* configuration error */
+# define EX_CONFIG 78 /* configuration error */
#endif
/* This one is not in any sysexits file that I've come across */
#include <sys/param.h>
#ifndef NO_SYS_RESOURCE_H /* QNX doesn't have this */
-#include <sys/resource.h>
+# include <sys/resource.h>
#endif
#include <sys/socket.h>
the code is run. It saves some #ifdef occurrences. */
#ifndef AF_INET6
-#define AF_INET6 24
+# define AF_INET6 24
#endif
#include <sys/ioctl.h>
f_free. */
#ifndef F_BAVAIL
- #define F_BAVAIL f_bavail
+ # define F_BAVAIL f_bavail
#endif
#ifndef F_FAVAIL
- #define F_FAVAIL f_ffree
+ # define F_FAVAIL f_ffree
#endif
/* All the systems I've been able to look at seem to have F_FILES */
#ifndef F_FILES
- #define F_FILES f_files
+ # define F_FILES f_files
#endif
#endif
#ifndef SIOCGIFCONF /* HACK for SunOS 5 */
-#include <sys/sockio.h>
+# include <sys/sockio.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
/* There's a shambles in IRIX6 - it defines EX_OK in unistd.h which conflicts
-with the definition in sysexits.h. Arrange to preserve it, even though at
-present Exim doesn't actually use it. */
+with the definition in sysexits.h. Exim does not actually use this macro, so we
+just undefine it. It would be nice to be able to re-instate the definition from
+sysexits.h if there is no definition in unistd.h, but I do not think there is a
+way to do this in C because macro definitions are not scanned for other macros
+at definition time. [The code here used to assume they were, until I was
+disabused of the notion. Luckily, since EX_OK is not used, it didn't matter.] */
#ifdef EX_OK
-#define SAVE_EX_OK EX_OK
-#undef EX_OK
+# undef EX_OK
#endif
#include <unistd.h>
-#ifdef SAVE_EX_OK
-#ifdef EX_OK
-#undef EX_OK
-#endif
-#define EX_OK SAVE_EX_OK
-#endif
-
#include <utime.h>
#ifndef NO_NET_IF_H
-#include <net/if.h>
+# include <net/if.h>
#endif
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
-/* If arpa/nameser.h defines a maximum name server packet size, use it,
-provided it is greater than 2048. Otherwise go for a default. PACKETSZ was used
-for this, but it seems that NS_PACKETSZ is coming into use. */
-
-#if defined(NS_PACKETSZ) && NS_PACKETSZ >= 2048
- #define MAXPACKET NS_PACKETSZ
-#elif defined(PACKETSZ) && PACKETSZ >= 2048
- #define MAXPACKET PACKETSZ
-#else
- #define MAXPACKET 2048
-#endif
-
/* While IPv6 is still young the definitions of T_AAAA and T_A6 may not be
included in arpa/nameser.h. Fudge them here. */
header files. I don't suppose they have T_SRV either. */
#ifndef T_TXT
-#define T_TXT 16
+# define T_TXT 16
#endif
#ifndef T_SRV
-#define T_SRV 33
+# define T_SRV 33
#endif
+/* Many systems do not have T_SPF. */
+
+#ifndef T_SPF
+# define T_SPF 99
+#endif
+
+/* New TLSA record for DANE */
+#ifndef T_TLSA
+# define T_TLSA 52
+#endif
+#define MAX_TLSA_EXPANDED_SIZE 8192
+
+/* It seems that some versions of arpa/nameser.h don't define *any* of the
+T_xxx macros, which seem to be non-standard nowadays. Just to be on the safe
+side, put in definitions for all the ones that Exim uses. */
+
+#ifndef T_A
+# define T_A 1
+#endif
+
+#ifndef T_CNAME
+# define T_CNAME 5
+#endif
+
+#ifndef T_SOA
+# define T_SOA 6
+#endif
+
+#ifndef T_MX
+# define T_MX 15
+#endif
+
+#ifndef T_NS
+# define T_NS 2
+#endif
+
+#ifndef T_PTR
+# define T_PTR 12
+#endif
+
+
/* We define a few private types for special DNS lookups:
. T_ZNS gets the nameservers of the enclosing zone of a domain
. T_CSA gets the domain's Client SMTP Authorization SRV record
+ . T_ADDRESSES looks up both AAAA (or A6) and A records
+
+If any of these names appear in the RRtype list at:
+ <http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml>
+then we should rename Exim's private type away from the conflict.
*/
#define T_ZNS (-1)
#define T_MXH (-2)
#define T_CSA (-3)
+#define T_ADDRESSES (-4)
/* The resolv.h header defines __P(x) on some Solaris 2.5.1 systems (without
checking that it is already defined, in fact). This conflicts with other
to undefine it if resolv.h defines it. */
#if defined(__P)
-#define __P_WAS_DEFINED_BEFORE_RESOLV
+# define __P_WAS_DEFINED_BEFORE_RESOLV
#endif
#include <resolv.h>
#if defined(__P) && ! defined (__P_WAS_DEFINED_BEFORE_RESOLV)
-#undef __P
+# undef __P
+#endif
+
+/* If not defined by os.h, we do nothing special to push DNS resolver state
+back to be available by the classic resolver routines. Also, provide
+prototype for our get routine, unless defined away. */
+
+#ifndef os_put_dns_resolver_res
+# define os_put_dns_resolver_res(R) do {/**/} while(0)
+#endif
+#ifndef os_get_dns_resolver_res
+res_state os_get_dns_resolver_res(void);
#endif
/* These three are to support the IP option logging code. Linux is
#include <netinet/ip.h>
#ifndef NO_IP_VAR_H
-#include <netinet/ip_var.h>
+# include <netinet/ip_var.h>
#endif
/* Linux (and some others) uses a different type for the 2nd argument of
here. */
#ifndef ICONV_ARG2_TYPE
-#define ICONV_ARG2_TYPE const char **
+# define ICONV_ARG2_TYPE char **
#endif
/* One OS uses a different type for the 5th argument of getsockopt */
#ifndef GETSOCKOPT_ARG5_TYPE
-#define GETSOCKOPT_ARG5_TYPE socklen_t *
+# define GETSOCKOPT_ARG5_TYPE socklen_t *
#endif
/* One operating system uses a different type for the 2nd argument of select().
Its os.h file defines SELECT_ARG2_TYPE. For the rest, define a default here. */
#ifndef SELECT_ARG2_TYPE
-#define SELECT_ARG2_TYPE fd_set
+# define SELECT_ARG2_TYPE fd_set
#endif
/* One operating system uses a different type for the 4th argument of
default here. */
#ifndef DN_EXPAND_ARG4_TYPE
-#define DN_EXPAND_ARG4_TYPE char *
+# define DN_EXPAND_ARG4_TYPE char *
#endif
/* One operating system defines a different type for the yield of inet_addr().
use different values for specific OS if ever necessary. */
#ifndef S_ADDR_TYPE
-#define S_ADDR_TYPE u_long
+# define S_ADDR_TYPE u_long
#endif
/* (At least) one operating system (Solaris) defines a different type for the
here. */
#ifndef PAM_CONVERSE_ARG2_TYPE
-#define PAM_CONVERSE_ARG2_TYPE const struct pam_message
+# define PAM_CONVERSE_ARG2_TYPE const struct pam_message
#endif
/* One operating system (SunOS4) defines getc, ungetc, feof, and ferror as
flag gets set to cause this to be sorted out here. */
#ifdef FUDGE_GETC_AND_FRIENDS
-#undef getc
+# undef getc
extern int getc(FILE *);
-#undef ungetc
+# undef ungetc
extern int ungetc(int, FILE *);
-#undef feof
+# undef feof
extern int feof(FILE *);
-#undef ferror
+# undef ferror
extern int ferror(FILE *);
#endif
/* The header from the PCRE regex package */
-#include "pcre/pcre.h"
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
/* Exim includes are in several files. Note that local_scan.h #includes
-mytypes.h and store.h, so we don't need to mention them explicitly. */
-
-#include "config.h"
+config.h, mytypes.h, and store.h, so we don't need to mention them explicitly.
+*/
#include "local_scan.h"
#include "macros.h"
-#include "dbstuff.h"
+#include "hintsdb.h"
+#include "hintsdb_structs.h"
#include "structs.h"
+#include "blob.h"
+#include "hash.h"
#include "globals.h"
#include "functions.h"
#include "dbfunctions.h"
#include "osfunctions.h"
#ifdef EXPERIMENTAL_BRIGHTMAIL
-#include "bmi_spam.h"
+# include "bmi_spam.h"
#endif
-#ifdef EXPERIMENTAL_SPF
-#include "spf.h"
+#ifdef SUPPORT_SPF
+# include "spf.h"
#endif
-#ifdef EXPERIMENTAL_SRS
-#include "srs.h"
+#ifndef DISABLE_DKIM
+# include "dkim.h"
#endif
-#ifdef EXPERIMENTAL_DOMAINKEYS
-#include "dk.h"
+#ifdef SUPPORT_DMARC
+# include "dmarc.h"
+# include <opendmarc/dmarc.h>
#endif
/* The following stuff must follow the inclusion of config.h because it
requires various things that are set therein. */
#if HAVE_ICONV /* Not all OS have this */
-#include <iconv.h>
+# include <iconv.h>
#endif
-#if defined(USE_READLINE) || defined(EXPAND_DLFUNC)
-#include <dlfcn.h>
+#if defined(USE_READLINE) || defined(EXPAND_DLFUNC) || defined (LOOKUP_MODULE_DIR)
+# include <dlfcn.h>
+#endif
+
+#ifdef ENABLE_DISABLE_FSYNC
+# define EXIMfsync(f) (disable_fsync? 0 : fsync(f))
+#else
+# define EXIMfsync(f) fsync(f)
#endif
/* Backward compatibility; LOOKUP_LSEARCH now includes all three */
#if (!defined LOOKUP_LSEARCH) && (defined LOOKUP_WILDLSEARCH || defined LOOKUP_NWILDLSEARCH)
-#define LOOKUP_LSEARCH yes
+# define LOOKUP_LSEARCH yes
#endif
/* Define a union to hold either an IPv4 or an IPv6 sockaddr structure; this
-simplifies some of the coding. */
+simplifies some of the coding. We include the sockaddr to reduce type-punning
+issues in C99. */
union sockaddr_46 {
struct sockaddr_in v4;
#if HAVE_IPV6
struct sockaddr_in6 v6;
#endif
+ struct sockaddr v0;
};
-/* If SUPPORT_TLS is not defined, ensure that USE_GNUTLS is also not defined
-so that if USE_GNUTLS *is* set, we can assume SUPPORT_TLS is also set. */
+/* If DISABLE_TLS is defined, ensure that USE_GNUTLS is not defined
+so that if USE_GNUTLS *is* set, we can assume DISABLE_TLS is not set.
+Ditto USE_OPENSSL.
+Likewise, OSCP, AUTH_TLS and CERTNAMES cannot be supported. */
-#ifndef SUPPORT_TLS
-#undef USE_GNUTLS
+#ifdef DISABLE_TLS
+# undef USE_OPENSSL
+# undef USE_GNUTLS
+# ifndef DISABLE_OCSP
+# define DISABLE_OCSP
+# endif
+# undef EXPERIMENTAL_CERTNAMES
+# undef AUTH_TLS
#endif
/* If SPOOL_DIRECTORY, LOG_FILE_PATH or PID_FILE_PATH have not been defined,
default to EDQUOT if it exists, otherwise ENOSPC. */
#ifndef ERRNO_QUOTA
-#ifdef EDQUOT
-#define ERRNO_QUOTA EDQUOT
-#else
-#define ERRNO_QUOTA ENOSPC
+# ifdef EDQUOT
+# define ERRNO_QUOTA EDQUOT
+# else
+# define ERRNO_QUOTA ENOSPC
+# endif
#endif
+
+/* DANE w/o DNSSEC is useless */
+#if defined(SUPPORT_DANE) && defined(DISABLE_DNSSEC)
+# error DANE support requires DNSSEC support
#endif
-/* Ensure PATH_MAX is defined */
+/* Some platforms (FreeBSD, OpenBSD, Solaris) do not seem to define this */
-#ifndef PATH_MAX
- #ifdef MAXPATHLEN
- #define PATH_MAX MAXPATHLEN
- #else
- #define PATH_MAX 1024
- #endif
+#ifndef POLLRDHUP
+# define POLLRDHUP (POLLIN | POLLHUP)
#endif
+/* Some platforms (Darwin) have to define a larger limit on groups membership */
+#ifndef EXIM_GROUPLIST_SIZE
+# define EXIM_GROUPLIST_SIZE NGROUPS_MAX
+#endif
+
+/* Linux has TCP_CORK, FreeBSD has TCP_NOPUSH; they do pretty much the same */
+
+#ifdef TCP_CORK
+# define EXIM_TCP_CORK TCP_CORK
+#elif defined(TCP_NOPUSH)
+# define EXIM_TCP_CORK TCP_NOPUSH
+#endif
+
+/* LibreSSL seems to not push out the SMTP response to QUIT with our usual
+handling which is trying to get the client to FIN first so that the server does
+not get the TIME_WAIT */
+
+#if !defined(DISABLE_TLS) && defined(USE_OPENSSL) && defined(LIBRESSL_VERSION_NUMBER)
+# define SERVERSIDE_CLOSE_NOWAIT
+#endif
+
+#endif
/* End of exim.h */