/* * Copyright (c) 2004-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. * */ #include "sm/generic.h" SM_RCSID("@(#)$Id: smerr2txt.c,v 1.26 2007/11/05 05:47:50 ca Exp $") #include "sm/error.h" #include "sm/dns.h" #include "sm/bdb.h" #include "sm/rfc2821.h" #define SMERR2TXT 1 #include "smerr2txt.h" #if 0 /* convert define line to struct entry: :'a,.s/^#define \(SM[^ ]*\).*/ { \1, "\1" },/ */ #endif /* 0 */ static e2s_T e_modules[] = { { SM_EM_NONE, "none" }, { SM_EM_AQ, "AQ" }, { SM_EM_IQDB, "IQDB" }, { SM_EM_IBDB, "IBDB" }, { SM_EM_EDB, "EDB" }, { SM_EM_CDB, "CDB" }, { SM_EM_DA, "delivery agent" }, { SM_EM_OCC, "open connection cache" }, { SM_EM_DNS, "DNS" }, { SM_EM_SMTPC, "SMTPC" }, { SM_EM_SMTPS, "SMTPS" }, { SM_EM_MAPS, "MAPS" }, { SM_EM_MAP, "MAP" }, { SM_EM_BDB, "BDB" }, { SM_EM_STTHRIO, "STTHRIO" }, { SM_EM_STTHR, "STTHR" }, { SM_EM_EVTHR, "EVTHR" }, { SM_EM_RECCOM, "RECCOM" }, { SM_EM_HT, "hash table" }, { SM_EM_RSC, "restricted size cache" }, { SM_EM_STR, "str" }, { SM_EM_RCB, "RCB" }, { SM_EM_TLS, "TLS" }, { SM_EM_SASL, "SASL" }, { SM_EM_NET, "NET" }, { SM_EM_IO, "IO" }, { SM_EM_LOG, "logging" }, { SM_EM_ADDR, "RFC 2821 address parsing" }, { SM_EM_IP, "IP address parsing" }, { SM_EM_Q_Q2AR, "QMGR: QMGR to SMAR" }, { SM_EM_Q_AR2Q, "QMGR: SMAR to QMGR" }, { SM_EM_Q_Q2SS, "QMGR: QMGR to SMTPS" }, { SM_EM_Q_SS2Q, "QMGR: SMTPS to QMGR" }, { SM_EM_Q_Q2SC, "QMGR: QMGR to SMTPC" }, { SM_EM_Q_SC2Q, "QMGR: SMTPC to QMGR" }, { SM_EM_Q_RDIBDB, "QMGR: read IBDB" }, { SM_EM_Q_IQDB, "QMGR: IQDB" }, { SM_EM_Q_IBDB, "QMGR: IBDB" }, { SM_EM_Q_EDBC, "QMGR: EDBC" }, { SM_EM_Q_DSN, "QMGR: DSN" }, { SM_EM_Q_START, "QMGR: startup" }, { SM_EM_Q_CTL2Q, "QMGR: control" }, { SM_EM_Q_CONF, "QMGR: configuration" }, { SM_EM_Q_CLEAN, "QMGR: cleanup" }, { SM_EM_Q_SCHED, "QMGR: scheduler" }, { SM_EM_Q, "QMGR: misc" }, { SM_EM_AR_Q2AR, "SMAR: QMGR to SMAR" }, { SM_EM_AR_AR2Q, "SMAR: SMAR to QMGR" }, { SM_EM_AR_DNSW, "SMAR: DNS write" }, { SM_EM_AR_DNSR, "SMAR: DNS read" }, { SM_EM_AR_DNSD, "SMAR: DNS read" }, { SM_EM_AR_WAIT, "SMAR: wait for async function" }, { SM_EM_AR, "SMAR: misc" }, { SM_EM_CONF, "configuration" }, { SM_EM_PMILTER, "pmilter" }, { SM_EM_THR, "thread" }, { SM_EM_BATV, "BATV" }, { SM_EM_UTIL, "utility functions" }, { 0, NULL } }; e2s_T e_error[] = { { SM_E_NOMORE, "no next entry" }, { SM_E_UNEXPECTED, "unexpected" }, { SM_E_RANGE, "input parameter out of range" }, { SM_E_2BIG, "input parameter too big" }, { SM_E_FULL, "object full" }, { SM_E_OVFLW_SC, "scalar overflow" }, { SM_E_OVFLW_NS, "nonscalar overflow" }, { SM_E_NOTFOUND, "not found" }, { SM_E_STARTFAIL, "start failure" }, { SM_E_SYNTAX, "syntax" }, { SM_E_USAGE, "usage" }, { SM_E_DONTSTART, "donotstart" }, { SM_E_VER_MIX, "version mismatch" }, { SM_E_NO_AR, "smar not available" }, { SM_E_NO_DA, "no delivery agent available" }, { SM_E_NO_DA_FREE, "no free delivery agent" }, { SM_E_PR_V_MISM, "protocol version mismatch" }, { SM_E_PR_ERR, "protocol error" }, { SM_E_RCB2LONG, "RCB too large" }, { SM_E_TEMPMAP, "temporary map error" }, { SM_E_PERMMAP, "permanent map error" }, { SM_E_CLOSEDMAP, "closedmap" }, { SM_E_NOMAP, "map is not available" }, { SM_E_NOTIMPL, "not implemented" }, { SM_E_MXEMPTY, "MX list is empty after removal of local addresses" }, { SM_E_TTMYSELF, "talking to myself" }, { SM_E_ALIASEXP, "alias expansion failed" }, { SM_E_ALIAS_REC, "aliases nested too deep" }, { SM_E_IP_MISM, "DNS answer from different server" }, { SM_E_NOSIG, "no signature" }, { SM_E_EXPIRED, "expired" }, { SM_E_RSR_PRB, "resource problem" }, { SM_E_ILL_PIPE, "illegal pipelining" }, { SM_E_RD, "read error" }, { SM_E_EOF, "EOF" }, { SM_E_WR, "write error" }, { SM_E_BARE_NL, "bare NL detected" }, { SM_E_CONN_CLSD, "internal connection to other module closed" }, { SM_E_WRONG_ID, "internal error: communication context id mismatch" }, { SM_SSL_ERROR_SYSCALL, "TLS syscall error" }, { SM_SSL_ERROR_SSL, "TLS protocol error" }, { SM_SSL_ERROR_GENERIC, "TLS unknown error" }, { SM_E_UNAVAIL, "unavailable" }, { DNSR_NOTFOUND, "DNS record not found (authorative)" }, { DNSR_NO_DATA, "valid name but no data record of requested type" }, { DNSR_TEMP, "query failed: try again" }, { DNSR_PERM, "query failed: do not retry" }, { DNSR_TIMEOUT, "query timed out" }, { DNSR_REFUSED, "query refused by nameserver" }, { DNSR_MXINVALID, "MX record invalid" }, { DNSR_PTRINVALID, "PTR record invalid" }, { DNSR_CNINVALID, "CNAME record invalid" }, { R2821_ERR_LEFT, "missing '<'" }, { R2821_ERR_RIGHT, "missing '>'" }, { R2821_ERR_ROUTE, "route address not allowed" }, { R2821_ERR_HOST, "domain part does not start with an atom" }, { R2821_ERR_FQDN, "domain part is not a FQDN" }, { R2821_ERR_LOCAL, "missing local part" }, { R2821_ERR_AT, "missing '@'" }, { R2821_ERR_EMPTY, "<> not allowed here" }, { R2821_ERR_MBOX, "completely empty address" }, { R2821_ERR_COLON, "missing ':' (unused)" }, { R2821_ERR_DOTSTR, "\"dotstr\" syntax is wrong: expected atom after '.'" }, { R2821_ERR_DOMAIN, "domain part is empty" }, { R2821_ERR_DOT, "expecting ':'" }, { R2821_ERR_TRAILDOT, "domain has trailing '.'" }, { R2821_ERR_ATDOMAIN, "'@' in route address missing" }, { R2821_ERR_COMMA, "comma in route address missing" }, { R2821_ERR_DOMSYNTAX, "domain part has wrong syntax" }, { R2821_ERR_MORE, "tokens after end" }, { R2821_ERR_DEL_MISS, "domain does not end in delimiter" }, { R2821_ERR_TOOLONG, "address too long" }, { R2821_ERR_TRAILBACKSL, "trailing backslash" }, { R2821_ERR_CLS_BRACKET, "too many closing brackets" }, { R2821_ERR_CLS_PARENTH, "too many closing parentheses" }, { R2821_ERR_PARENTHESIS, "parenthesis in address not allowed" }, { R2821_ERR_MUSTQUOTE, "character must be quoted but isn't" }, { SM_CNF_E_NEWLINE_IN_STRING, "newline in string" }, { SM_CNF_E_EOF_IN_STRING, "EOF in string" }, { SM_CNF_E_BAD_CHAR, "unexpected character" }, { SM_CNF_E_NO_MEMORY, "out of memory" }, { SM_CNF_E_HEX_EXPECTED, "hexadecimal digit expected after \\x \\u or \\U" }, { SM_CNF_E_CHAR_OVERFLOW, "character constant too large" }, { SM_CNF_E_INVALID, "invalid argument to configuration function" }, { SM_CNF_E_READ, "error while reading configuration file" }, { SM_CNF_E_READ_OPEN, "cannot open configuration file for reading" }, { SM_CNF_E_READ_CLOSE, "error closing configuration file after reading" }, { SM_CNF_E_SYNTAX, "syntax error" }, { SM_CNF_E_NOT_FOUND, "not found" }, { SM_CNF_E_ALREADY, "already exists" }, { SM_CNF_E_TYPE, "invalid value" }, { SM_CNF_E_NUL_IN_STRING, "ascii NUL character in string" }, { SM_CNF_E_TOO_MANY, "too many elements in array" }, { 0, NULL } }; /* XXX HACK XXX is there a DB function to do this? */ e2s_T e_bdb4_2[] = { { DB_DONOTINDEX, "DB_DONOTINDEX" }, #ifdef DB_FILEOPEN { DB_FILEOPEN, "DB_FILEOPEN" }, #endif { DB_KEYEMPTY, "DB_KEYEMPTY" }, { DB_KEYEXIST, "DB_KEYEXIST" }, { DB_LOCK_DEADLOCK, "DB_LOCK_DEADLOCK" }, { DB_LOCK_NOTGRANTED, "DB_LOCK_NOTGRANTED" }, { DB_NOSERVER, "DB_NOSERVER" }, { DB_NOSERVER_HOME, "DB_NOSERVER_HOME" }, { DB_NOSERVER_ID, "DB_NOSERVER_ID" }, { DB_NOTFOUND, "DB_NOTFOUND" }, { DB_OLD_VERSION, "DB_OLD_VERSION" }, { DB_PAGE_NOTFOUND, "DB_PAGE_NOTFOUND" }, { DB_REP_DUPMASTER, "DB_REP_DUPMASTER" }, #ifdef DB_REP_HANDLE_DEAD { DB_REP_HANDLE_DEAD, "DB_REP_HANDLE_DEAD" }, #endif { DB_REP_HOLDELECTION, "DB_REP_HOLDELECTION" }, #ifdef DB_REP_ISPERM { DB_REP_ISPERM, "DB_REP_ISPERM" }, #endif { DB_REP_NEWMASTER, "DB_REP_NEWMASTER" }, { DB_REP_NEWSITE, "DB_REP_NEWSITE" }, #ifdef DB_REP_NOTPERM { DB_REP_NOTPERM, "DB_REP_NOTPERM" }, #endif #ifdef DB_REP_OUTDATED { DB_REP_OUTDATED, "DB_REP_OUTDATED" }, #endif { DB_REP_UNAVAIL, "DB_REP_UNAVAIL" }, { DB_RUNRECOVERY, "DB_RUNRECOVERY" }, { DB_SECONDARY_BAD, "DB_SECONDARY_BAD" }, #ifdef DB_VERIFY_BAD { DB_VERIFY_BAD, "DB_VERIFY_BAD" }, #endif #if defined(DB_BUFFER_SMALL) && ENOMEM != DB_BUFFER_SMALL { DB_BUFFER_SMALL, "DB_BUFFER_SMALL" }, #endif { 0, NULL } }; #if 0 static e2s_T e_dns[] = { { DNSR_NOTFOUND, "DNSR Not Found" }, { DNSR_NO_DATA, "Valid name but no data record of requested type" }, { DNSR_TEMP, "query failed: try again" }, { DNSR_PERM, "query failed: don't retry" }, { DNSR_TIMEOUT, "query timed out" }, { DNSR_REFUSED, "query refused by nameserver" }, { DNSR_MXINVALID, "MX record invalid" }, { DNSR_PTRINVALID, "PTR record invalid" }, { DNSR_CNINVALID, "CNAME record invalid" }, { 0, NULL } }; #endif /* 0 */ char * finde(int ecode, e2s_P table) { int i; i = 0; while (table[i].e2s_code != 0 || table[i].e2s_str != NULL) { if (table[i].e2s_code == ecode) return table[i].e2s_str; if (sm_error_value(table[i].e2s_code) == sm_error_value(ecode)) return table[i].e2s_str; ++i; } return NULL; } char * smmod2txt(sm_error_T err) { char *errtxt; errtxt = finde(sm_error_module(err), e_modules); return (errtxt != NULL) ? errtxt : SM_ETXT_UNKNOWN; } char * smerr2txt(sm_error_T err) { int errornumber, eno; char *errtxt; eno = errornumber = sm_error_value(err); errtxt = NULL; if (err == SM_IO_EOF) errtxt = "EOF"; else if (errornumber > 0 && errornumber < sm_sys_nerr) errtxt = strerror(errornumber); else if (SM_IS_BDB_ERR(err)) #if 0 /* ** If this is used then every application needs to link ** against libdb. */ errtxt = db_strerror(eno); #else errtxt = finde(eno, e_bdb4_2); #endif #if 0 else if (errornumber >= DNS_ERR_BASE && errornumber < R2821_BASE) errtxt = finde(err, e_dns); #endif /* 0 */ else errtxt = finde(errornumber, e_error); return (errtxt != NULL) ? errtxt : SM_ETXT_UNKNOWN; }