aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/librdns
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-12-16 15:03:22 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-12-16 15:03:22 +0000
commitcfbfd0fca860f3d616fa07e0e9706a3f954f5476 (patch)
tree7dbf903cf5b18dc6790a6c775d7179043baf60fd /contrib/librdns
parentbd3b1b6d81ea91e3e4781c226e24d7162fa70e34 (diff)
downloadrspamd-cfbfd0fca860f3d616fa07e0e9706a3f954f5476.tar.gz
rspamd-cfbfd0fca860f3d616fa07e0e9706a3f954f5476.zip
[Minor] Try to retransmit DNS requests on write failures
Diffstat (limited to 'contrib/librdns')
-rw-r--r--contrib/librdns/resolver.c112
1 files changed, 81 insertions, 31 deletions
diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c
index 9c214c21e..aec0e9381 100644
--- a/contrib/librdns/resolver.c
+++ b/contrib/librdns/resolver.c
@@ -555,6 +555,43 @@ rdns_process_retransmit (int fd, void *arg)
}
}
+struct rdns_server *
+rdns_select_request_upstream (struct rdns_resolver *resolver,
+ struct rdns_request *req,
+ bool is_retransmit,
+ struct rdns_server *prev_serv)
+{
+ struct rdns_server *serv = NULL;
+
+ if (resolver->ups) {
+ struct rdns_upstream_elt *elt;
+
+ if (is_retransmit && prev_serv) {
+ elt = resolver->ups->select_retransmit (req->requested_names[0].name,
+ req->requested_names[0].len,
+ prev_serv->ups_elt,
+ resolver->ups->data);
+ }
+ else {
+ elt = resolver->ups->select (req->requested_names[0].name,
+ req->requested_names[0].len, resolver->ups->data);
+ }
+
+ if (elt) {
+ serv = elt->server;
+ serv->ups_elt = elt;
+ }
+ else {
+ UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
+ }
+ }
+ else {
+ UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
+ }
+
+ return serv;
+}
+
#define align_ptr(p, a) \
(guint8 *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
@@ -741,30 +778,14 @@ rdns_make_request_full (
/* Add EDNS RR */
rdns_add_edns0 (req);
- req->retransmits = repeats;
+ req->retransmits = repeats ? repeats : 1;
req->timeout = timeout;
req->state = RDNS_REQUEST_NEW;
}
req->async = resolver->async;
- if (resolver->ups) {
- struct rdns_upstream_elt *elt;
-
- elt = resolver->ups->select (req->requested_names[0].name,
- req->requested_names[0].len, resolver->ups->data);
-
- if (elt) {
- serv = elt->server;
- serv->ups_elt = elt;
- }
- else {
- UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
- }
- }
- else {
- UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
- }
+ serv = rdns_select_request_upstream (resolver, req, false, NULL);
if (serv == NULL) {
rdns_warn ("cannot find suitable server for request");
@@ -780,25 +801,54 @@ rdns_make_request_full (
req->io->sock, req);
}
else {
- req->io->uses++;
-
/* Now send request to server */
- r = rdns_send_request (req, req->io->sock, true);
+ do {
+ r = rdns_send_request (req, req->io->sock, true);
- if (r == -1) {
- rdns_info ("cannot send DNS request: %s", strerror (errno));
- REF_RELEASE (req);
+ if (r == -1) {
+ req->retransmits --; /* It must be > 0 */
+
+ if (req->retransmits > 0) {
+ if (resolver->ups && serv->ups_elt) {
+ resolver->ups->fail (serv->ups_elt, resolver->ups->data,
+ "send IO error");
+ }
+ else {
+ UPSTREAM_FAIL (serv, time (NULL));
+ }
+
+ serv = rdns_select_request_upstream (resolver, req,
+ true, serv);
- if (resolver->ups && serv->ups_elt) {
- resolver->ups->fail (serv->ups_elt, resolver->ups->data,
- "send IO error");
+ if (serv == NULL) {
+ rdns_warn ("cannot find suitable server for request");
+ REF_RELEASE (req);
+ return NULL;
+ }
+
+ req->io = serv->io_channels[ottery_rand_uint32 () % serv->io_cnt];
+ }
+ else {
+ rdns_info ("cannot send DNS request: %s", strerror (errno));
+ REF_RELEASE (req);
+
+ if (resolver->ups && serv->ups_elt) {
+ resolver->ups->fail (serv->ups_elt, resolver->ups->data,
+ "send IO error");
+ }
+ else {
+ UPSTREAM_FAIL (serv, time (NULL));
+ }
+
+ return NULL;
+ }
}
else {
- UPSTREAM_FAIL (serv, time (NULL));
+ /* All good */
+ req->io->uses++;
+ break;
}
-
- return NULL;
- }
+ } while (req->retransmits > 0);
}
REF_RETAIN (req->io);