Skip to content

Commit a84e31f

Browse files
committed
Add resolver fallback to the null resolver (getaddrinfo)
This enables a best-effort, two-step resolution when a resolver is configured: - if the DNS resolver returns any domain, that record is used with its corresponding TTL - otherwise, the module tries resolving the name with the default, NULL resolver, which is just a wrapper over getaddrinfo * if the resolution succeeds, this was likely a domain in /etc/hosts or an IP literal, which was not known by the DNS server. The associated record has no TTL value and uses the default director TTL. * if the resolution fails, this was likely a bad domain. No records are stored and a new request is made after the default director TTL, as was done previously.
1 parent 2d51da7 commit a84e31f

File tree

3 files changed

+75
-30
lines changed

3 files changed

+75
-30
lines changed

src/tests/resolver/fallback.vtc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
varnishtest "falling back from a resolver to getaddrinfo"
2+
3+
server s1 {
4+
rxreq
5+
txresp
6+
} -start
7+
8+
varnish v1 -vcl+backend {
9+
import ${vmod_dynamic};
10+
11+
sub vcl_init {
12+
new r1 = dynamic.resolver();
13+
new d1 = dynamic.director(
14+
resolver = r1.use());
15+
d1.debug(true);
16+
}
17+
18+
sub vcl_recv {
19+
set req.backend_hint = d1.backend(host = "img.localhost", port = "${s1_port}");
20+
}
21+
} -start
22+
23+
client c1 {
24+
txreq
25+
rxresp
26+
expect resp.status == 200
27+
} -run

src/vmod_dynamic.c

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ dom_lookup_thread(void *priv)
775775
struct vrt_ctx ctx;
776776
vtim_real lookup, results, update;
777777
const struct res_cb *res;
778+
struct vmod_dynamic_resolver *res_instance;
778779
void *res_priv = NULL;
779780
int ret;
780781

@@ -783,49 +784,63 @@ dom_lookup_thread(void *priv)
783784

784785
obj = dom->obj;
785786
res = obj->resolver;
787+
res_instance = obj->resolver_inst;
786788

787789
Lck_Lock(&dom->mtx);
788790
assert(dom->status == DYNAMIC_ST_STARTING);
789791
while (dom->status <= DYNAMIC_ST_ACTIVE) {
790792
Lck_Unlock(&dom->mtx);
791793

792-
lookup = VTIM_real();
793-
if (lookup > dom->expires) {
794-
Lck_Lock(&obj->domains_mtx);
794+
while (1) { // Loop run at most twice: one for the resolve, and one for the fallaback gai resolver
795+
lookup = VTIM_real();
795796
if (lookup > dom->expires) {
796-
LOG(NULL, SLT_VCL_Log, dom, "%s", "timeout");
797-
dom->expires = HUGE_VAL;
798-
VRBT_REMOVE(dom_tree_head, &obj->ref_domains,
799-
dom);
800-
VTAILQ_INSERT_TAIL(&obj->unref_domains, dom,
801-
link.list);
797+
Lck_Lock(&obj->domains_mtx);
798+
if (lookup > dom->expires) {
799+
LOG(NULL, SLT_VCL_Log, dom, "%s", "timeout");
800+
dom->expires = HUGE_VAL;
801+
VRBT_REMOVE(dom_tree_head, &obj->ref_domains,
802+
dom);
803+
VTAILQ_INSERT_TAIL(&obj->unref_domains, dom,
804+
link.list);
805+
}
806+
Lck_Unlock(&obj->domains_mtx);
802807
}
803-
Lck_Unlock(&obj->domains_mtx);
804-
}
805808

806-
dynamic_timestamp(dom, "Lookup", lookup, 0., 0.);
809+
dynamic_timestamp(dom, "Lookup", lookup, 0., 0.);
807810

808-
ret = res->lookup(obj->resolver_inst, dom->addr,
809-
dom_port(dom), &res_priv);
811+
ret = res->lookup(res_instance, dom->addr,
812+
dom_port(dom), &res_priv);
810813

811-
results = VTIM_real();
812-
dynamic_timestamp(dom, "Results", results, results - lookup,
813-
results - lookup);
814+
results = VTIM_real();
815+
dynamic_timestamp(dom, "Results", results, results - lookup,
816+
results - lookup);
814817

815-
if (ret == 0) {
816-
dom_update(dom, res, res_priv, results);
817-
update = VTIM_real();
818-
dynamic_timestamp(dom, "Update", update,
819-
update - lookup, update - results);
820-
} else {
821-
LOG(&ctx, SLT_Error, dom, "%s %d (%s)",
822-
res->name, ret, res->strerror(ret));
823-
dom->deadline = results + obj->retry_after;
824-
dbg_res_details(NULL, dom->obj, res, res_priv);
825-
}
818+
if (ret == 0) {
819+
dom_update(dom, res, res_priv, results);
820+
update = VTIM_real();
821+
dynamic_timestamp(dom, "Update", update,
822+
update - lookup, update - results);
823+
} else {
824+
LOG(&ctx, SLT_Error, dom, "%s %d (%s)",
825+
res->name, ret, res->strerror(ret));
826+
dbg_res_details(NULL, dom->obj, res, res_priv);
827+
}
828+
829+
res->fini(&res_priv);
830+
AZ(res_priv);
826831

827-
res->fini(&res_priv);
828-
AZ(res_priv);
832+
if (ret == 0) {
833+
break;
834+
}
835+
if (res == &res_gai) {
836+
/* Failed with fallback getaddrinfo resolver: update deadline with default TTL and break */
837+
dom->deadline = results + obj->retry_after;
838+
break;
839+
}
840+
/* Failed with custom resolver: try again with fallback getaddrinfo resolver */
841+
res = &res_gai;
842+
res_instance = NULL;
843+
}
829844

830845
Lck_Lock(&dom->mtx);
831846

src/vmod_dynamic.vcc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ Parameters:
306306
The argument to the *resolver* parameter must be the return
307307
value of the `xresolver.use()`_ method.
308308

309+
If the resolver does not find any addresses, a fallback
310+
attempt to resolve the address without the resolver is made.
311+
309312
.. _ttl_from:
310313

311314
- *ttl_from*

0 commit comments

Comments
 (0)