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.
This commit is contained in:
parent
5f87d8dcc8
commit
c45386588b
3 changed files with 34 additions and 7 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue