📄 dblookup.c
字号:
* Look for a pair with the given attribute. look first on the same line, * then in the whole entry. */static Ndbtuple*look(Ndbtuple *entry, Ndbtuple *line, char *attr){ Ndbtuple *nt; /* first look on same line (closer binding) */ for(nt = line;;){ if(cistrcmp(attr, nt->attr) == 0) return nt; nt = nt->line; if(nt == line) break; } /* search whole tuple */ for(nt = entry; nt; nt = nt->entry) if(cistrcmp(attr, nt->attr) == 0) return nt; return 0;}static RR**linkrr(RR *rp, DN *dp, RR **l){ rp->owner = dp; rp->auth = 1; rp->db = 1; *l = rp; return &rp->next;}/* these are answered specially by the tcp version */static RR*doaxfr(Ndb *db, char *name){ USED(db, name); return 0;}/* * read the all the soa's from the database to determine area's. * this is only used when we're not caching the database. */static voiddbfile2area(Ndb *db){ Ndbtuple *t; if(debug) syslog(0, logfile, "rereading %s", db->file); Bseek(&db->b, 0, 0); while(t = ndbparse(db)){ ndbfree(t); }}/* * read the database into the cache */static voiddbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair){ RR *rp; Ndbtuple *t; static ulong ord; rp = 0; if(cistrcmp(pair->attr, "ip") == 0){ dp->ordinal = ord++; rp = addrrr(entry, pair); } else if(cistrcmp(pair->attr, "ns") == 0){ rp = nsrr(entry, pair); } else if(cistrcmp(pair->attr, "soa") == 0){ rp = soarr(entry, pair); addarea(dp, rp, pair); } else if(cistrcmp(pair->attr, "mx") == 0){ rp = mxrr(entry, pair); } else if(cistrcmp(pair->attr, "cname") == 0){ rp = cnamerr(entry, pair); } else if(cistrcmp(pair->attr, "nullrr") == 0){ rp = nullrr(entry, pair); } else if(cistrcmp(pair->attr, "txtrr") == 0){ rp = txtrr(entry, pair); } if(rp == 0) return; rp->owner = dp; rp->db = 1; t = look(entry, pair, "ttl"); if(t) rp->ttl = atoi(t->val); rrattach(rp, 0);}static voiddbtuple2cache(Ndbtuple *t){ Ndbtuple *et, *nt; DN *dp; for(et = t; et; et = et->entry){ if(strcmp(et->attr, "dom") == 0){ dp = dnlookup(et->val, Cin, 1); /* first same line */ for(nt = et->line; nt != et; nt = nt->line){ dbpair2cache(dp, t, nt); nt->ptr = 1; } /* then rest of entry */ for(nt = t; nt; nt = nt->entry){ if(nt->ptr == 0) dbpair2cache(dp, t, nt); nt->ptr = 0; } } }}static voiddbfile2cache(Ndb *db){ Ndbtuple *t; if(debug) syslog(0, logfile, "rereading %s", db->file); Bseek(&db->b, 0, 0); while(t = ndbparse(db)){ dbtuple2cache(t); ndbfree(t); }}voiddb2cache(int doit){ Ndb *ndb; Dir *d; ulong youngest, temp; static ulong lastcheck; static ulong lastyoungest; /* no faster than once every 2 minutes */ if(now < lastcheck + 2*Min && !doit) return; refresh_areas(owned); lock(&dblock); if(opendatabase() < 0){ unlock(&dblock); return; } /* * file may be changing as we are reading it, so loop till * mod times are consistent. * * we don't use the times in the ndb records because they may * change outside of refreshing our cached knowledge. */ for(;;){ lastcheck = now; youngest = 0; for(ndb = db; ndb; ndb = ndb->next){ /* the dirfstat avoids walking the mount table each time */ if((d = dirfstat(Bfildes(&ndb->b))) != nil || (d = dirstat(ndb->file)) != nil){ temp = d->mtime; /* ulong vs int crap */ if(temp > youngest) youngest = temp; free(d); } } if(!doit && youngest == lastyoungest) break; /* forget our area definition */ freearea(&owned); freearea(&delegated); /* reopen all the files (to get oldest for time stamp) */ for(ndb = db; ndb; ndb = ndb->next) ndbreopen(ndb); if(cachedb){ /* mark all db records as timed out */ dnagedb(); /* read in new entries */ for(ndb = db; ndb; ndb = ndb->next) dbfile2cache(ndb); /* mark as authentic anything in our domain */ dnauthdb(); /* remove old entries */ dnageall(1); } else { /* read all the soa's to get database defaults */ for(ndb = db; ndb; ndb = ndb->next) dbfile2area(ndb); } doit = 0; lastyoungest = youngest; createptrs(); } unlock(&dblock);}extern uchar ipaddr[IPaddrlen];/* * get all my xxx */Ndbtuple*lookupinfo(char *attr){ char buf[64]; char *a[2]; static Ndbtuple *t; snprint(buf, sizeof buf, "%I", ipaddr); a[0] = attr; lock(&dblock); if(opendatabase() < 0){ unlock(&dblock); return nil; } t = ndbipinfo(db, "ip", buf, a, 1); unlock(&dblock); return t;}char *localservers = "local#dns#servers";char *localserverprefix = "local#dns#server";/* * return non-zero is this is a bad delegation */intbaddelegation(RR *rp, RR *nsrp, uchar *addr){ Ndbtuple *nt; static Ndbtuple *t; if(t == nil) t = lookupinfo("dom"); if(t == nil) return 0; for(; rp; rp = rp->next){ if(rp->type != Tns) continue; /* see if delegation is looping */ if(nsrp) if(rp->owner != nsrp->owner) if(subsume(rp->owner->name, nsrp->owner->name) && strcmp(nsrp->owner->name, localservers) != 0){ syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr); return 1; } /* see if delegating to us what we don't own */ for(nt = t; nt != nil; nt = nt->entry) if(rp->host && cistrcmp(rp->host->name, nt->val) == 0) break; if(nt != nil && !inmyarea(rp->owner->name)){ syslog(0, logfile, "bad delegation %R from %I", rp, addr); return 1; } } return 0;}static voidaddlocaldnsserver(DN *dp, int class, char *ipaddr, int i){ DN *nsdp; RR *rp; char buf[32]; /* ns record for name server, make up an impossible name */ rp = rralloc(Tns); snprint(buf, sizeof(buf), "%s%d", localserverprefix, i); nsdp = dnlookup(buf, class, 1); rp->host = nsdp; rp->owner = dp; rp->local = 1; rp->db = 1; rp->ttl = 10*Min; rrattach(rp, 1); /* A record */ rp = rralloc(Ta); rp->ip = dnlookup(ipaddr, class, 1); rp->owner = nsdp; rp->local = 1; rp->db = 1; rp->ttl = 10*Min; rrattach(rp, 1);}/* * return list of dns server addresses to use when * acting just as a resolver. */RR*dnsservers(int class){ Ndbtuple *t, *nt; RR *nsrp; DN *dp; char *p; int i, n; char *buf, *args[5]; dp = dnlookup(localservers, class, 1); nsrp = rrlookup(dp, Tns, NOneg); if(nsrp != nil) return nsrp; p = getenv("DNSSERVER"); if(p != nil){ buf = estrdup(p); n = tokenize(buf, args, nelem(args)); for(i = 0; i < n; i++) addlocaldnsserver(dp, class, args[i], i); free(buf); } else { t = lookupinfo("@dns"); if(t == nil) return nil; i = 0; for(nt = t; nt != nil; nt = nt->entry){ addlocaldnsserver(dp, class, nt->val, i); i++; } ndbfree(t); } return rrlookup(dp, Tns, NOneg);}static voidaddlocaldnsdomain(DN *dp, int class, char *domain){ RR *rp; /* A record */ rp = rralloc(Tptr); rp->ptr = dnlookup(domain, class, 1); rp->owner = dp; rp->db = 1; rp->ttl = 10*Min; rrattach(rp, 1);}/* * return list of domains to use when resolving names without '.'s */RR*domainlist(int class){ Ndbtuple *t, *nt; RR *rp; DN *dp; dp = dnlookup("local#dns#domains", class, 1); rp = rrlookup(dp, Tptr, NOneg); if(rp != nil) return rp; t = lookupinfo("dnsdomain"); if(t == nil) return nil; for(nt = t; nt != nil; nt = nt->entry) addlocaldnsdomain(dp, class, nt->val); ndbfree(t); return rrlookup(dp, Tptr, NOneg);}char *v4ptrdom = ".in-addr.arpa";char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */char *attribs[] = { "ipmask", 0};/* * create ptrs that are in our areas */static voidcreateptrs(void){ int len, dlen, n; Area *s; char *f[40]; char buf[Domlen+1]; uchar net[IPaddrlen]; uchar mask[IPaddrlen]; char ipa[48]; Ndbtuple *t, *nt; dlen = strlen(v4ptrdom); for(s = owned; s; s = s->next){ len = strlen(s->soarr->owner->name); if(len <= dlen) continue; if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0) continue; /* get mask and net value */ strncpy(buf, s->soarr->owner->name, sizeof(buf)); buf[sizeof(buf)-1] = 0; n = getfields(buf, f, nelem(f), 0, "."); memset(mask, 0xff, IPaddrlen); ipmove(net, v4prefix); switch(n){ case 3: /* /8 */ net[IPv4off] = atoi(f[0]); mask[IPv4off+1] = 0; mask[IPv4off+2] = 0; mask[IPv4off+3] = 0; break; case 4: /* /16 */ net[IPv4off] = atoi(f[1]); net[IPv4off+1] = atoi(f[0]); mask[IPv4off+2] = 0; mask[IPv4off+3] = 0; break; case 5: /* /24 */ net[IPv4off] = atoi(f[2]); net[IPv4off+1] = atoi(f[1]); net[IPv4off+2] = atoi(f[0]); mask[IPv4off+3] = 0; break; case 6: /* rfc2317 */ net[IPv4off] = atoi(f[3]); net[IPv4off+1] = atoi(f[2]); net[IPv4off+2] = atoi(f[1]); net[IPv4off+3] = atoi(f[0]); sprint(ipa, "%I", net); t = ndbipinfo(db, "ip", ipa, attribs, 1); if(t == nil) /* could be a reverse with no forward */ continue; nt = look(t, t, "ipmask"); if(nt == nil){ /* we're confused */ ndbfree(t); continue; } parseipmask(mask, nt->val); n = 5; break; default: continue; } /* go through all domain entries looking for RR's in this network and create ptrs */ dnptr(net, mask, s->soarr->owner->name, 6-n, 0); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -