diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-11-01 13:30:14 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-11-01 13:30:14 +0200 |
commit | e1ae6a6eb13992e21ee4102c45cc1a692017d891 (patch) | |
tree | 2ec401ca6feea878d2f492bd7185c9fe5903d1a0 | |
parent | 64ea91a529e07f5444e23f05b7dccdcfec3f3db4 (diff) | |
download | mailfromd-e1ae6a6eb13992e21ee4102c45cc1a692017d891.tar.gz mailfromd-e1ae6a6eb13992e21ee4102c45cc1a692017d891.tar.bz2 |
Improve ADNS return status handling.
* lib/dns.c (adns_to_dns_status): Rewrite.
-rw-r--r-- | lib/dns.c | 79 |
1 files changed, 69 insertions, 10 deletions
@@ -248,21 +248,80 @@ errno_to_dns_status(int e) return dns_failure; } } - + +/* Table of correspondence between ADNS status codes and dns status. + Values are increased by 1 to be able to tell whether the entry is + initialized or not. */ +int adns_to_dns_tab[] = { +#define STAT(s) ((s)+1) + [adns_s_ok] = STAT(dns_success), + + [adns_s_nomemory] = STAT(dns_failure), + [adns_s_unknownrrtype] = STAT(dns_failure), + [adns_s_systemfail] = STAT(dns_failure), + + /* remotely induced errors), detected locally */ + [adns_s_timeout] = STAT(dns_temp_failure), + [adns_s_allservfail] = STAT(dns_temp_failure), + [adns_s_norecurse] = STAT(dns_temp_failure), + [adns_s_invalidresponse] = STAT(dns_failure), + [adns_s_unknownformat] = STAT(dns_failure), + + /* remotely induced errors), reported by remote server to us */ + [adns_s_rcodeservfail] = STAT(dns_not_found), + [adns_s_rcodeformaterror] = STAT(dns_not_found), + [adns_s_rcodenotimplemented] = STAT(dns_not_found), + [adns_s_rcoderefused] = STAT(dns_not_found), + [adns_s_rcodeunknown] = STAT(dns_not_found), + + /* remote configuration errors */ + [adns_s_inconsistent] = STAT(dns_not_found), + [adns_s_prohibitedcname] = STAT(dns_not_found), + [adns_s_answerdomaininvalid] = STAT(dns_not_found), + [adns_s_answerdomaintoolong] = STAT(dns_not_found), + [adns_s_invaliddata] = STAT(dns_not_found), + + /* permanent problems with the query */ + [adns_s_querydomainwrong] = STAT(dns_failure), + [adns_s_querydomaininvalid] = STAT(dns_failure), + [adns_s_querydomaintoolong] = STAT(dns_failure), + + /* permanent errors */ + [adns_s_nxdomain] = STAT(dns_not_found), + [adns_s_nodata] = STAT(dns_not_found), +#undef STAT +}; + +/* Convert ADNS status code E to DNS status. */ static int adns_to_dns_status(int e) { - switch (e) { - case adns_s_ok: - return dns_success; - case adns_s_timeout: + int r; + + /* If it is negative, fail right away */ + if (e < 0) + return dns_failure; + /* If it is not in table, it still can be a valid, but unhandled + value */ + if (e >= MU_ARRAY_SIZE(adns_to_dns_tab)) + return e < adns_s_max_permfail ? dns_not_found : dns_failure; + /* Now, look up in the table */ + if ((r = adns_to_dns_tab[e]) > 0) + return r - 1; + /* If not found in table, use adns_s_max_ constants to decide the + error class. + */ + if (e < adns_s_max_localfail) + return dns_failure; + if (e < adns_s_max_remotefail) + return dns_not_found; + if (e < adns_s_max_tempfail) return dns_temp_failure; - case adns_s_nxdomain: - case adns_s_nodata: + if (e < adns_s_max_misconfig) return dns_not_found; - default: - return dns_failure; - } + if (e < adns_s_max_misquery) + return dns_not_found; + return dns_not_found; } dns_status |