#include <bio.h>
#include <ndb.h>
#include <ip.h>
+#include <ctype.h>
#include "dns.h"
enum {
* 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.
*/
- Ptrttl = 120,
+ Ptrttl = 2*Min,
};
static Ndb *db;
xdb = ndbopen(dbfile); /* /lib/ndb */
snprint(netdbnm, sizeof netdbnm, "%s/ndb", mntpt);
+ for(netdb = xdb; netdb; netdb = netdb->next)
+ if(strcmp(netdb->file, netdbnm) == 0){
+ db = xdb;
+ return 0;
+ }
+
netdb = ndbopen(netdbnm); /* /net/ndb */
if(netdb)
netdb->nohash = 1;
dblookup(char *name, int class, int type, int auth, int ttl)
{
int err;
- char *wild, *cp;
- char buf[256];
+ char buf[Domlen], *wild;
RR *rp, *tp;
DN *dp, *ndp;
- static int parallel;
- static int parfd[2];
- static char token[1];
/* so far only internet lookups are implemented */
if(class != Cin)
return 0;
err = Rname;
+ rp = nil;
if(type == Tall){
- lock(&dnlock);
- rp = nil;
for (type = Ta; type < Tall; type++)
if(implemented[type])
rrcat(&rp, dblookup(name, class, type, auth, ttl));
- unlock(&dnlock);
+
return rp;
}
- rp = nil;
-
lock(&dblock);
- dp = dnlookup(name, class, 1);
+ dp = idnlookup(name, class, 1);
if(opendatabase() < 0)
goto out;
if(rp)
goto out;
- /* try lower case version */
- for(cp = name; *cp; cp++)
- *cp = tolower(*cp);
- if(cfg.cachedb)
- rp = rrlookup(dp, type, NOneg);
- else
- rp = dblookup1(name, type, auth, ttl);
- if(rp)
- 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;
}
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;
}
/*
* find a matching entry in the database
*/
- t = nil;
- free(ndbgetvalue(db, &s, "dom", name, attr, &t));
+ nstrcpy(dname, name, sizeof dname);
+ for(x=0; x<4; x++){
+ switch(x){
+ case 1: /* try unicode */
+ if(idn2utf(name, dname, sizeof dname) == nil){
+ 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) == nil)
+ continue;
+ case 2:
+ mklowcase(dname);
+ if(strcmp(name, dname) == 0)
+ continue;
+ break;
+ }
+ t = nil;
+ 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)
+ break;
+ }
- /*
- * hack for local names
- */
- if(t == nil && strchr(name, '.') == nil)
- free(ndbgetvalue(db, &s, "sys", name, attr, &t));
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 */
- strncpy(dname, name, sizeof dname);
for(nt = t; nt; nt = nt->entry)
if(strcmp(nt->attr, "dom") == 0){
nstrcpy(dname, nt->val, sizeof dname);
nstrcpy(dname, nt->val, sizeof dname);
found = 1;
}
- if(cistrcmp(attr, nt->attr) == 0){
+ if(strcmp(attr, nt->attr) == 0){
rp = (*f)(t, nt);
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 && cistrcmp(attr, nt->attr) == 0){
+ if(nt->ptr == 0 && strcmp(attr, nt->attr) == 0){
rp = (*f)(t, nt);
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;
}
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;
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 # */
/* first look on same line (closer binding) */
for(nt = line;;){
- if(cistrcmp(attr, nt->attr) == 0)
+ if(strcmp(attr, nt->attr) == 0)
return nt;
nt = nt->line;
if(nt == line)
}
/* search whole tuple */
for(nt = entry; nt; nt = nt->entry)
- if(cistrcmp(attr, nt->attr) == 0)
+ if(strcmp(attr, nt->attr) == 0)
return nt;
return 0;
}
static ulong ord;
rp = 0;
- if(cistrcmp(pair->attr, "ip") == 0 ||
- cistrcmp(pair->attr, "ipv6") == 0){
+ if(strcmp(pair->attr, "ip") == 0 ||
+ strcmp(pair->attr, "ipv6") == 0) {
dp->ordinal = ord++;
rp = addrrr(entry, pair);
- } else if(cistrcmp(pair->attr, "ns") == 0)
+ }
+ else if(strcmp(pair->attr, "ns") == 0)
rp = nsrr(entry, pair);
- else if(cistrcmp(pair->attr, "soa") == 0) {
+ else if(strcmp(pair->attr, "soa") == 0) {
rp = soarr(entry, pair);
addarea(dp, rp, pair);
- } else if(cistrcmp(pair->attr, "mx") == 0)
+ }
+ else if(strcmp(pair->attr, "mx") == 0)
rp = mxrr(entry, pair);
- else if(cistrcmp(pair->attr, "srv") == 0)
+ else if(strcmp(pair->attr, "srv") == 0)
rp = srvrr(entry, pair);
- else if(cistrcmp(pair->attr, "cname") == 0)
+ else if(strcmp(pair->attr, "cname") == 0)
rp = cnamerr(entry, pair);
- else if(cistrcmp(pair->attr, "nullrr") == 0)
+ else if(strcmp(pair->attr, "nullrr") == 0)
rp = nullrr(entry, pair);
- else if(cistrcmp(pair->attr, "txtrr") == 0)
+ else if(strcmp(pair->attr, "txtrr") == 0)
rp = txtrr(entry, pair);
if(rp == nil)
return;
rp->owner = dp;
- dnagenever(dp, 1);
rp->db = 1;
rp->ttl = intval(entry, pair, "ttl", rp->ttl);
rrattach(rp, Notauthoritative);
+ dnagenever(dp);
}
static void
dbtuple2cache(Ndbtuple *t)
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){
unlock(&dblock);
}
-void
-dnforceage(void)
-{
- lock(&dblock);
- dnageall(1);
- unlock(&dblock);
-}
-
extern char mntpt[Maxpath]; /* net mountpoint */
static uchar ipaddr[IPaddrlen]; /* my ip address */
return t;
}
-char *localservers = "local#dns#servers";
-char *localserverprefix = "local#dns#server";
-
/*
* return non-zero if this is a bad delegation
*/
int
baddelegation(RR *rp, RR *nsrp, uchar *addr)
{
- Ndbtuple *nt;
static int whined;
static Ndbtuple *t;
+ Ndbtuple *nt;
- if(t == nil)
- t = lookupinfo("dom");
- if(t == nil)
+ if(rp->type != Tns)
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){
- dnslog("delegation loop %R -> %R from %I",
- nsrp, rp, addr);
- return 1;
- }
-
+ if(t == nil)
+ t = lookupinfo("dom");
+ if(t != nil){
/* 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)){
if (!whined) {
whined = 1;
- dnslog("bad delegation %R from %I; "
- "no further logging of them", rp, addr);
+ dnslog("bad delegation %R from %I/%s; "
+ "no further logging of them",
+ rp, addr, nsrp->host->name);
}
return 1;
}
}
-
return 0;
}
int
myaddr(char *addr)
{
- char *name, *line, *sp;
+ char *line, *sp;
char buf[64];
Biobuf *bp;
if(ipcmp(ipaddr, IPnoaddr) == 0)
- return -1;
+ if(myipaddr(ipaddr, mntpt) < 0)
+ return -1;
snprint(buf, sizeof buf, "%I", ipaddr);
if (strcmp(addr, buf) == 0) {
return 1;
}
- name = smprint("%s/ipselftab", mntpt);
- bp = Bopen(name, OREAD);
- free(name);
+ 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';
/* ns record for name server, make up an impossible name */
rp = rralloc(Tns);
- snprint(buf, sizeof buf, "%s%d", localserverprefix, i);
+ snprint(buf, sizeof buf, "local#dns#server%d", i);
nsdp = dnlookup(buf, class, 1);
rp->host = nsdp;
rp->owner = dp; /* e.g., local#dns#servers */
rp->local = 1;
rp->db = 1;
-// rp->ttl = 10*Min; /* seems too short */
- rp->ttl = (1UL<<31)-1;
+ rp->ttl = 10*Min;
rrattach(rp, Authoritative); /* will not attach rrs in my area */
+ dnagenever(dp);
/* A or AAAA record */
if (parseip(ip, ipaddr) >= 0 && isv4(ip))
rp->owner = nsdp;
rp->local = 1;
rp->db = 1;
-// rp->ttl = 10*Min; /* seems too short */
- rp->ttl = (1UL<<31)-1;
+ rp->ttl = 10*Min;
rrattach(rp, Authoritative); /* will not attach rrs in my area */
+ dnagenever(nsdp);
dnslog("added local dns server %s at %s", buf, ipaddr);
}
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;
rp->db = 1;
rp->ttl = 10*Min;
rrattach(rp, Authoritative);
+ dnagenever(dp);
}
/*
{
int len, dlen, n;
char *dom;
- char buf[Domlen+1], ipa[48];
+ char buf[Domlen], ipa[48];
char *f[40];
uchar net[IPaddrlen], mask[IPaddrlen];
Area *s;
continue;
/* get mask and net value */
- strncpy(buf, dom, sizeof buf);
- buf[sizeof buf-1] = 0;
+ nstrcpy(buf, dom, sizeof buf);
/* buf contains something like 178.204.in-addr.arpa (n==4) */
n = getfields(buf, f, nelem(f), 0, ".");
memset(mask, 0xff, IPaddrlen);
{
int len, dlen, i, n, pfxnibs;
char *dom;
- char buf[Domlen+1];
+ char buf[Domlen];
char *f[40];
uchar net[IPaddrlen], mask[IPaddrlen];
uchar nibnet[IPaddrlen*2], nibmask[IPaddrlen*2];
continue;
/* get mask and net value */
- strncpy(buf, dom, sizeof buf);
- buf[sizeof buf-1] = 0;
+ nstrcpy(buf, dom, sizeof buf);
/* buf contains something like 2.0.0.2.ip6.arpa (n==6) */
n = getfields(buf, f, nelem(f), 0, ".");
pfxnibs = n - 2; /* 2 for .ip6.arpa */
if (!cfg.inside || !cfg.straddle || !cfg.serve)
return 1;
+ if (dom[0] == '\0' || strcmp(dom, ".") == 0) /* dns root? */
+ return 1; /* hack for initialisation */
lock(&dblock);
if (indoms == nil)
loaddomsrvs();
if (indoms == nil) {
unlock(&dblock);
- return 1; /* no "inside" sys, try inside nameservers */
+ return 1; /* no "inside-dom" sys, try inside nameservers */
}
rv = 0;
return 0;
}
-uchar *
-outsidens(int n)
+int
+outsidensip(int n, uchar *ip)
{
int i;
Ndbtuple *t;
- static uchar ipa[IPaddrlen];
i = 0;
for (t = outnmsrvs; t != nil; t = t->entry)
if (strcmp(t->attr, "ip") == 0 && i++ == n) {
- parseip(ipa, t->val);
- return ipa;
+ parseip(ip, t->val);
+ return 0;
}
- return nil;
+ return -1;
}