/* * Copyright (c) 2002-2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: error.h,v 1.75 2007/01/11 05:13:48 ca Exp $ */ #ifndef SM_ERROR_H #define SM_ERROR_H 1 #include "sm/generic.h" #include "sm/types.h" #if HAVE_ERRNO_H # include #endif /* need a 32bit signed integer */ typedef int32_t sm_error_T; typedef int32_t sm_ret_T; #define SM_RET_MAX INT32_MAX /* not an error, but a useful return code for some functions */ #define SM_NOMATCH 1 #define SM_NOTDONE 2 /* operation not performed because it wasn't necessary */ /* ** layout: ** bit 31 1 (if error) ** bit 30-24 module (7bit: 0..127) ** bit 23-16 type (8bit: 0..255) ** bit 15- 0 number (similar to errno) (16bit) ** ** less bits for type, more for module? ** ** Note: Berkeley DB uses negative error numbers: -30800 -30999 ** hence we cast the value to int16_t and then to int to preserve the sign. */ #define SM_ERR_HIGH_BIT 0x80000000 #define SM_ERR_MODULE_BITS 0x0000007f #define SM_ERR_TYPE_BITS 0x000000ff #define SM_ERR_VALUE_BITS 0x0000ffff #define SM_ERR_MODULE_OFF 24 #define SM_ERR_TYPE_OFF 16 #define SM_ERR_VALUE_OFF 0 /* if changed: see below! */ #define sm_error_module(err) (((err) >> SM_ERR_MODULE_OFF) & SM_ERR_MODULE_BITS) #define sm_error_type(err) (((err) >> SM_ERR_TYPE_OFF) & SM_ERR_TYPE_BITS) #define sm_error_value(err) ((sm_ret_T)((int16_t)(err))) #define sm_error_gen(mod, type, value) ((sm_ret_T)(SM_ERR_HIGH_BIT |\ ((((mod) & SM_ERR_MODULE_BITS) << SM_ERR_MODULE_OFF) |\ (((type) & SM_ERR_TYPE_BITS) << SM_ERR_TYPE_OFF) |\ ((value) & SM_ERR_VALUE_BITS)))) /* everything is fine... */ /* #define SM_SUCCESS 0 defined in generic.h */ /* error types, notice checks down below: require order */ #define SM_ERR_NONE 0 #define SM_ERR_INFO 1 /* make this "compliant" with EOF? */ #define SM_ERR_WARN 2 #define SM_ERR_TEMP 3 #define SM_ERR_PERM 4 /* more? */ /* ** For example: ** SM_ERR_SOFT_LIMIT ** SM_ERR_HARD_LIMIT ** SM_ERR_CONF_LIMIT ** */ /* No an error iff the high bit is not set */ #define sm_is_success(err) (((err) & SM_ERR_HIGH_BIT) == 0) #define sm_is_err(err) (((err) & SM_ERR_HIGH_BIT) != 0) /* Note: this can also be just a warning or info! */ /* ** XXX This doesn't really work if we want to "merge" error values ** and others, i.e,. if error values must have SM_ERR_HIGH_BIT set. ** Do we want that? ** XXX See above! Requires ordering! Maybe use bitmask? */ /* these checks are not ok unless you already know it's an error */ #define sm_is_temp_err(err) (sm_error_type(err) == SM_ERR_TEMP) #define sm_is_perm_err(err) (sm_error_type(err) == SM_ERR_PERM) #define sm_is_warn_err(err) (sm_error_type(err) == SM_ERR_WARN) #define sm_is_error(err) (sm_error_type(err) > SM_ERR_WARN) #define sm_is_ok(err) (sm_error_type(err) <= SM_ERR_WARN) /* these checks are ok */ #define SM_IS_TEMP_ERR(err) (sm_is_err(err) && sm_error_type(err) == SM_ERR_TEMP) #define SM_IS_PERM_ERR(err) (sm_is_err(err) && sm_error_type(err) == SM_ERR_PERM) #define SM_IS_ERROR(err) (sm_is_err(err) && sm_error_type(err) > SM_ERR_WARN) #define SM_IS_OK(err) (sm_is_success(err) || sm_error_type(err) <= SM_ERR_WARN) #define sm_error_info(mod, value) sm_error_gen(mod, SM_ERR_INFO, (value)) #define sm_error_warn(mod, value) sm_error_gen(mod, SM_ERR_WARN, (value)) #define sm_error_temp(mod, value) sm_error_gen(mod, SM_ERR_TEMP, (value)) #define sm_error_perm(mod, value) sm_error_gen(mod, SM_ERR_PERM, (value)) #define sm_err_info(value) sm_error_gen(0, SM_ERR_INFO, (value)) #define sm_err_warn(value) sm_error_gen(0, SM_ERR_WARN, (value)) #define sm_err_temp(value) sm_error_gen(0, SM_ERR_TEMP, (value)) #define sm_err_perm(value) sm_error_gen(0, SM_ERR_PERM, (value)) /* ** Where to start? This is the same value as in sm8/include/errstring.h ** Make sure these offsets match the error codes used below! ** ** NOTE: if you make additions here, then change also libmta/smerr2txt.c */ #define SM_ERR_BASE 256 #define DNS_ERR_BASE (SM_ERR_BASE + 64) #define R2821_BASE 512 /* sm specific error codes */ #define SM_E_NOMORE (SM_ERR_BASE + 1) /* no "next" entry */ #define SM_E_UNEXPECTED (SM_ERR_BASE + 2) /* unexpected error */ /* ** Input parameter out of range (too large or too small). ** This applies to scalar values that must be within a certain range ** which might be configured at runtime. */ #define SM_E_RANGE (SM_ERR_BASE + 3) /* ** Too big: an input parameter is too large, e.g., a string is too long. ** This applies to non-scalar values (as opposed to SM_E_RANGE) which ** must be within a certain range that is known a-priori. */ #define SM_E_2BIG (SM_ERR_BASE + 4) /* ** Object (e.g., cache, array, hash table) is "full": no entries can be added; */ #define SM_E_FULL (SM_ERR_BASE + 5) /* ** Operation would cause overflow of some variable, e.g., integer overflow. ** This applies to scalar values (SC) */ #define SM_E_OVFLW_SC (SM_ERR_BASE + 6) /* ** Operation would cause overflow of some buffer. ** This applies to non-scalar values (NS) */ #define SM_E_OVFLW_NS (SM_ERR_BASE + 7) #define SM_E_NOTFOUND (SM_ERR_BASE + 8) /* object not found */ /* startup failed (need more detail!) */ #define SM_E_STARTFAIL (SM_ERR_BASE + 9) #define SM_E_SYNTAX (SM_ERR_BASE + 10) #define SM_E_USAGE (SM_ERR_BASE + 11) /* do not start the system; e.g., option like -? has been used */ #define SM_E_DONTSTART (SM_ERR_BASE + 12) /* ** Version (compile/run time) mismatch; this applies to ** libraries as well as data (e.g., persistent databases). */ #define SM_E_VER_MIX (SM_ERR_BASE + 13) #define SM_E_NO_AR (SM_ERR_BASE + 14) /* no AR available */ #define SM_E_NO_DA (SM_ERR_BASE + 15) /* no DA available */ #define SM_E_NO_DA_FREE (SM_ERR_BASE + 16) /* no DA free */ /* protocol version mismatch */ #define SM_E_PR_V_MISM (SM_ERR_BASE + 17) /* protocol error, e.g., unexpected RT or wrong length */ #define SM_E_PR_ERR (SM_ERR_BASE + 18) /* RCB too long or length doesn't match data (protocol error) */ #define SM_E_RCB2LONG (SM_ERR_BASE + 19) /* especially for map lookups */ #define SM_E_TEMPMAP (SM_ERR_BASE + 20) /* temporary map lookup failure */ #define SM_E_PERMMAP (SM_ERR_BASE + 21) /* permanent map lookup failure */ #define SM_E_CLOSEDMAP (SM_ERR_BASE + 22) /* map closed (why?) */ #define SM_E_NOMAP (SM_ERR_BASE + 23) /* map is NULL */ #define SM_E_NOTIMPL (SM_ERR_BASE + 24) /* required function is NULL */ /* others? */ /* MX list is empty after removal of local addresses */ #define SM_E_MXEMPTY (SM_ERR_BASE + 25) /* talking to myself */ #define SM_E_TTMYSELF (SM_ERR_BASE + 26) /* alias expansion in AR failed */ #define SM_E_ALIASEXP (SM_ERR_BASE + 27) /* aliases nested too deep */ #define SM_E_ALIAS_REC (SM_ERR_BASE + 28) /* DNS: answer came from different IP address */ #define SM_E_IP_MISM (SM_ERR_BASE + 29) #define SM_E_NOSIG (SM_ERR_BASE + 30) /* BATV: no signature */ #define SM_E_EXPIRED (SM_ERR_BASE + 31) /* expired */ #define SM_E_RSR_PRB (SM_ERR_BASE + 32) /* resource problem */ #define SM_E_ILL_PIPE (SM_ERR_BASE + 33) /* invalid use of PIPELINING */ #define SM_E_RD (SM_ERR_BASE + 34) /* read error */ #define SM_E_EOF (SM_ERR_BASE + 35) /* read error: EOF */ #define SM_E_WR (SM_ERR_BASE + 36) /* write error */ #define SM_E_BARE_NL (SM_ERR_BASE + 37) /* bare NL '\n' in input */ /* connection to other module has been closed (EOF) */ #define SM_E_CONN_CLSD (SM_ERR_BASE + 38) /* communication context id mismatch (see smtps/s2q.c) */ #define SM_E_WRONG_ID (SM_ERR_BASE + 39) #define SM_SSL_ERROR_SYSCALL (SM_ERR_BASE + 40) #define SM_SSL_ERROR_SSL (SM_ERR_BASE + 41) #define SM_SSL_ERROR_GENERIC (SM_ERR_BASE + 42) #define SM_E_UNAVAIL (SM_ERR_BASE + 43) #define SM_E_LASTCODE SM_E_UNAVAIL /* check for consistency! */ #if DNS_ERR_BASE <= SM_E_LASTCODE ERROR: fix error numbers: _DNS_ERR_BASE <= _SM_E_LASTCODE #endif #define E_CONFBASE (SM_ERR_BASE + 45) /* base for sm-conf errors */ /* check for consistency! */ #if E_CONFBASE <= SM_E_LASTCODE ERROR: fix error numbers: _E_CONFBASE <= _SM_E_LASTCODE #endif /* SM_CONF_ERR values */ #define SM_C_E_NEWLINE_IN_STRING (E_CONFBASE + 1) #define SM_C_E_EOF_IN_STRING (E_CONFBASE + 2) #define SM_C_E_BAD_CHAR (E_CONFBASE + 3) #define SM_C_E_NO_MEMORY (E_CONFBASE + 4) #define SM_C_E_HEX_EXPECTED (E_CONFBASE + 5) #define SM_C_E_CHAR_OVERFLOW (E_CONFBASE + 6) #define SM_C_E_INVALID (E_CONFBASE + 7) #define SM_C_E_READ (E_CONFBASE + 8) #define SM_C_E_READ_OPEN (E_CONFBASE + 9) #define SM_C_E_READ_CLOSE (E_CONFBASE + 10) #define SM_C_E_EOF (E_CONFBASE + 11) #define SM_C_E_SYNTAX (E_CONFBASE + 12) #define SM_C_E_NOT_FOUND (E_CONFBASE + 13) #define SM_C_E_ALREADY (E_CONFBASE + 14) #define SM_C_E_TYPE (E_CONFBASE + 15) #define SM_C_E_NUL_IN_STRING (E_CONFBASE + 16) #define SM_C_E_TOO_MANY (E_CONFBASE + 17) /* check for consistency! use last SM_C_E_code here! */ #if DNS_ERR_BASE <= SM_C_E_TOO_MANY ERROR: fix error numbers: _DNS_ERR_BASE <= _SM_C_E_TOO_MANY #endif #if 0 #define E_LDAPBASE (E_PSEUDOBASE + 70) /* base for LDAP errors */ #endif /* ** Modules ** How fine grained should this be? Just on the library level? ** Down to function level? In that case the module field needs to be larger. ** Should the be somehow related to the logging context/modules? ** For example, the DNS library has its own error codes (see above, starting ** at DNS_ERR_BASE). Having also a DNS error module seems like overkill, but ** the DNS module can also return "generic" errors, e.g., ENOMEM. ** Note: any change here must be reflected in libmta/smerr2txt.c, e_modules */ #define SM_EM_NONE 0 #define SM_EM_AQ 1 #define SM_EM_IQDB 2 #define SM_EM_IBDB 3 #define SM_EM_EDB 4 #define SM_EM_CDB 5 #define SM_EM_DA 6 #define SM_EM_OCC 7 #define SM_EM_DNS 8 #define SM_EM_SMTPC 9 #define SM_EM_SMTPS 10 #define SM_EM_MAPS 11 #define SM_EM_MAP 12 #define SM_EM_BDB 13 /* Berkeley DB related */ /* ** state threads: sm I/O layer (not really returned to application because ** I/O errors are "hidden" and just indicated with a flag in sm I/O) */ #define SM_EM_STTHRIO 14 /* state threads (not yet used) */ #define SM_EM_STTHR 15 #define SM_EM_EVTHR 16 #define SM_EM_RECCOM 17 #define SM_EM_HT 18 /* hash table */ #define SM_EM_RSC 19 /* Restricted Size Cache */ #define SM_EM_STR 20 /* str */ #define SM_EM_RCB 21 /* RCB */ #define SM_EM_TLS 22 /* TLS library */ #define SM_EM_SASL 23 /* SASL library */ #define SM_EM_NET 24 /* network related */ #define SM_EM_IO 25 /* sm I/O related */ #define SM_EM_LOG 26 /* log related */ #define SM_EM_ADDR 27 /* RFC 2821 address parsing */ #define SM_EM_IP 28 /* IP address parsing */ /* inside QMGR */ #define SM_EM_Q_Q2AR 32 /* QMGR -> AR */ #define SM_EM_Q_AR2Q 33 /* AR -> QMGR */ #define SM_EM_Q_Q2SS 34 /* QMGR -> SMTPS */ #define SM_EM_Q_SS2Q 35 /* SMTPS -> QMGR */ #define SM_EM_Q_Q2SC 36 /* QMGR -> SMTPC */ #define SM_EM_Q_SC2Q 37 /* SMTPC -> QMGR */ #define SM_EM_Q_RDIBDB 38 /* read IBDB */ #define SM_EM_Q_IQDB 39 /* IQDB */ #define SM_EM_Q_IBDB 40 /* IBDB */ #define SM_EM_Q_EDBC 41 /* EDB cache */ #define SM_EM_Q_DSN 42 /* bounce handling */ #define SM_EM_Q_START 43 /* QMGR startup */ #define SM_EM_Q_CTL2Q 44 /* CONTROL -> QMGR */ #define SM_EM_Q_CONF 45 /* QMGR configuration */ #define SM_EM_Q_CLEAN 46 /* QMGR cleanup functions */ #define SM_EM_Q_SCHED 47 /* QMGR scheduler */ #define SM_EM_Q 48 /* other QMGR functions */ /* inside SMAR */ #define SM_EM_AR_Q2AR 60 /* QMGR -> AR */ #define SM_EM_AR_AR2Q 61 /* AR -> QMGR */ #define SM_EM_AR_DNSW 62 /* DNS Write */ #define SM_EM_AR_DNSR 63 /* DNS Read */ #define SM_EM_AR_DNSD 63 /* DNS Decode */ #define SM_EM_AR_WAIT 64 /* internal wait for async function */ #define SM_EM_AR 65 /* other AR functions */ #define SM_EM_CONF 66 /* sm-conf */ #define SM_EM_PMILTER 67 /* libpmilter */ #define SM_EM_THR 68 /* threads */ #define SM_EM_BATV 69 /* BATV */ #define SM_EM_UTIL 127 /* utility programs */ /* maximum: 127 */ #if 0 #define SM_EM_x 2 #endif #define SM_CNF_E_NEWLINE_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_NEWLINE_IN_STRING) #define SM_CNF_E_EOF_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_EOF_IN_STRING) #define SM_CNF_E_BAD_CHAR sm_error_perm(SM_EM_CONF, SM_C_E_BAD_CHAR) #define SM_CNF_E_NO_MEMORY sm_error_temp(SM_EM_CONF, SM_C_E_NO_MEMORY) #define SM_CNF_E_HEX_EXPECTED sm_error_perm(SM_EM_CONF, SM_C_E_HEX_EXPECTED) #define SM_CNF_E_CHAR_OVERFLOW sm_error_perm(SM_EM_CONF, SM_C_E_CHAR_OVERFLOW) #define SM_CNF_E_INVALID sm_error_perm(SM_EM_CONF, SM_C_E_INVALID) #define SM_CNF_E_READ sm_error_perm(SM_EM_CONF, SM_C_E_READ) #define SM_CNF_E_READ_OPEN sm_error_perm(SM_EM_CONF, SM_C_E_READ_OPEN) #define SM_CNF_E_READ_CLOSE sm_error_perm(SM_EM_CONF, SM_C_E_READ_CLOSE) #define SM_CNF_E_EOF sm_error_perm(SM_EM_CONF, SM_C_E_EOF) #define SM_CNF_E_SYNTAX sm_error_perm(SM_EM_CONF, SM_C_E_SYNTAX) #define SM_CNF_E_NOT_FOUND sm_error_perm(SM_EM_CONF, SM_C_E_NOT_FOUND) #define SM_CNF_E_ALREADY sm_error_perm(SM_EM_CONF, SM_C_E_ALREADY) #define SM_CNF_E_TYPE sm_error_perm(SM_EM_CONF, SM_C_E_TYPE) #define SM_CNF_E_NUL_IN_STRING sm_error_perm(SM_EM_CONF, SM_C_E_NUL_IN_STRING) #define SM_CNF_E_TOO_MANY sm_error_perm(SM_EM_CONF, SM_C_E_TOO_MANY) #define SM_ETXT_UNKNOWN "Unknown" char *smerr2txt(sm_error_T _err); char *smmod2txt(sm_error_T _err); sm_ret_T errno2err(int _err, int _module); int smerr2txt_r(sm_error_T _err, char *_strerrbuf, size_t _buflen); #if defined(ELAST) # define sm_sys_nerr (ELAST + 1) #elif HAVE_SYS_NERR # define sm_sys_nerr sys_nerr #else # define sm_sys_nerr SM_ERR_BASE #endif #endif /* SM_ERROR_H */