ndb/dns: various changes

stop absolute/relative dual use of RR.ttl. now RR.ttl is
*always* the *relative* ttl value. we derive absolute
timeout in RR.expire.

remove unused lookuptime field in DN. replace refs and
keep with mark field in DN. we do not care about the
number of references. only *iff* it is referenced, so
use a single bit for that (bit 0). for keep, we use
bit 1.

remove dolock parameter in dnagenever(), it is not
needed. we always need to lock.

mark local dns servers and domains as never to be aged.

the keeper bit is *just* a cache optimization, preventing
the domain and the domains it points to from being flushed.
it should not be used as a write protect bit in rrattach()
for preventing spoofing as it will prevent updates of say,
cname domains.

remove "removing spam ..." message. these are usualy just
hints, so normal. still, remove the hint as we currently
do no check if the nameserver has authority over the
cname domain.

remove "mydnsquery: trying to send to myself (%s); bzzzt"
message. this can happen when myaddr() fails for other
reasons. myaddr() will print error for us anyway.
This commit is contained in:
cinap_lenrek 2013-11-15 02:00:47 +01:00
parent 2ce68c5aa1
commit 5f87d8dcc8
7 changed files with 62 additions and 70 deletions

View file

@ -192,18 +192,16 @@ static uchar*
convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp) convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
{ {
uchar *lp, *data; uchar *lp, *data;
int len, ttl; long ttl;
int len;
Txt *t; Txt *t;
NAME(rp->owner->name); NAME(rp->owner->name);
USHORT(rp->type); USHORT(rp->type);
USHORT(rp->owner->class); USHORT(rp->owner->class);
/* egregious overuse of ttl (it's absolute time in the cache) */ if(rp->db || (ttl = (long)(rp->expire - now)) > rp->ttl)
if(rp->db)
ttl = rp->ttl; ttl = rp->ttl;
else
ttl = rp->ttl - now;
if(ttl < 0) if(ttl < 0)
ttl = 0; ttl = 0;
ULONG(ttl); ULONG(ttl);

View file

@ -345,7 +345,6 @@ retry:
rp->type = type; rp->type = type;
ULONG(rp->ttl); ULONG(rp->ttl);
rp->ttl += now;
USHORT(len); /* length of data following */ USHORT(len); /* length of data following */
data = sp->p; data = sp->p;
assert(data != nil); assert(data != nil);

View file

@ -17,7 +17,7 @@ enum {
* confused by a zero ttl, and instead of using the data and then * confused by a zero ttl, and instead of using the data and then
* discarding the RR, they conclude that they don't have valid data. * discarding the RR, they conclude that they don't have valid data.
*/ */
Ptrttl = 120, Ptrttl = 2*Min,
}; };
static Ndb *db; static Ndb *db;
@ -611,10 +611,10 @@ dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
return; return;
rp->owner = dp; rp->owner = dp;
dnagenever(dp, 1);
rp->db = 1; rp->db = 1;
rp->ttl = intval(entry, pair, "ttl", rp->ttl); rp->ttl = intval(entry, pair, "ttl", rp->ttl);
rrattach(rp, Notauthoritative); rrattach(rp, Notauthoritative);
dnagenever(dp);
} }
static void static void
dbtuple2cache(Ndbtuple *t) dbtuple2cache(Ndbtuple *t)
@ -911,9 +911,9 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
rp->owner = dp; /* e.g., local#dns#servers */ rp->owner = dp; /* e.g., local#dns#servers */
rp->local = 1; rp->local = 1;
rp->db = 1; rp->db = 1;
// rp->ttl = 10*Min; /* seems too short */ rp->ttl = 10*Min;
rp->ttl = (1UL<<31)-1;
rrattach(rp, Authoritative); /* will not attach rrs in my area */ rrattach(rp, Authoritative); /* will not attach rrs in my area */
dnagenever(dp);
/* A or AAAA record */ /* A or AAAA record */
if (parseip(ip, ipaddr) >= 0 && isv4(ip)) if (parseip(ip, ipaddr) >= 0 && isv4(ip))
@ -924,9 +924,9 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
rp->owner = nsdp; rp->owner = nsdp;
rp->local = 1; rp->local = 1;
rp->db = 1; rp->db = 1;
// rp->ttl = 10*Min; /* seems too short */ rp->ttl = 10*Min;
rp->ttl = (1UL<<31)-1;
rrattach(rp, Authoritative); /* will not attach rrs in my area */ rrattach(rp, Authoritative); /* will not attach rrs in my area */
dnagenever(nsdp);
dnslog("added local dns server %s at %s", buf, ipaddr); dnslog("added local dns server %s at %s", buf, ipaddr);
} }
@ -983,6 +983,7 @@ addlocaldnsdomain(DN *dp, int class, char *domain)
rp->db = 1; rp->db = 1;
rp->ttl = 10*Min; rp->ttl = 10*Min;
rrattach(rp, Authoritative); rrattach(rp, Authoritative);
dnagenever(dp);
} }
/* /*

View file

@ -14,14 +14,10 @@
* figure it out. * figure it out.
*/ */
enum { enum {
// Deftarget = 1<<30, /* effectively disable aging */
// Minage = 1<<30,
// Defagefreq = 1<<30, /* age names this often (seconds) */
/* these settings will trigger frequent aging */ /* these settings will trigger frequent aging */
Deftarget = 4000, Deftarget = 4000,
Minage = 5*60, Minage = 5*Min,
Defagefreq = 15*60, /* age names this often (seconds) */ Defagefreq = 15*Min, /* age names this often (seconds) */
}; };
/* /*
@ -305,9 +301,9 @@ dndump(char *file)
for(dp = ht[i]; dp; dp = dp->next){ for(dp = ht[i]; dp; dp = dp->next){
fprint(fd, "%s\n", dp->name); fprint(fd, "%s\n", dp->name);
for(rp = dp->rr; rp; rp = rp->next) { for(rp = dp->rr; rp; rp = rp->next) {
fprint(fd, "\t%R %c%c %lud/%lud\n", fprint(fd, "\t%R %c%c %ld/%lud\n",
rp, rp->auth? 'A': 'U', rp, rp->auth? 'A': 'U',
rp->db? 'D': 'N', rp->expire, rp->ttl); rp->db? 'D': 'N', (long)(rp->expire - now), rp->ttl);
if (rronlist(rp, rp->next)) if (rronlist(rp, rp->next))
fprint(fd, "*** duplicate:\n"); fprint(fd, "*** duplicate:\n");
} }
@ -372,29 +368,28 @@ dnage(DN *dp)
if (canlock(&dnlock)) if (canlock(&dnlock))
abort(); /* dnage called with dnlock not held */ abort(); /* dnage called with dnlock not held */
diff = now - dp->referenced; diff = now - dp->referenced;
if(diff < Reserved || dp->keep) if(diff < Reserved || dp->mark != 0)
return; return;
l = &dp->rr; l = &dp->rr;
while ((rp = *l) != nil){ while ((rp = *l) != nil){
assert(rp->magic == RRmagic && rp->cached); assert(rp->magic == RRmagic && rp->cached);
if(!rp->db && (rp->expire < now || diff > dnvars.oldest)) if(!rp->db && ((long)(rp->expire - now) <= 0 || diff > dnvars.oldest))
rrdelhead(l); /* rp == *l before; *l == rp->next after */ rrdelhead(l); /* rp == *l before; *l == rp->next after */
else else
l = &rp->next; l = &rp->next;
} }
} }
#define MARK(dp) { if (dp) (dp)->keep = 1; } #define MARK(dp) { if (dp) (dp)->mark |= 2; }
/* mark a domain name and those in its RRs as never to be aged */ /* mark a domain name and those in its RRs as never to be aged */
void void
dnagenever(DN *dp, int dolock) dnagenever(DN *dp)
{ {
RR *rp; RR *rp;
if (dolock) lock(&dnlock);
lock(&dnlock);
/* mark all referenced domain names */ /* mark all referenced domain names */
MARK(dp); MARK(dp);
@ -449,11 +444,10 @@ dnagenever(DN *dp, int dolock)
} }
} }
if (dolock) unlock(&dnlock);
unlock(&dnlock);
} }
#define REF(dp) { if (dp) (dp)->refs++; } #define REF(dp) { if (dp) (dp)->mark |= 1; }
/* /*
* periodicly sweep for old records and remove unreferenced domain names * periodicly sweep for old records and remove unreferenced domain names
@ -468,7 +462,7 @@ dnageall(int doit)
RR *rp; RR *rp;
static ulong nextage; static ulong nextage;
if(dnvars.names < target || (now < nextage && !doit)){ if(dnvars.names < target || ((long)(nextage - now) > 0 && !doit)){
dnvars.oldest = maxage; dnvars.oldest = maxage;
return; return;
} }
@ -483,14 +477,14 @@ dnageall(int doit)
if (agefreq > dnvars.oldest / 2) if (agefreq > dnvars.oldest / 2)
nextage = now + dnvars.oldest / 2; nextage = now + dnvars.oldest / 2;
else else
nextage = now + agefreq; nextage = now + (ulong)agefreq;
lock(&dnlock); lock(&dnlock);
/* time out all old entries (and set refs to 0) */ /* time out all old entries (and set refs to 0) */
for(i = 0; i < HTLEN; i++) for(i = 0; i < HTLEN; i++)
for(dp = ht[i]; dp; dp = dp->next){ for(dp = ht[i]; dp; dp = dp->next){
dp->refs = 0; dp->mark &= ~1;
dnage(dp); dnage(dp);
} }
@ -552,7 +546,7 @@ dnageall(int doit)
for(i = 0; i < HTLEN; i++){ for(i = 0; i < HTLEN; i++){
l = &ht[i]; l = &ht[i];
for(dp = *l; dp; dp = *l){ for(dp = *l; dp; dp = *l){
if(dp->rr == nil && dp->refs == 0 && dp->keep == 0){ if(dp->rr == nil && dp->mark == 0){
assert(dp->magic == DNmagic); assert(dp->magic == DNmagic);
*l = dp->next; *l = dp->next;
@ -586,7 +580,7 @@ dnagedb(void)
/* time out all database entries */ /* time out all database entries */
for(i = 0; i < HTLEN; i++) for(i = 0; i < HTLEN; i++)
for(dp = ht[i]; dp; dp = dp->next) { for(dp = ht[i]; dp; dp = dp->next) {
dp->keep = 0; dp->mark = 0;
for(rp = dp->rr; rp; rp = rp->next) for(rp = dp->rr; rp; rp = rp->next)
if(rp->db) if(rp->db)
rp->expire = 0; rp->expire = 0;
@ -738,22 +732,28 @@ rrattach1(RR *new, int auth)
RR **l; RR **l;
RR *rp; RR *rp;
DN *dp; DN *dp;
ulong ttl;
assert(new->magic == RRmagic && !new->cached); assert(new->magic == RRmagic && !new->cached);
if(!new->db) {
/*
* try not to let responses expire before we
* can use them to complete this query, by extending
* past (or nearly past) expiration time.
*/
new->expire = new->ttl > now + Min? new->ttl: now + 10*Min;
} else
new->expire = now + Year;
dp = new->owner; dp = new->owner;
assert(dp != nil && dp->magic == DNmagic); assert(dp != nil && dp->magic == DNmagic);
new->auth |= auth; new->auth |= auth;
new->next = 0; new->next = 0;
/*
* try not to let responses expire before we
* can use them to complete this query, by extending
* past (or nearly past) expiration time.
*/
if(new->db)
ttl = Year;
else
ttl = new->ttl;
if(ttl <= Min)
ttl = 10*Min;
new->expire = now + ttl;
/* /*
* find first rr of the right type * find first rr of the right type
*/ */
@ -788,9 +788,8 @@ rrattach1(RR *new, int auth)
} }
/* all things equal, pick the newer one */ /* all things equal, pick the newer one */
else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){ else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
/* new drives out old */ /* old drives out new */
if (new->ttl <= rp->ttl && if((long)(rp->expire - new->expire) > 0) {
new->expire <= rp->expire) {
rrfree(new); rrfree(new);
return; return;
} }
@ -842,8 +841,8 @@ rrattach(RR *rp, int auth)
next = rp->next; next = rp->next;
rp->next = nil; rp->next = nil;
dp = rp->owner; dp = rp->owner;
/* avoid any outside spoofing; leave keepers alone */ /* avoid any outside spoofing */
if(cfg.cachedb && !rp->db && (dp->keep || inmyarea(dp->name))) if(cfg.cachedb && !rp->db && inmyarea(dp->name))
rrfree(rp); rrfree(rp);
else else
rrattach1(rp, auth); rrattach1(rp, auth);
@ -974,8 +973,8 @@ rrlookup(DN *dp, int type, int flag)
for(rp = dp->rr; rp; rp = rp->next){ for(rp = dp->rr; rp; rp = rp->next){
if(!rp->db) if(!rp->db)
if(rp->auth) if(rp->auth)
if(rp->ttl + 60 > now) if((long)(rp->expire - now) > 0)
if(tsame(type, rp->type)){ if(tsame(type, rp->type)){
if(flag == NOneg && rp->negative) if(flag == NOneg && rp->negative)
goto out; goto out;
last = rrcopy(rp, last); last = rrcopy(rp, last);
@ -987,7 +986,7 @@ rrlookup(DN *dp, int type, int flag)
/* try for a living unauthoritative network entry */ /* try for a living unauthoritative network entry */
for(rp = dp->rr; rp; rp = rp->next){ for(rp = dp->rr; rp; rp = rp->next){
if(!rp->db) if(!rp->db)
if(rp->ttl + 60 > now) if((long)(rp->expire - now) > 0)
if(tsame(type, rp->type)){ if(tsame(type, rp->type)){
if(flag == NOneg && rp->negative) if(flag == NOneg && rp->negative)
goto out; goto out;
@ -1822,7 +1821,9 @@ dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl)
for(rp = first; rp != nil; rp = nrp){ for(rp = first; rp != nil; rp = nrp){
nrp = rp->next; nrp = rp->next;
rp->next = nil; rp->next = nil;
dp = rp->owner;
rrattach(rp, Authoritative); rrattach(rp, Authoritative);
dnagenever(dp);
} }
} }

View file

@ -346,7 +346,7 @@ issuequery(Query *qp, char *name, int class, int depth, int recurse)
nsrp = randomize(rrlookup(nsdp, Tns, NOneg)); nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
/* if the entry timed out, ignore it */ /* if the entry timed out, ignore it */
if(nsrp && nsrp->ttl < now) if(nsrp && !nsrp->db && (long)(nsrp->expire - now) <= 0)
rrfreelistptr(&nsrp); rrfreelistptr(&nsrp);
if(nsrp){ if(nsrp){
@ -397,7 +397,7 @@ dnresolve1(char *name, int class, int type, Request *req, int depth,
} }
} else } else
/* cached entry must still be valid */ /* cached entry must still be valid */
if(rp->ttl > now) if((long)(rp->expire - now) > 0)
/* but Tall entries are special */ /* but Tall entries are special */
if(type != Tall || rp->query == Tall) { if(type != Tall || rp->query == Tall) {
noteinmem(); noteinmem();
@ -850,7 +850,7 @@ cacheneg(DN *dp, int type, int rcode, RR *soarr)
/* the attach can cause soarr to be freed so mine it now */ /* the attach can cause soarr to be freed so mine it now */
if(soarr != nil && soarr->soa != nil) if(soarr != nil && soarr->soa != nil)
ttl = soarr->soa->minttl+now; ttl = soarr->soa->minttl;
else else
ttl = 5*Min; ttl = 5*Min;
@ -893,11 +893,8 @@ mydnsquery(Query *qp, int medium, uchar *udppkt, int len)
rv = -1; rv = -1;
snprint(domain, sizeof(domain), "%I", udppkt); snprint(domain, sizeof(domain), "%I", udppkt);
if (myaddr(domain)) { if (myaddr(domain))
dnslog("mydnsquery: trying to send to myself (%s); bzzzt",
domain);
return rv; return rv;
}
switch (medium) { switch (medium) {
case Udp: case Udp:
nfd = dup(qp->udpfd, -1); nfd = dup(qp->udpfd, -1);
@ -1094,13 +1091,11 @@ procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p)
if(mp->an){ if(mp->an){
/* /*
* only use cname answer when returned. some dns servers * only use cname answer when returned. some dns servers
* attach spam address records which poisons the cache. * attach (potential) spam hint address records which poisons the cache.
*/ */
if((tp = rrremtype(&mp->an, Tcname)) != 0){ if((tp = rrremtype(&mp->an, Tcname)) != 0){
if(mp->an){ if(mp->an)
dnslog("removing spam %Q for %Q from %I", mp->an, tp, srcip);
rrfreelist(mp->an); rrfreelist(mp->an);
}
mp->an = tp; mp->an = tp;
} }
rrattach(mp->an, (mp->flags & Fauth) != 0); rrattach(mp->an, (mp->flags & Fauth) != 0);

View file

@ -194,13 +194,10 @@ struct DN
char *name; /* owner */ char *name; /* owner */
RR *rr; /* resource records off this name */ RR *rr; /* resource records off this name */
ulong referenced; /* time last referenced */ ulong referenced; /* time last referenced */
ulong lookuptime; /* last time we tried to get a better value */
/* refs was `char' but we've seen refs > 120, so go whole hog */
ulong refs; /* for mark and sweep */
ulong ordinal; ulong ordinal;
ushort class; /* RR class */ ushort class; /* RR class */
uchar keep; /* flag: never age this name */
uchar respcode; /* response code */ uchar respcode; /* response code */
uchar mark; /* for mark and sweep */
}; };
/* /*
@ -448,7 +445,7 @@ void db2cache(int);
void dnage(DN*); void dnage(DN*);
void dnageall(int); void dnageall(int);
void dnagedb(void); void dnagedb(void);
void dnagenever(DN *, int); void dnagenever(DN *);
void dnauthdb(void); void dnauthdb(void);
void dncheck(void); void dncheck(void);
void dndump(char*); void dndump(char*);

View file

@ -141,7 +141,7 @@ prettyrrfmt(Fmt *f)
p = buf; p = buf;
e = buf + sizeof(buf); e = buf + sizeof(buf);
p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name, p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
longtime(rp->db? rp->ttl: (rp->ttl - now)), longtime(rp->ttl),
rrname(rp->type, buf, sizeof buf)); rrname(rp->type, buf, sizeof buf));
if(rp->negative){ if(rp->negative){
@ -308,9 +308,10 @@ squirrelserveraddrs(void)
/* look up the resolver address first */ /* look up the resolver address first */
cfg.resolver = 0; cfg.resolver = 0;
debug = 0; debug = 0;
if(serveraddrs) if(serveraddrs){
rrfreelist(serveraddrs); rrfreelist(serveraddrs);
serveraddrs = nil; serveraddrs = nil;
}
rr = getdnsservers(Cin); rr = getdnsservers(Cin);
l = &serveraddrs; l = &serveraddrs;
for(rp = rr; rp != nil; rp = rp->next){ for(rp = rr; rp != nil; rp = rp->next){