diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-11-16 04:42:09 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-11-16 04:42:09 +0100 |
commit | c45386588ba849f2859833ab9c368b7bc6cc0a31 (patch) | |
tree | f2d502e0f289240b8d4ae19503ac4c29c0fdb045 | |
parent | 5f87d8dcc814700f10f40c10a0225400e4828ef9 (diff) | |
download | plan9front-c45386588ba849f2859833ab9c368b7bc6cc0a31.tar.xz |
ndb/dns: detect query loops
never try to resolve a nameserver address when that nameserver
is in the set of nameservers already being queried.
this situation can happen when the Ta and Taaaa RR's expire, but
the Tns records are still in the cache so there is no usable
nameserver but they still refer to each another.
-rw-r--r-- | sys/src/cmd/ndb/dn.c | 1 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dnresolve.c | 39 | ||||
-rw-r--r-- | sys/src/cmd/ndb/dns.h | 1 |
3 files changed, 34 insertions, 7 deletions
diff --git a/sys/src/cmd/ndb/dn.c b/sys/src/cmd/ndb/dn.c index 7383c9e4b..fcf262259 100644 --- a/sys/src/cmd/ndb/dn.c +++ b/sys/src/cmd/ndb/dn.c @@ -655,6 +655,7 @@ getactivity(Request *req, int recursive) now = time(nil); nowns = nsec(); req->id = ++dnvars.id; + req->aux = nil; unlock(&dnvars); return rv; diff --git a/sys/src/cmd/ndb/dnresolve.c b/sys/src/cmd/ndb/dnresolve.c index 6e8709e94..3c5942093 100644 --- a/sys/src/cmd/ndb/dnresolve.c +++ b/sys/src/cmd/ndb/dnresolve.c @@ -52,6 +52,8 @@ struct Query { DN *dp; /* domain */ ushort type; /* and type to look up */ Request *req; + Query *prev; /* previous query */ + RR *nsrp; /* name servers to consult */ /* dest must not be on the stack due to forking in slave() */ @@ -225,14 +227,18 @@ queryinit(Query *qp, DN *dp, int type, Request *req) qp->type = type; if (qp->type != type) dnslog("queryinit: bogus type %d", type); - qp->req = req; qp->nsrp = nil; qp->dest = qp->curdest = nil; + qp->prev = req->aux; + qp->req = req; + req->aux = qp; } static void querydestroy(Query *qp) { + if(qp->req->aux == qp) + qp->req->aux = qp->prev; /* leave udpfd open */ if (qp->tcpfd >= 0) close(qp->tcpfd); @@ -739,6 +745,30 @@ ipisbm(uchar *ip) return 0; } +static int +queryloops(Query *qp, RR *rp) +{ + DN *ns; + + ns = rp->host; + + /* + * avoid loops looking up a server under itself + */ + if(subsume(rp->owner->name, ns->name)) + return 1; + + /* + * must not cycle on name servers refering + * to each another. + */ + for(qp = qp->prev; qp; qp = qp->prev) + for(rp = qp->nsrp; rp; rp = rp->next) + if(rp->host == ns) + return 1; + return 0; +} + /* * Get next server address(es) into qp->dest[nd] and beyond */ @@ -787,13 +817,8 @@ serveraddrs(Query *qp, int nd, int depth) if(rp->marker) continue; rp->marker = 1; - - /* - * avoid loops looking up a server under itself - */ - if(subsume(rp->owner->name, rp->host->name)) + if(queryloops(qp, rp)) continue; - arp = dnresolve(rp->host->name, Cin, Ta, qp->req, 0, depth+1, Recurse, 1, 0); if(arp == nil) diff --git a/sys/src/cmd/ndb/dns.h b/sys/src/cmd/ndb/dns.h index 1e0ae2e86..e14a20cdd 100644 --- a/sys/src/cmd/ndb/dns.h +++ b/sys/src/cmd/ndb/dns.h @@ -182,6 +182,7 @@ struct Request jmp_buf mret; /* where master jumps to after starting a slave */ int id; char *from; /* who asked us? */ + void *aux; }; /* |