From a073be8fbc9479ff4a45a35b479547fe530858c4 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 5 Jul 2018 16:04:17 +0100 Subject: [PATCH] [Fix] Work with broken resolvers in resolv.conf --- contrib/librdns/resolver.c | 30 +++++++++++++++++++++++++----- contrib/librdns/util.c | 11 +++++------ src/libserver/dns.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c index b3f698fdf..2ce85b2c5 100644 --- a/contrib/librdns/resolver.c +++ b/contrib/librdns/resolver.c @@ -548,11 +548,19 @@ rdns_make_request_full ( struct rdns_fake_reply_idx *idx; if (resolver == NULL || !resolver->initialized) { + if (resolver == NULL) { + return NULL; + } + + rdns_err ("resolver is uninitialized"); + return NULL; } req = malloc (sizeof (struct rdns_request)); if (req == NULL) { + rdns_err ("failed to allocate memory for request: %s", + strerror (errno)); return NULL; } @@ -569,6 +577,9 @@ rdns_make_request_full ( if (req->requested_names == NULL) { free (req); + rdns_err ("failed to allocate memory for request data: %s", + strerror (errno)); + return NULL; } @@ -589,7 +600,7 @@ rdns_make_request_full ( clen = strlen (cur_name); if (clen == 0) { - rdns_info ("got empty name to resolve"); + rdns_warn ("got empty name to resolve"); rdns_request_free (req); return NULL; } @@ -615,7 +626,7 @@ rdns_make_request_full ( tlen += clen; } else if (last_name == NULL) { - rdns_info ("got NULL as the first name to resolve"); + rdns_err ("got NULL as the first name to resolve"); rdns_request_free (req); return NULL; } @@ -623,6 +634,7 @@ rdns_make_request_full ( if (req->state != RDNS_REQUEST_FAKE) { if (!rdns_format_dns_name (resolver, last_name, clen, &req->requested_names[cur].name, &olen)) { + rdns_err ("cannot format %s", last_name); rdns_request_free (req); return NULL; } @@ -648,12 +660,14 @@ rdns_make_request_full ( type = req->requested_names[i].type; if (queries > 1) { if (!rdns_add_rr (req, cur_name, clen, type, &comp)) { + rdns_err ("cannot add rr", cur_name); REF_RELEASE (req); rnds_compression_free (comp); return NULL; } } else { if (!rdns_add_rr (req, cur_name, clen, type, NULL)) { + rdns_err ("cannot add rr", cur_name); REF_RELEASE (req); rnds_compression_free (comp); return NULL; @@ -711,6 +725,7 @@ rdns_make_request_full ( r = rdns_send_request (req, req->io->sock, true); if (r == -1) { + rdns_info ("cannot send DNS request"); REF_RELEASE (req); return NULL; } @@ -730,10 +745,12 @@ rdns_resolver_init (struct rdns_resolver *resolver) struct rdns_io_channel *ioc; if (!resolver->async_binded) { + rdns_err ("no async backend specified"); return false; } if (resolver->servers == NULL) { + rdns_err ("no DNS servers defined"); return false; } @@ -743,13 +760,16 @@ rdns_resolver_init (struct rdns_resolver *resolver) for (i = 0; i < serv->io_cnt; i ++) { ioc = calloc (1, sizeof (struct rdns_io_channel)); if (ioc == NULL) { - rdns_err ("cannot allocate memory for the resolver"); + rdns_err ("cannot allocate memory for the resolver IO channels"); return false; } + ioc->sock = rdns_make_client_socket (serv->name, serv->port, SOCK_DGRAM); - ioc->active = true; + if (ioc->sock == -1) { - rdns_err ("cannot open socket to %s:%d %s", serv->name, serv->port, strerror (errno)); + ioc->active = false; + rdns_err ("cannot open socket to %s:%d %s", + serv->name, serv->port, strerror (errno)); free (ioc); return false; } diff --git a/contrib/librdns/util.c b/contrib/librdns/util.c index 401c6aad3..1cace2386 100644 --- a/contrib/librdns/util.c +++ b/contrib/librdns/util.c @@ -559,7 +559,7 @@ rdns_resolver_conf_process_line (struct rdns_resolver *resolver, } /* XXX: skip unknown resolv.conf lines */ - return true; + return false; } bool @@ -569,6 +569,7 @@ rdns_resolver_parse_resolv_conf_cb (struct rdns_resolver *resolver, FILE *in; char buf[BUFSIZ]; char *p; + bool processed = false; in = fopen (path, "r"); @@ -588,16 +589,14 @@ rdns_resolver_parse_resolv_conf_cb (struct rdns_resolver *resolver, *p-- = '\0'; } - if (!rdns_resolver_conf_process_line (resolver, buf, cb, ud)) { - rdns_warn ("rdns_resolver_parse_resolv_conf: cannot parse line: %s", buf); - fclose (in); - return false; + if (rdns_resolver_conf_process_line (resolver, buf, cb, ud)) { + processed = true; } } fclose (in); - return true; + return processed; } bool diff --git a/src/libserver/dns.c b/src/libserver/dns.c index b10eaf8c4..d75ad00e8 100644 --- a/src/libserver/dns.c +++ b/src/libserver/dns.c @@ -21,6 +21,7 @@ #include "utlist.h" #include "uthash.h" #include "rdns_event.h" +#include "unix-std.h" static struct rdns_upstream_elt* rspamd_dns_select_upstream (const char *name, size_t len, void *ups_data); @@ -240,6 +241,34 @@ rspamd_dns_resolv_conf_on_server (struct rdns_resolver *resolver, int priority, unsigned int io_cnt, void *ud) { struct rspamd_dns_resolver *dns_resolver = ud; + struct rspamd_config *cfg; + rspamd_inet_addr_t *addr; + gint test_fd; + + cfg = dns_resolver->cfg; + + msg_info_config ("parsed nameserver %s from resolv.conf", name); + + /* Try to open a connection */ + if (!rspamd_parse_inet_address (&addr, name, strlen (name))) { + msg_warn_config ("cannot parse nameserver address %s", name); + + return FALSE; + } + + rspamd_inet_address_set_port (addr, port); + test_fd = rspamd_inet_address_connect (addr, SOCK_DGRAM, TRUE); + + if (test_fd == -1) { + msg_warn_config ("cannot open connection to nameserver at address %s: %s", + name, strerror (errno)); + rspamd_inet_address_free (addr); + + return FALSE; + } + + rspamd_inet_address_free (addr); + close (test_fd); return rspamd_upstreams_add_upstream (dns_resolver->ups, name, port, RSPAMD_UPSTREAM_PARSE_NAMESERVER, -- 2.39.5