Ptrttl = 2*Min,
};
-static Ndb *db;
-static Lock dblock;
+static Ndb *db;
+static QLock dblock;
+
+static Ipifc *ipifcs;
+static QLock ipifclock;
static RR* addrrr(Ndbtuple*, Ndbtuple*);
static RR* cnamerr(Ndbtuple*, Ndbtuple*);
char netdbnm[256];
Ndb *xdb, *netdb;
- if (db)
+ if(db != nil)
return 0;
xdb = ndbopen(dbfile); /* /lib/ndb */
netdb->nohash = 1;
db = ndbcat(netdb, xdb); /* both */
- return db? 0: -1;
+ return db!=nil ? 0: -1;
}
/*
dblookup(char *name, int class, int type, int auth, int ttl)
{
int err;
- char *wild;
- char buf[256];
+ char buf[Domlen], *wild;
RR *rp, *tp;
DN *dp, *ndp;
return rp;
}
- lock(&dblock);
- dp = dnlookup(name, class, 1);
+ qlock(&dblock);
+ dp = idnlookup(name, class, 1);
if(opendatabase() < 0)
goto out;
/* walk the domain name trying the wildcard '*' at each position */
for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
snprint(buf, sizeof buf, "*%s", wild);
- ndp = dnlookup(buf, class, 1);
+ ndp = idnlookup(buf, class, 1);
if(ndp->rr)
err = 0;
if(cfg.cachedb)
* don't call it non-existent if it's not ours
* (unless we're a resolver).
*/
- if(err == Rname && (!inmyarea(name) || cfg.resolver))
+ if(err == Rname && (!inmyarea(dp->name) || cfg.resolver))
err = Rserver;
dp->respcode = err;
}
- unlock(&dblock);
+ qunlock(&dblock);
return rp;
}
return (t? strtoul(t->val, 0, 10): def);
}
+static void
+mklowcase(char *cp)
+{
+ Rune r;
+
+ while(*cp != 0){
+ chartorune(&r, cp);
+ r = tolowerrune(r);
+ cp += runetochar(cp, &r);
+ }
+}
+
/*
* lookup an RR in the network database
*/
case Tixfr:
return doaxfr(db, name);
default:
-// dnslog("dnlookup1(%s) bad type", name);
+// dnslog("dblookup1(%s) bad type", name);
return nil;
}
*/
t = nil;
nstrcpy(dname, name, sizeof dname);
- free(ndbgetvalue(db, &s, "dom", dname, attr, &t));
- if(t == nil && strchr(dname, '.') == nil)
- free(ndbgetvalue(db, &s, "sys", dname, attr, &t));
- if(t == nil) {
- char *cp;
-
- /* try lower case */
- for(cp = dname; *cp; cp++)
- if(isupper(*cp)) {
- for(; *cp; cp++)
- *cp = tolower(*cp);
- free(ndbgetvalue(db, &s, "dom", dname, attr, &t));
- if(t == nil && strchr(dname, '.') == nil)
- free(ndbgetvalue(db, &s, "sys", dname, attr, &t));
- break;
+ for(x=0; x<4; x++){
+ switch(x){
+ case 1: /* try unicode */
+ if(idn2utf(name, dname, sizeof dname) < 0){
+ nstrcpy(dname, name, sizeof dname);
+ continue;
}
+ if(strcmp(name, dname) == 0)
+ continue;
+ break;
+ case 3: /* try ascii (lower case) */
+ if(utf2idn(name, dname, sizeof dname) < 0)
+ continue;
+ case 2:
+ mklowcase(dname);
+ if(strcmp(name, dname) == 0)
+ continue;
+ break;
+ }
+ for(nt = ndbsearch(db, &s, "dom", dname); nt != nil; nt = ndbsnext(&s, "dom", dname)) {
+ if(ndbfindattr(nt, s.t, attr) == nil) {
+ ndbfree(nt);
+ continue;
+ }
+ t = ndbconcatenate(t, ndbreorder(nt, s.t));
+ }
+ if(t == nil && strchr(dname, '.') == nil) {
+ for(nt = ndbsearch(db, &s, "sys", dname); nt != nil; nt = ndbsnext(&s, "sys", dname)) {
+ if(ndbfindattr(nt, s.t, attr) == nil) {
+ ndbfree(nt);
+ continue;
+ }
+ t = ndbconcatenate(t, ndbreorder(nt, s.t));
+ }
+ }
+ s.t = t;
+ if(t != nil)
+ break;
}
+
if(t == nil) {
-// dnslog("dnlookup1(%s) name not found", name);
+// dnslog("dblookup1(%s) name not found", name);
return nil;
}
+
/* search whole entry for default domain name */
for(nt = t; nt; nt = nt->entry)
if(strcmp(nt->attr, "dom") == 0){
nstrcpy(dname, nt->val, sizeof dname);
found = 1;
}
- if(strcmp(attr, nt->attr) == 0){
- rp = (*f)(t, nt);
+ if(strcmp(attr, nt->attr) == 0 && (rp = (*f)(t, nt)) != nil){
rp->auth = auth;
rp->db = 1;
if(ttl)
rp->ttl = ttl;
if(dp == nil)
- dp = dnlookup(dname, Cin, 1);
+ dp = idnlookup(dname, Cin, 1);
rp->owner = dp;
*l = rp;
l = &rp->next;
/* search whole entry */
for(nt = t; nt; nt = nt->entry)
- if(nt->ptr == 0 && strcmp(attr, nt->attr) == 0){
- rp = (*f)(t, nt);
+ if(nt->ptr == 0 && strcmp(attr, nt->attr) == 0 && (rp = (*f)(t, nt)) != nil){
+ rp->auth = auth;
rp->db = 1;
if(ttl)
rp->ttl = ttl;
- rp->auth = auth;
if(dp == nil)
- dp = dnlookup(dname, Cin, 1);
+ dp = idnlookup(dname, Cin, 1);
rp->owner = dp;
*l = rp;
l = &rp->next;
}
ndbfree(t);
-// dnslog("dnlookup1(%s) -> %#p", name, list);
+// dnslog("dblookup1(%s) -> %#p", name, list);
return list;
}
* make various types of resource records from a database entry
*/
static RR*
-addrrr(Ndbtuple *entry, Ndbtuple *pair)
+addrrr(Ndbtuple*, Ndbtuple *pair)
{
RR *rp;
- uchar addr[IPaddrlen];
+ uchar ip[IPaddrlen];
- USED(entry);
- parseip(addr, pair->val);
- if(isv4(addr))
- rp = rralloc(Ta);
- else
- rp = rralloc(Taaaa);
- rp->ip = dnlookup(pair->val, Cin, 1);
+ if(parseip(ip, pair->val) == -1)
+ return nil;
+ rp = rralloc(isv4(ip) ? Ta : Taaaa);
+ rp->ip = ipalookup(ip, Cin, 1);
return rp;
}
static RR*
-nullrr(Ndbtuple *entry, Ndbtuple *pair)
+nullrr(Ndbtuple*, Ndbtuple *pair)
{
RR *rp;
- USED(entry);
rp = rralloc(Tnull);
rp->null->data = (uchar*)estrdup(pair->val);
rp->null->dlen = strlen((char*)rp->null->data);
* <= 255 byte ones.
*/
static RR*
-txtrr(Ndbtuple *entry, Ndbtuple *pair)
+txtrr(Ndbtuple*, Ndbtuple *pair)
{
RR *rp;
Txt *t, **l;
int i, len, sofar;
- USED(entry);
rp = rralloc(Ttxt);
l = &rp->txt;
rp->txt = nil;
return rp;
}
static RR*
-cnamerr(Ndbtuple *entry, Ndbtuple *pair)
+cnamerr(Ndbtuple*, Ndbtuple *pair)
{
RR *rp;
- USED(entry);
rp = rralloc(Tcname);
- rp->host = dnlookup(pair->val, Cin, 1);
+ rp->host = idnlookup(pair->val, Cin, 1);
return rp;
}
static RR*
RR *rp;
rp = rralloc(Tmx);
- rp->host = dnlookup(pair->val, Cin, 1);
+ rp->host = idnlookup(pair->val, Cin, 1);
rp->pref = intval(entry, pair, "pref", 1);
return rp;
}
Ndbtuple *t;
rp = rralloc(Tns);
- rp->host = dnlookup(pair->val, Cin, 1);
+ rp->host = idnlookup(pair->val, Cin, 1);
t = look(entry, pair, "soa");
if(t && t->val[0] == 0)
rp->local = 1;
return rp;
}
static RR*
-ptrrr(Ndbtuple *entry, Ndbtuple *pair)
+ptrrr(Ndbtuple*, Ndbtuple *pair)
{
RR *rp;
- USED(entry);
rp = rralloc(Tns);
rp->ptr = dnlookup(pair->val, Cin, 1);
return rp;
ns = look(entry, pair, "ns");
if(ns == nil)
ns = look(entry, pair, "dom");
- rp->host = dnlookup(ns->val, Cin, 1);
+ rp->host = idnlookup(ns->val, Cin, 1);
/* accept all of:
* mbox=person
p = strchr(mb->val, '@');
if(p != nil)
*p = '.';
- rp->rmb = dnlookup(mb->val, Cin, 1);
+ rp->rmb = idnlookup(mb->val, Cin, 1);
} else {
snprint(mailbox, sizeof mailbox, "%s.%s",
mb->val, ns->val);
- rp->rmb = dnlookup(mailbox, Cin, 1);
+ rp->rmb = idnlookup(mailbox, Cin, 1);
}
else {
snprint(mailbox, sizeof mailbox, "postmaster.%s", ns->val);
- rp->rmb = dnlookup(mailbox, Cin, 1);
+ rp->rmb = idnlookup(mailbox, Cin, 1);
}
/*
RR *rp;
rp = rralloc(Tsrv);
- rp->host = dnlookup(pair->val, Cin, 1);
+ rp->host = idnlookup(pair->val, Cin, 1);
rp->srv->pri = intval(entry, pair, "pri", 0);
rp->srv->weight = intval(entry, pair, "weight", 0);
/* TODO: translate service name to port # */
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)
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 void
-dbfile2area(Ndb *db)
-{
- Ndbtuple *t;
-
- if(debug)
- dnslog("rereading %s", db->file);
- Bseek(&db->b, 0, 0);
- while(t = ndbparse(db))
- ndbfree(t);
-}
-
/*
* read the database into the cache
*/
for(et = t; et; et = et->entry)
if(strcmp(et->attr, "dom") == 0){
- dp = dnlookup(et->val, Cin, 1);
+ dp = idnlookup(et->val, Cin, 1);
/* first same line */
for(nt = et->line; nt != et; nt = nt->line){
refresh_areas(owned);
- lock(&dblock);
-
+ qlock(&dblock);
if(opendatabase() < 0){
- unlock(&dblock);
+ qunlock(&dblock);
return;
}
+ qlock(&ipifclock);
+ ipifcs = readipifc(mntpt, ipifcs, -1);
+ qunlock(&ipifclock);
+
/*
* file may be changing as we are reading it, so loop till
* mod times are consistent.
/* reload straddle-server configuration */
loaddomsrvs();
- if(cfg.cachedb){
- /* mark all db records as timed out */
- dnagedb();
+ /* mark all db records as timed out */
+ dnagedb();
+ if(cfg.cachedb){
/* read in new entries */
for(ndb = db; ndb; ndb = ndb->next)
dbfile2cache(ndb);
+ }
- /* mark as authoritative anything in our domain */
- dnauthdb();
+ /*
+ * mark as authoritative anything in our domain,
+ * delete timed out db records
+ */
+ 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);
+ /* remove old entries */
+ dnageall(1);
doit = 0;
lastyoungest = youngest;
createptrs();
}
- unlock(&dblock);
+ qunlock(&dblock);
}
extern char mntpt[Maxpath]; /* net mountpoint */
-static uchar ipaddr[IPaddrlen]; /* my ip address */
/*
* get all my xxx
Ndbtuple*
lookupinfo(char *attr)
{
- char buf[64];
- char *a[2];
- Ndbtuple *t;
-
- if(ipcmp(ipaddr, IPnoaddr) == 0)
- if(myipaddr(ipaddr, mntpt) < 0)
- return nil;
-
- snprint(buf, sizeof buf, "%I", ipaddr);
- a[0] = attr;
+ Ndbtuple *t, *nt;
+ char ip[64];
+ Ipifc *ifc;
+ Iplifc *lifc;
- lock(&dblock);
+ t = nil;
+ qlock(&dblock);
if(opendatabase() < 0){
- unlock(&dblock);
+ qunlock(&dblock);
return nil;
}
- t = ndbipinfo(db, "ip", buf, a, 1);
- unlock(&dblock);
- return t;
-}
+ qlock(&ipifclock);
+ if(ipifcs == nil)
+ ipifcs = readipifc(mntpt, ipifcs, -1);
+ for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
+ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
+ snprint(ip, sizeof(ip), "%I", lifc->ip);
+ nt = ndbipinfo(db, "ip", ip, &attr, 1);
+ t = ndbconcatenate(t, nt);
+ }
+ }
+ qunlock(&ipifclock);
+ qunlock(&dblock);
-char *localservers = "local#dns#servers";
-char *localserverprefix = "local#dns#server";
+ return ndbdedup(t);
+}
/*
* return non-zero if this is a bad delegation
}
int
-myaddr(char *addr)
+myip(uchar *ip)
{
- char *line, *sp;
- char buf[64];
- Biobuf *bp;
-
- if(ipcmp(ipaddr, IPnoaddr) == 0)
- if(myipaddr(ipaddr, mntpt) < 0)
- return -1;
-
- snprint(buf, sizeof buf, "%I", ipaddr);
- if (strcmp(addr, buf) == 0) {
- dnslog("rejecting my ip %s as local dns server", addr);
- return 1;
- }
-
- snprint(buf, sizeof buf, "%s/ipselftab", mntpt);
- bp = Bopen(buf, OREAD);
- if (bp != nil) {
- while ((line = Brdline(bp, '\n')) != nil) {
- line[Blinelen(bp) - 1] = '\0';
- sp = strchr(line, ' ');
- if (sp) {
- *sp = '\0';
- if (strcmp(addr, line) == 0) {
- dnslog("rejecting my ip %s as local dns server",
- addr);
- return 1;
- }
+ Ipifc *ifc;
+ Iplifc *lifc;
+
+ qlock(&ipifclock);
+ for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
+ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
+ if(ipcmp(ip, lifc->ip) == 0){
+ qunlock(&ipifclock);
+ return 1;
}
}
- Bterm(bp);
}
+ qunlock(&ipifclock);
+
return 0;
}
-static char *locdns[20];
-static QLock locdnslck;
-
static void
-addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
+addlocaldnsserver(DN *dp, int class, char *addr, int i)
{
- int n;
- DN *nsdp;
- RR *rp;
- char buf[32];
uchar ip[IPaddrlen];
+ DN *nsdp, *ipdp;
+ RR *rp, *tp;
+ int type, n;
+ char buf[32];
+
+ if(parseip(ip, addr) == -1 || ipcmp(ip, IPnoaddr) == 0){
+ dnslog("rejecting bad ip %s as local dns server", addr);
+ return;
+ }
/* reject our own ip addresses so we don't query ourselves via udp */
- if (myaddr(ipaddr))
+ if(myip(ip)){
+ dnslog("rejecting my ip %I as local dns server", ip);
return;
+ }
- qlock(&locdnslck);
- for (n = 0; n < i && n < nelem(locdns) && locdns[n]; n++)
- if (strcmp(locdns[n], ipaddr) == 0) {
- dnslog("rejecting duplicate local dns server ip %s",
- ipaddr);
- qunlock(&locdnslck);
- return;
+ /* A or AAAA record */
+ type = isv4(ip) ? Ta : Taaaa;
+ ipdp = ipalookup(ip, class, 1);
+
+ /* check duplicate ip */
+ for(n = 0; n < i; n++){
+ snprint(buf, sizeof buf, "local#dns#server%d", n);
+ nsdp = dnlookup(buf, class, 0);
+ if(nsdp == nil)
+ continue;
+ rp = rrlookup(nsdp, type, NOneg);
+ for(tp = rp; tp != nil; tp = tp->next){
+ if(tp->ip == ipdp){
+ dnslog("rejecting duplicate local dns server ip %I", ip);
+ rrfreelist(rp);
+ return;
+ }
}
- if (n < nelem(locdns))
- if (locdns[n] == nil || ++n < nelem(locdns))
- locdns[n] = strdup(ipaddr); /* remember 1st few local ns */
- qunlock(&locdnslck);
+ rrfreelist(rp);
+ }
+
+ snprint(buf, sizeof buf, "local#dns#server%d", i);
+ nsdp = dnlookup(buf, class, 1);
/* 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; /* e.g., local#dns#servers */
rp->local = 1;
rrattach(rp, Authoritative); /* will not attach rrs in my area */
dnagenever(dp);
- /* A or AAAA record */
- if (parseip(ip, ipaddr) >= 0 && isv4(ip))
- rp = rralloc(Ta);
- else
- rp = rralloc(Taaaa);
- rp->ip = dnlookup(ipaddr, class, 1);
+ rp = rralloc(type);
+ rp->ip = ipdp;
rp->owner = nsdp;
rp->local = 1;
rp->db = 1;
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 %I", buf, ip);
}
/*
{
int i, n;
char *p;
- char *args[5];
+ char *args[16];
Ndbtuple *t, *nt;
RR *nsrp;
DN *dp;
- dp = dnlookup(localservers, class, 1);
+ dp = dnlookup("local#dns#servers", class, 1);
nsrp = rrlookup(dp, Tns, NOneg);
if(nsrp != nil)
return nsrp;
if (dom[0] == '\0' || strcmp(dom, ".") == 0) /* dns root? */
return 1; /* hack for initialisation */
- lock(&dblock);
+ qlock(&dblock);
if (indoms == nil)
loaddomsrvs();
if (indoms == nil) {
- unlock(&dblock);
+ qunlock(&dblock);
return 1; /* no "inside-dom" sys, try inside nameservers */
}
break;
}
}
- unlock(&dblock);
+ qunlock(&dblock);
return rv;
}
for (t = innmsrvs; t != nil; t = t->entry)
if (strcmp(t->attr, "ip") == 0) {
- parseip(ipa, t->val);
- if (memcmp(ipa, ip, sizeof ipa) == 0)
+ if (parseip(ipa, t->val) != -1 && ipcmp(ipa, ip) == 0)
return 1;
}
return 0;
i = 0;
for (t = outnmsrvs; t != nil; t = t->entry)
if (strcmp(t->attr, "ip") == 0 && i++ == n) {
- parseip(ip, t->val);
+ if (parseip(ip, t->val) == -1)
+ return -1;
return 0;
}
return -1;