xref: /plan9/sys/src/cmd/ndb/dblookup.c (revision d9924332ebdbff1ae6e4e81162ea52d38508aa08)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ndb.h>
57dd7cddfSDavid du Colombier #include <ip.h>
63e12c5d1SDavid du Colombier #include "dns.h"
73e12c5d1SDavid du Colombier 
8617c0e1eSDavid du Colombier enum {
9617c0e1eSDavid du Colombier 	Nibwidth = 4,
10617c0e1eSDavid du Colombier 	Nibmask = (1<<Nibwidth) - 1,
11617c0e1eSDavid du Colombier 	V6maxrevdomdepth = 128 / Nibwidth,	/* bits / bits-per-nibble */
12617c0e1eSDavid du Colombier 
130a12e455SDavid du Colombier 	/*
140a12e455SDavid du Colombier 	 * ttl for generated ptr records.  it was zero, which might seem
150a12e455SDavid du Colombier 	 * like a good idea, but some dns implementations seem to be
160a12e455SDavid du Colombier 	 * confused by a zero ttl, and instead of using the data and then
170a12e455SDavid du Colombier 	 * discarding the RR, they conclude that they don't have valid data.
180a12e455SDavid du Colombier 	 */
19410ea80bSDavid du Colombier 	Ptrttl = 120,
20617c0e1eSDavid du Colombier };
21617c0e1eSDavid du Colombier 
223e12c5d1SDavid du Colombier static Ndb *db;
23bd389b36SDavid du Colombier static Lock	dblock;
244f8f669cSDavid du Colombier 
254f8f669cSDavid du Colombier static RR*	addrrr(Ndbtuple*, Ndbtuple*);
264f8f669cSDavid du Colombier static RR*	cnamerr(Ndbtuple*, Ndbtuple*);
273ff48bf5SDavid du Colombier static void	createptrs(void);
284f8f669cSDavid du Colombier static RR*	dblookup1(char*, int, int, int);
294f8f669cSDavid du Colombier static RR*	doaxfr(Ndb*, char*);
304f8f669cSDavid du Colombier static Ndbtuple*look(Ndbtuple*, Ndbtuple*, char*);
314f8f669cSDavid du Colombier static RR*	mxrr(Ndbtuple*, Ndbtuple*);
324f8f669cSDavid du Colombier static RR*	nsrr(Ndbtuple*, Ndbtuple*);
334f8f669cSDavid du Colombier static RR*	nullrr(Ndbtuple*, Ndbtuple*);
344f8f669cSDavid du Colombier static RR*	ptrrr(Ndbtuple*, Ndbtuple*);
354f8f669cSDavid du Colombier static RR*	soarr(Ndbtuple*, Ndbtuple*);
364f8f669cSDavid du Colombier static RR*	srvrr(Ndbtuple*, Ndbtuple*);
374f8f669cSDavid du Colombier static RR*	txtrr(Ndbtuple*, Ndbtuple*);
38bd389b36SDavid du Colombier 
39219b2ee8SDavid du Colombier static int	implemented[Tall] =
40bd389b36SDavid du Colombier {
41219b2ee8SDavid du Colombier 	[Ta]		1,
424f8f669cSDavid du Colombier 	[Taaaa]		1,
437dd7cddfSDavid du Colombier 	[Tcname]	1,
444f8f669cSDavid du Colombier 	[Tmx]		1,
454f8f669cSDavid du Colombier 	[Tns]		1,
469a747e4fSDavid du Colombier 	[Tnull]		1,
474f8f669cSDavid du Colombier 	[Tptr]		1,
484f8f669cSDavid du Colombier 	[Tsoa]		1,
494f8f669cSDavid du Colombier 	[Tsrv]		1,
509a747e4fSDavid du Colombier 	[Ttxt]		1,
51219b2ee8SDavid du Colombier };
52bd389b36SDavid du Colombier 
534f8f669cSDavid du Colombier /* straddle server configuration */
544f8f669cSDavid du Colombier static Ndbtuple *indoms, *innmsrvs, *outnmsrvs;
554f8f669cSDavid du Colombier 
5657837e0bSDavid du Colombier static void
5757837e0bSDavid du Colombier nstrcpy(char *to, char *from, int len)
5857837e0bSDavid du Colombier {
5957837e0bSDavid du Colombier 	strncpy(to, from, len);
6057837e0bSDavid du Colombier 	to[len-1] = 0;
6157837e0bSDavid du Colombier }
6257837e0bSDavid du Colombier 
637dd7cddfSDavid du Colombier int
647dd7cddfSDavid du Colombier opendatabase(void)
657dd7cddfSDavid du Colombier {
664f8f669cSDavid du Colombier 	char netdbnm[256];
674f8f669cSDavid du Colombier 	Ndb *xdb, *netdb;
687dd7cddfSDavid du Colombier 
694f8f669cSDavid du Colombier 	if (db)
707dd7cddfSDavid du Colombier 		return 0;
714f8f669cSDavid du Colombier 
724f8f669cSDavid du Colombier 	xdb = ndbopen(dbfile);		/* /lib/ndb */
734f8f669cSDavid du Colombier 
744f8f669cSDavid du Colombier 	snprint(netdbnm, sizeof netdbnm, "%s/ndb", mntpt);
754f8f669cSDavid du Colombier 	netdb = ndbopen(netdbnm);	/* /net/ndb */
764f927735SDavid du Colombier 	if(netdb)
774f927735SDavid du Colombier 		netdb->nohash = 1;
784f8f669cSDavid du Colombier 
794f8f669cSDavid du Colombier 	db = ndbcat(netdb, xdb);	/* both */
804f8f669cSDavid du Colombier 	return db? 0: -1;
817dd7cddfSDavid du Colombier }
827dd7cddfSDavid du Colombier 
833e12c5d1SDavid du Colombier /*
843e12c5d1SDavid du Colombier  *  lookup an RR in the network database, look for matches
853e12c5d1SDavid du Colombier  *  against both the domain name and the wildcarded domain name.
863e12c5d1SDavid du Colombier  *
87bd389b36SDavid du Colombier  *  the lock makes sure only one process can be accessing the data
88bd389b36SDavid du Colombier  *  base at a time.  This is important since there's a lot of
89bd389b36SDavid du Colombier  *  shared state there.
90bd389b36SDavid du Colombier  *
917dd7cddfSDavid du Colombier  *  e.g. for x.research.bell-labs.com, first look for a match against
924f8f669cSDavid du Colombier  *       the x.research.bell-labs.com.  If nothing matches,
934f8f669cSDavid du Colombier  *	 try *.research.bell-labs.com.
943e12c5d1SDavid du Colombier  */
953e12c5d1SDavid du Colombier RR*
967dd7cddfSDavid du Colombier dblookup(char *name, int class, int type, int auth, int ttl)
973e12c5d1SDavid du Colombier {
986b0d5c8bSDavid du Colombier 	int err;
994f8f669cSDavid du Colombier 	char *wild, *cp;
1004f8f669cSDavid du Colombier 	char buf[256];
1014f8f669cSDavid du Colombier 	RR *rp, *tp;
1024f8f669cSDavid du Colombier 	DN *dp, *ndp;
103bd389b36SDavid du Colombier 	static int parallel;
104bd389b36SDavid du Colombier 	static int parfd[2];
105bd389b36SDavid du Colombier 	static char token[1];
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier 	/* so far only internet lookups are implemented */
1083e12c5d1SDavid du Colombier 	if(class != Cin)
1093e12c5d1SDavid du Colombier 		return 0;
1103e12c5d1SDavid du Colombier 
1117dd7cddfSDavid du Colombier 	err = Rname;
1127dd7cddfSDavid du Colombier 
113219b2ee8SDavid du Colombier 	if(type == Tall){
114530fef66SDavid du Colombier 		lock(&dnlock);
1154f8f669cSDavid du Colombier 		rp = nil;
1167dd7cddfSDavid du Colombier 		for (type = Ta; type < Tall; type++)
117530fef66SDavid du Colombier 			if(implemented[type])
1183ff48bf5SDavid du Colombier 				rrcat(&rp, dblookup(name, class, type, auth, ttl));
119530fef66SDavid du Colombier 		unlock(&dnlock);
120219b2ee8SDavid du Colombier 		return rp;
121219b2ee8SDavid du Colombier 	}
122bd389b36SDavid du Colombier 
1234f8f669cSDavid du Colombier 	rp = nil;
1244f8f669cSDavid du Colombier 
125219b2ee8SDavid du Colombier 	lock(&dblock);
1263ff48bf5SDavid du Colombier 	dp = dnlookup(name, class, 1);
1274f8f669cSDavid du Colombier 
1287dd7cddfSDavid du Colombier 	if(opendatabase() < 0)
129bd389b36SDavid du Colombier 		goto out;
1307dd7cddfSDavid du Colombier 	if(dp->rr)
1317dd7cddfSDavid du Colombier 		err = 0;
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	/* first try the given name */
1344f8f669cSDavid du Colombier 	if(cfg.cachedb)
1357dd7cddfSDavid du Colombier 		rp = rrlookup(dp, type, NOneg);
1367dd7cddfSDavid du Colombier 	else
1373ff48bf5SDavid du Colombier 		rp = dblookup1(name, type, auth, ttl);
1383e12c5d1SDavid du Colombier 	if(rp)
139bd389b36SDavid du Colombier 		goto out;
1403e12c5d1SDavid du Colombier 
1413e12c5d1SDavid du Colombier 	/* try lower case version */
1423e12c5d1SDavid du Colombier 	for(cp = name; *cp; cp++)
1433e12c5d1SDavid du Colombier 		*cp = tolower(*cp);
1444f8f669cSDavid du Colombier 	if(cfg.cachedb)
1457dd7cddfSDavid du Colombier 		rp = rrlookup(dp, type, NOneg);
1467dd7cddfSDavid du Colombier 	else
1473ff48bf5SDavid du Colombier 		rp = dblookup1(name, type, auth, ttl);
1483e12c5d1SDavid du Colombier 	if(rp)
149bd389b36SDavid du Colombier 		goto out;
1503e12c5d1SDavid du Colombier 
1517dd7cddfSDavid du Colombier 	/* walk the domain name trying the wildcard '*' at each position */
1527dd7cddfSDavid du Colombier 	for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
1534f8f669cSDavid du Colombier 		snprint(buf, sizeof buf, "*%s", wild);
1547dd7cddfSDavid du Colombier 		ndp = dnlookup(buf, class, 1);
1557dd7cddfSDavid du Colombier 		if(ndp->rr)
1567dd7cddfSDavid du Colombier 			err = 0;
1574f8f669cSDavid du Colombier 		if(cfg.cachedb)
1587dd7cddfSDavid du Colombier 			rp = rrlookup(ndp, type, NOneg);
1597dd7cddfSDavid du Colombier 		else
1607dd7cddfSDavid du Colombier 			rp = dblookup1(buf, type, auth, ttl);
1617dd7cddfSDavid du Colombier 		if(rp)
1627dd7cddfSDavid du Colombier 			break;
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier out:
1657dd7cddfSDavid du Colombier 	/* add owner to uncached records */
1664f8f669cSDavid du Colombier 	if(rp)
1673e12c5d1SDavid du Colombier 		for(tp = rp; tp; tp = tp->next)
1683e12c5d1SDavid du Colombier 			tp->owner = dp;
1694f8f669cSDavid du Colombier 	else {
170a41547ffSDavid du Colombier 		/*
171a41547ffSDavid du Colombier 		 * don't call it non-existent if it's not ours
172a41547ffSDavid du Colombier 		 * (unless we're a resolver).
173a41547ffSDavid du Colombier 		 */
174a41547ffSDavid du Colombier 		if(err == Rname && (!inmyarea(name) || cfg.resolver))
175271b8d73SDavid du Colombier 			err = Rserver;
1764f8f669cSDavid du Colombier 		dp->respcode = err;
177fb7f0c93SDavid du Colombier 	}
1787dd7cddfSDavid du Colombier 
179bd389b36SDavid du Colombier 	unlock(&dblock);
1803e12c5d1SDavid du Colombier 	return rp;
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier 
1834f8f669cSDavid du Colombier static ulong
1844f8f669cSDavid du Colombier intval(Ndbtuple *entry, Ndbtuple *pair, char *attr, ulong def)
1854f8f669cSDavid du Colombier {
1864f8f669cSDavid du Colombier 	Ndbtuple *t = look(entry, pair, attr);
1874f8f669cSDavid du Colombier 
1884f8f669cSDavid du Colombier 	return (t? strtoul(t->val, 0, 10): def);
1894f8f669cSDavid du Colombier }
1904f8f669cSDavid du Colombier 
1913e12c5d1SDavid du Colombier /*
1923e12c5d1SDavid du Colombier  *  lookup an RR in the network database
1933e12c5d1SDavid du Colombier  */
1943e12c5d1SDavid du Colombier static RR*
1957dd7cddfSDavid du Colombier dblookup1(char *name, int type, int auth, int ttl)
1963e12c5d1SDavid du Colombier {
1973e12c5d1SDavid du Colombier 	Ndbtuple *t, *nt;
1983e12c5d1SDavid du Colombier 	RR *rp, *list, **l;
1993e12c5d1SDavid du Colombier 	Ndbs s;
20057837e0bSDavid du Colombier 	char dname[Domlen];
2013e12c5d1SDavid du Colombier 	char *attr;
2023e12c5d1SDavid du Colombier 	DN *dp;
2033e12c5d1SDavid du Colombier 	RR *(*f)(Ndbtuple*, Ndbtuple*);
2047dd7cddfSDavid du Colombier 	int found, x;
2053e12c5d1SDavid du Colombier 
2064f8f669cSDavid du Colombier 	dp = nil;
2073e12c5d1SDavid du Colombier 	switch(type){
2087dd7cddfSDavid du Colombier 	case Tptr:
2097dd7cddfSDavid du Colombier 		attr = "ptr";
2107dd7cddfSDavid du Colombier 		f = ptrrr;
2117dd7cddfSDavid du Colombier 		break;
2123e12c5d1SDavid du Colombier 	case Ta:
2133e12c5d1SDavid du Colombier 		attr = "ip";
2143e12c5d1SDavid du Colombier 		f = addrrr;
2153e12c5d1SDavid du Colombier 		break;
216*d9924332SDavid du Colombier 	case Taaaa:
217*d9924332SDavid du Colombier 		attr = "ipv6";
218*d9924332SDavid du Colombier 		f = addrrr;
219*d9924332SDavid du Colombier 		break;
2209a747e4fSDavid du Colombier 	case Tnull:
2219a747e4fSDavid du Colombier 		attr = "nullrr";
2229a747e4fSDavid du Colombier 		f = nullrr;
2239a747e4fSDavid du Colombier 		break;
2243e12c5d1SDavid du Colombier 	case Tns:
2253e12c5d1SDavid du Colombier 		attr = "ns";
2263e12c5d1SDavid du Colombier 		f = nsrr;
2273e12c5d1SDavid du Colombier 		break;
2283e12c5d1SDavid du Colombier 	case Tsoa:
2293e12c5d1SDavid du Colombier 		attr = "soa";
2303e12c5d1SDavid du Colombier 		f = soarr;
2313e12c5d1SDavid du Colombier 		break;
2324f8f669cSDavid du Colombier 	case Tsrv:
2334f8f669cSDavid du Colombier 		attr = "srv";
2344f8f669cSDavid du Colombier 		f = srvrr;
2354f8f669cSDavid du Colombier 		break;
2363e12c5d1SDavid du Colombier 	case Tmx:
2373e12c5d1SDavid du Colombier 		attr = "mx";
2383e12c5d1SDavid du Colombier 		f = mxrr;
2393e12c5d1SDavid du Colombier 		break;
2407dd7cddfSDavid du Colombier 	case Tcname:
2417dd7cddfSDavid du Colombier 		attr = "cname";
2427dd7cddfSDavid du Colombier 		f = cnamerr;
2437dd7cddfSDavid du Colombier 		break;
2447dd7cddfSDavid du Colombier 	case Taxfr:
2457dd7cddfSDavid du Colombier 	case Tixfr:
2467dd7cddfSDavid du Colombier 		return doaxfr(db, name);
2473e12c5d1SDavid du Colombier 	default:
2484f8f669cSDavid du Colombier //		dnslog("dnlookup1(%s) bad type", name);
2497dd7cddfSDavid du Colombier 		return nil;
2503e12c5d1SDavid du Colombier 	}
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier 	/*
2533e12c5d1SDavid du Colombier 	 *  find a matching entry in the database
2543e12c5d1SDavid du Colombier 	 */
2554f8f669cSDavid du Colombier 	t = nil;
25657837e0bSDavid du Colombier 	free(ndbgetvalue(db, &s, "dom", name, attr, &t));
257219b2ee8SDavid du Colombier 
258219b2ee8SDavid du Colombier 	/*
259219b2ee8SDavid du Colombier 	 *  hack for local names
260219b2ee8SDavid du Colombier 	 */
2614f8f669cSDavid du Colombier 	if(t == nil && strchr(name, '.') == nil)
26257837e0bSDavid du Colombier 		free(ndbgetvalue(db, &s, "sys", name, attr, &t));
2634f8f669cSDavid du Colombier 	if(t == nil) {
2644f8f669cSDavid du Colombier //		dnslog("dnlookup1(%s) name not found", name);
2657dd7cddfSDavid du Colombier 		return nil;
2664f8f669cSDavid du Colombier 	}
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier 	/* search whole entry for default domain name */
26957837e0bSDavid du Colombier 	strncpy(dname, name, sizeof dname);
2707dd7cddfSDavid du Colombier 	for(nt = t; nt; nt = nt->entry)
2717dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "dom") == 0){
27257837e0bSDavid du Colombier 			nstrcpy(dname, nt->val, sizeof dname);
2737dd7cddfSDavid du Colombier 			break;
2747dd7cddfSDavid du Colombier 		}
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 	/* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
2774f8f669cSDavid du Colombier 	x = intval(t, s.t, "ttl", 0);
2787dd7cddfSDavid du Colombier 	if(x > ttl)
2797dd7cddfSDavid du Colombier 		ttl = x;
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier 	/* default ttl is one day */
2827dd7cddfSDavid du Colombier 	if(ttl < 0)
2837dd7cddfSDavid du Colombier 		ttl = DEFTTL;
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier 	/*
2863e12c5d1SDavid du Colombier 	 *  The database has 2 levels of precedence; line and entry.
2873e12c5d1SDavid du Colombier 	 *  Pairs on the same line bind tighter than pairs in the
2883e12c5d1SDavid du Colombier 	 *  same entry, so we search the line first.
2893e12c5d1SDavid du Colombier 	 */
2907dd7cddfSDavid du Colombier 	found = 0;
2913e12c5d1SDavid du Colombier 	list = 0;
2923e12c5d1SDavid du Colombier 	l = &list;
2933e12c5d1SDavid du Colombier 	for(nt = s.t;; ){
2947dd7cddfSDavid du Colombier 		if(found == 0 && strcmp(nt->attr, "dom") == 0){
29557837e0bSDavid du Colombier 			nstrcpy(dname, nt->val, sizeof dname);
2967dd7cddfSDavid du Colombier 			found = 1;
2977dd7cddfSDavid du Colombier 		}
2983e12c5d1SDavid du Colombier 		if(cistrcmp(attr, nt->attr) == 0){
2993e12c5d1SDavid du Colombier 			rp = (*f)(t, nt);
3003e12c5d1SDavid du Colombier 			rp->auth = auth;
3013e12c5d1SDavid du Colombier 			rp->db = 1;
3027dd7cddfSDavid du Colombier 			if(ttl)
3037dd7cddfSDavid du Colombier 				rp->ttl = ttl;
3044f8f669cSDavid du Colombier 			if(dp == nil)
3057dd7cddfSDavid du Colombier 				dp = dnlookup(dname, Cin, 1);
3063e12c5d1SDavid du Colombier 			rp->owner = dp;
3073e12c5d1SDavid du Colombier 			*l = rp;
3083e12c5d1SDavid du Colombier 			l = &rp->next;
3093e12c5d1SDavid du Colombier 			nt->ptr = 1;
3103e12c5d1SDavid du Colombier 		}
3113e12c5d1SDavid du Colombier 		nt = nt->line;
3123e12c5d1SDavid du Colombier 		if(nt == s.t)
3133e12c5d1SDavid du Colombier 			break;
3143e12c5d1SDavid du Colombier 	}
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier 	/* search whole entry */
3173e12c5d1SDavid du Colombier 	for(nt = t; nt; nt = nt->entry)
3183e12c5d1SDavid du Colombier 		if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
3193e12c5d1SDavid du Colombier 			rp = (*f)(t, nt);
3203e12c5d1SDavid du Colombier 			rp->db = 1;
3217dd7cddfSDavid du Colombier 			if(ttl)
3227dd7cddfSDavid du Colombier 				rp->ttl = ttl;
3233e12c5d1SDavid du Colombier 			rp->auth = auth;
3244f8f669cSDavid du Colombier 			if(dp == nil)
3257dd7cddfSDavid du Colombier 				dp = dnlookup(dname, Cin, 1);
3263e12c5d1SDavid du Colombier 			rp->owner = dp;
3273e12c5d1SDavid du Colombier 			*l = rp;
3283e12c5d1SDavid du Colombier 			l = &rp->next;
3293e12c5d1SDavid du Colombier 		}
3303e12c5d1SDavid du Colombier 	ndbfree(t);
3313e12c5d1SDavid du Colombier 
3324f8f669cSDavid du Colombier //	dnslog("dnlookup1(%s) -> %#p", name, list);
3333e12c5d1SDavid du Colombier 	return list;
3343e12c5d1SDavid du Colombier }
3353e12c5d1SDavid du Colombier 
3363e12c5d1SDavid du Colombier /*
3373e12c5d1SDavid du Colombier  *  make various types of resource records from a database entry
3383e12c5d1SDavid du Colombier  */
3393e12c5d1SDavid du Colombier static RR*
3403e12c5d1SDavid du Colombier addrrr(Ndbtuple *entry, Ndbtuple *pair)
3413e12c5d1SDavid du Colombier {
3423e12c5d1SDavid du Colombier 	RR *rp;
3435d459b5aSDavid du Colombier 	uchar addr[IPaddrlen];
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 	USED(entry);
3465d459b5aSDavid du Colombier 	parseip(addr, pair->val);
3475d459b5aSDavid du Colombier 	if(isv4(addr))
3483e12c5d1SDavid du Colombier 		rp = rralloc(Ta);
3495d459b5aSDavid du Colombier 	else
3505d459b5aSDavid du Colombier 		rp = rralloc(Taaaa);
3513e12c5d1SDavid du Colombier 	rp->ip = dnlookup(pair->val, Cin, 1);
3523e12c5d1SDavid du Colombier 	return rp;
3533e12c5d1SDavid du Colombier }
3543e12c5d1SDavid du Colombier static RR*
3559a747e4fSDavid du Colombier nullrr(Ndbtuple *entry, Ndbtuple *pair)
3569a747e4fSDavid du Colombier {
3579a747e4fSDavid du Colombier 	RR *rp;
3589a747e4fSDavid du Colombier 
3599a747e4fSDavid du Colombier 	USED(entry);
3609a747e4fSDavid du Colombier 	rp = rralloc(Tnull);
3619a747e4fSDavid du Colombier 	rp->null->data = (uchar*)estrdup(pair->val);
3629a747e4fSDavid du Colombier 	rp->null->dlen = strlen((char*)rp->null->data);
3639a747e4fSDavid du Colombier 	return rp;
3649a747e4fSDavid du Colombier }
36560845620SDavid du Colombier /*
36660845620SDavid du Colombier  *  txt rr strings are at most 255 bytes long.  one
36760845620SDavid du Colombier  *  can represent longer strings by multiple concatenated
36860845620SDavid du Colombier  *  <= 255 byte ones.
36960845620SDavid du Colombier  */
3709a747e4fSDavid du Colombier static RR*
3719a747e4fSDavid du Colombier txtrr(Ndbtuple *entry, Ndbtuple *pair)
3729a747e4fSDavid du Colombier {
3739a747e4fSDavid du Colombier 	RR *rp;
37460845620SDavid du Colombier 	Txt *t, **l;
37560845620SDavid du Colombier 	int i, len, sofar;
3769a747e4fSDavid du Colombier 
3779a747e4fSDavid du Colombier 	USED(entry);
3789a747e4fSDavid du Colombier 	rp = rralloc(Ttxt);
37960845620SDavid du Colombier 	l = &rp->txt;
38060845620SDavid du Colombier 	rp->txt = nil;
38160845620SDavid du Colombier 	len = strlen(pair->val);
38260845620SDavid du Colombier 	sofar = 0;
38360845620SDavid du Colombier 	while(len > sofar){
38460845620SDavid du Colombier 		t = emalloc(sizeof(*t));
38560845620SDavid du Colombier 		t->next = nil;
38660845620SDavid du Colombier 
38760845620SDavid du Colombier 		i = len-sofar;
38860845620SDavid du Colombier 		if(i > 255)
38960845620SDavid du Colombier 			i = 255;
39060845620SDavid du Colombier 
39160845620SDavid du Colombier 		t->p = emalloc(i+1);
39260845620SDavid du Colombier 		memmove(t->p, pair->val+sofar, i);
39360845620SDavid du Colombier 		t->p[i] = 0;
39460845620SDavid du Colombier 		sofar += i;
39560845620SDavid du Colombier 
39660845620SDavid du Colombier 		*l = t;
39760845620SDavid du Colombier 		l = &t->next;
39860845620SDavid du Colombier 	}
3999a747e4fSDavid du Colombier 	return rp;
4009a747e4fSDavid du Colombier }
4019a747e4fSDavid du Colombier static RR*
4027dd7cddfSDavid du Colombier cnamerr(Ndbtuple *entry, Ndbtuple *pair)
4037dd7cddfSDavid du Colombier {
4047dd7cddfSDavid du Colombier 	RR *rp;
4057dd7cddfSDavid du Colombier 
4067dd7cddfSDavid du Colombier 	USED(entry);
4077dd7cddfSDavid du Colombier 	rp = rralloc(Tcname);
4087dd7cddfSDavid du Colombier 	rp->host = dnlookup(pair->val, Cin, 1);
4097dd7cddfSDavid du Colombier 	return rp;
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier static RR*
4123e12c5d1SDavid du Colombier mxrr(Ndbtuple *entry, Ndbtuple *pair)
4133e12c5d1SDavid du Colombier {
4143e12c5d1SDavid du Colombier 	RR *rp;
4153e12c5d1SDavid du Colombier 
4163e12c5d1SDavid du Colombier 	rp = rralloc(Tmx);
4173e12c5d1SDavid du Colombier 	rp->host = dnlookup(pair->val, Cin, 1);
4184f8f669cSDavid du Colombier 	rp->pref = intval(entry, pair, "pref", 1);
4193e12c5d1SDavid du Colombier 	return rp;
4203e12c5d1SDavid du Colombier }
4213e12c5d1SDavid du Colombier static RR*
4223e12c5d1SDavid du Colombier nsrr(Ndbtuple *entry, Ndbtuple *pair)
4233e12c5d1SDavid du Colombier {
4243e12c5d1SDavid du Colombier 	RR *rp;
4257dd7cddfSDavid du Colombier 	Ndbtuple *t;
4263e12c5d1SDavid du Colombier 
4273e12c5d1SDavid du Colombier 	rp = rralloc(Tns);
4283e12c5d1SDavid du Colombier 	rp->host = dnlookup(pair->val, Cin, 1);
4297dd7cddfSDavid du Colombier 	t = look(entry, pair, "soa");
4307dd7cddfSDavid du Colombier 	if(t && t->val[0] == 0)
4313e12c5d1SDavid du Colombier 		rp->local = 1;
4323e12c5d1SDavid du Colombier 	return rp;
4333e12c5d1SDavid du Colombier }
4347dd7cddfSDavid du Colombier static RR*
4357dd7cddfSDavid du Colombier ptrrr(Ndbtuple *entry, Ndbtuple *pair)
4367dd7cddfSDavid du Colombier {
4377dd7cddfSDavid du Colombier 	RR *rp;
4383e12c5d1SDavid du Colombier 
4397dd7cddfSDavid du Colombier 	USED(entry);
4407dd7cddfSDavid du Colombier 	rp = rralloc(Tns);
4417dd7cddfSDavid du Colombier 	rp->ptr = dnlookup(pair->val, Cin, 1);
4427dd7cddfSDavid du Colombier 	return rp;
4437dd7cddfSDavid du Colombier }
4443e12c5d1SDavid du Colombier static RR*
4453e12c5d1SDavid du Colombier soarr(Ndbtuple *entry, Ndbtuple *pair)
4463e12c5d1SDavid du Colombier {
4473e12c5d1SDavid du Colombier 	RR *rp;
4487dd7cddfSDavid du Colombier 	Ndbtuple *ns, *mb, *t;
4493e12c5d1SDavid du Colombier 	char mailbox[Domlen];
4507dd7cddfSDavid du Colombier 	Ndb *ndb;
4517dd7cddfSDavid du Colombier 	char *p;
4523e12c5d1SDavid du Colombier 
4533e12c5d1SDavid du Colombier 	rp = rralloc(Tsoa);
4547dd7cddfSDavid du Colombier 	rp->soa->serial = 1;
4557dd7cddfSDavid du Colombier 	for(ndb = db; ndb; ndb = ndb->next)
4567dd7cddfSDavid du Colombier 		if(ndb->mtime > rp->soa->serial)
4577dd7cddfSDavid du Colombier 			rp->soa->serial = ndb->mtime;
4584f8f669cSDavid du Colombier 
4594f8f669cSDavid du Colombier 	rp->soa->retry  = intval(entry, pair, "retry", Hour);
4604f8f669cSDavid du Colombier 	rp->soa->expire = intval(entry, pair, "expire", Day);
4614f8f669cSDavid du Colombier 	rp->soa->minttl = intval(entry, pair, "ttl", Day);
4624f8f669cSDavid du Colombier 	rp->soa->refresh = intval(entry, pair, "refresh", Day);
4634f8f669cSDavid du Colombier 	rp->soa->serial = intval(entry, pair, "serial", rp->soa->serial);
4647dd7cddfSDavid du Colombier 
4653e12c5d1SDavid du Colombier 	ns = look(entry, pair, "ns");
4664f8f669cSDavid du Colombier 	if(ns == nil)
4673e12c5d1SDavid du Colombier 		ns = look(entry, pair, "dom");
4683e12c5d1SDavid du Colombier 	rp->host = dnlookup(ns->val, Cin, 1);
4697dd7cddfSDavid du Colombier 
4707dd7cddfSDavid du Colombier 	/* accept all of:
4717dd7cddfSDavid du Colombier 	 *  mbox=person
4727dd7cddfSDavid du Colombier 	 *  mbox=person@machine.dom
4737dd7cddfSDavid du Colombier 	 *  mbox=person.machine.dom
4747dd7cddfSDavid du Colombier 	 */
4757dd7cddfSDavid du Colombier 	mb = look(entry, pair, "mbox");
4767dd7cddfSDavid du Colombier 	if(mb == nil)
4773e12c5d1SDavid du Colombier 		mb = look(entry, pair, "mb");
4784f8f669cSDavid du Colombier 	if(mb)
4797dd7cddfSDavid du Colombier 		if(strchr(mb->val, '.')) {
4807dd7cddfSDavid du Colombier 			p = strchr(mb->val, '@');
4817dd7cddfSDavid du Colombier 			if(p != nil)
4827dd7cddfSDavid du Colombier 				*p = '.';
4833e12c5d1SDavid du Colombier 			rp->rmb = dnlookup(mb->val, Cin, 1);
4847dd7cddfSDavid du Colombier 		} else {
4854f8f669cSDavid du Colombier 			snprint(mailbox, sizeof mailbox, "%s.%s",
4867dd7cddfSDavid du Colombier 				mb->val, ns->val);
4873e12c5d1SDavid du Colombier 			rp->rmb = dnlookup(mailbox, Cin, 1);
4883e12c5d1SDavid du Colombier 		}
4894f8f669cSDavid du Colombier 	else {
4904f8f669cSDavid du Colombier 		snprint(mailbox, sizeof mailbox, "postmaster.%s", ns->val);
4913e12c5d1SDavid du Colombier 		rp->rmb = dnlookup(mailbox, Cin, 1);
4923e12c5d1SDavid du Colombier 	}
493dc5a79c1SDavid du Colombier 
4944f8f669cSDavid du Colombier 	/*
4954f8f669cSDavid du Colombier 	 *  hang dns slaves off of the soa.  this is
496dc5a79c1SDavid du Colombier 	 *  for managing the area.
497dc5a79c1SDavid du Colombier 	 */
498dc5a79c1SDavid du Colombier 	for(t = entry; t != nil; t = t->entry)
499dc5a79c1SDavid du Colombier 		if(strcmp(t->attr, "dnsslave") == 0)
500dc5a79c1SDavid du Colombier 			addserver(&rp->soa->slaves, t->val);
501dc5a79c1SDavid du Colombier 
5023e12c5d1SDavid du Colombier 	return rp;
5033e12c5d1SDavid du Colombier }
5043e12c5d1SDavid du Colombier 
5054f8f669cSDavid du Colombier static RR*
5064f8f669cSDavid du Colombier srvrr(Ndbtuple *entry, Ndbtuple *pair)
5074f8f669cSDavid du Colombier {
5084f8f669cSDavid du Colombier 	RR *rp;
5094f8f669cSDavid du Colombier 
5104f8f669cSDavid du Colombier 	rp = rralloc(Tsrv);
511225077b0SDavid du Colombier 	rp->host = dnlookup(pair->val, Cin, 1);
5124f8f669cSDavid du Colombier 	rp->srv->pri = intval(entry, pair, "pri", 0);
5134f8f669cSDavid du Colombier 	rp->srv->weight = intval(entry, pair, "weight", 0);
51453874d13SDavid du Colombier 	/* TODO: translate service name to port # */
515225077b0SDavid du Colombier 	rp->port = intval(entry, pair, "port", 0);
5164f8f669cSDavid du Colombier 	return rp;
5174f8f669cSDavid du Colombier }
5184f8f669cSDavid du Colombier 
5193e12c5d1SDavid du Colombier /*
5203e12c5d1SDavid du Colombier  *  Look for a pair with the given attribute.  look first on the same line,
5213e12c5d1SDavid du Colombier  *  then in the whole entry.
5223e12c5d1SDavid du Colombier  */
5233e12c5d1SDavid du Colombier static Ndbtuple*
5243e12c5d1SDavid du Colombier look(Ndbtuple *entry, Ndbtuple *line, char *attr)
5253e12c5d1SDavid du Colombier {
5263e12c5d1SDavid du Colombier 	Ndbtuple *nt;
5273e12c5d1SDavid du Colombier 
5283e12c5d1SDavid du Colombier 	/* first look on same line (closer binding) */
5293e12c5d1SDavid du Colombier 	for(nt = line;;){
5303e12c5d1SDavid du Colombier 		if(cistrcmp(attr, nt->attr) == 0)
5313e12c5d1SDavid du Colombier 			return nt;
5323e12c5d1SDavid du Colombier 		nt = nt->line;
5333e12c5d1SDavid du Colombier 		if(nt == line)
5343e12c5d1SDavid du Colombier 			break;
5353e12c5d1SDavid du Colombier 	}
5363e12c5d1SDavid du Colombier 	/* search whole tuple */
5373e12c5d1SDavid du Colombier 	for(nt = entry; nt; nt = nt->entry)
5383e12c5d1SDavid du Colombier 		if(cistrcmp(attr, nt->attr) == 0)
5393e12c5d1SDavid du Colombier 			return nt;
5403e12c5d1SDavid du Colombier 	return 0;
5413e12c5d1SDavid du Colombier }
5423e12c5d1SDavid du Colombier 
5437dd7cddfSDavid du Colombier static RR**
5447dd7cddfSDavid du Colombier linkrr(RR *rp, DN *dp, RR **l)
5457dd7cddfSDavid du Colombier {
5467dd7cddfSDavid du Colombier 	rp->owner = dp;
5477dd7cddfSDavid du Colombier 	rp->auth = 1;
5487dd7cddfSDavid du Colombier 	rp->db = 1;
5497dd7cddfSDavid du Colombier 	*l = rp;
5507dd7cddfSDavid du Colombier 	return &rp->next;
5517dd7cddfSDavid du Colombier }
5527dd7cddfSDavid du Colombier 
5537dd7cddfSDavid du Colombier /* these are answered specially by the tcp version */
5547dd7cddfSDavid du Colombier static RR*
5557dd7cddfSDavid du Colombier doaxfr(Ndb *db, char *name)
5567dd7cddfSDavid du Colombier {
5577dd7cddfSDavid du Colombier 	USED(db, name);
5587dd7cddfSDavid du Colombier 	return 0;
5597dd7cddfSDavid du Colombier }
5607dd7cddfSDavid du Colombier 
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier /*
5637dd7cddfSDavid du Colombier  *  read the all the soa's from the database to determine area's.
5647dd7cddfSDavid du Colombier  *  this is only used when we're not caching the database.
5657dd7cddfSDavid du Colombier  */
5667dd7cddfSDavid du Colombier static void
5677dd7cddfSDavid du Colombier dbfile2area(Ndb *db)
5687dd7cddfSDavid du Colombier {
5697dd7cddfSDavid du Colombier 	Ndbtuple *t;
5707dd7cddfSDavid du Colombier 
57159cc4ca5SDavid du Colombier 	if(debug)
5724f8f669cSDavid du Colombier 		dnslog("rereading %s", db->file);
5737dd7cddfSDavid du Colombier 	Bseek(&db->b, 0, 0);
5744f8f669cSDavid du Colombier 	while(t = ndbparse(db))
5757dd7cddfSDavid du Colombier 		ndbfree(t);
5767dd7cddfSDavid du Colombier }
5777dd7cddfSDavid du Colombier 
5787dd7cddfSDavid du Colombier /*
5797dd7cddfSDavid du Colombier  *  read the database into the cache
5807dd7cddfSDavid du Colombier  */
5817dd7cddfSDavid du Colombier static void
5827dd7cddfSDavid du Colombier dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
5837dd7cddfSDavid du Colombier {
5847dd7cddfSDavid du Colombier 	RR *rp;
5853ff48bf5SDavid du Colombier 	static ulong ord;
5867dd7cddfSDavid du Colombier 
5877dd7cddfSDavid du Colombier 	rp = 0;
588*d9924332SDavid du Colombier 	if(cistrcmp(pair->attr, "ip") == 0 ||
589*d9924332SDavid du Colombier 	   cistrcmp(pair->attr, "ipv6") == 0){
5903ff48bf5SDavid du Colombier 		dp->ordinal = ord++;
5917dd7cddfSDavid du Colombier 		rp = addrrr(entry, pair);
5924f8f669cSDavid du Colombier 	} else 	if(cistrcmp(pair->attr, "ns") == 0)
5937dd7cddfSDavid du Colombier 		rp = nsrr(entry, pair);
5944f8f669cSDavid du Colombier 	else if(cistrcmp(pair->attr, "soa") == 0) {
5957dd7cddfSDavid du Colombier 		rp = soarr(entry, pair);
5967dd7cddfSDavid du Colombier 		addarea(dp, rp, pair);
5974f8f669cSDavid du Colombier 	} else if(cistrcmp(pair->attr, "mx") == 0)
5987dd7cddfSDavid du Colombier 		rp = mxrr(entry, pair);
59976783259SDavid du Colombier 	else if(cistrcmp(pair->attr, "srv") == 0)
60076783259SDavid du Colombier 		rp = srvrr(entry, pair);
6014f8f669cSDavid du Colombier 	else if(cistrcmp(pair->attr, "cname") == 0)
6027dd7cddfSDavid du Colombier 		rp = cnamerr(entry, pair);
6034f8f669cSDavid du Colombier 	else if(cistrcmp(pair->attr, "nullrr") == 0)
6049a747e4fSDavid du Colombier 		rp = nullrr(entry, pair);
6054f8f669cSDavid du Colombier 	else if(cistrcmp(pair->attr, "txtrr") == 0)
6069a747e4fSDavid du Colombier 		rp = txtrr(entry, pair);
6074f8f669cSDavid du Colombier 	if(rp == nil)
6087dd7cddfSDavid du Colombier 		return;
6097dd7cddfSDavid du Colombier 
6107dd7cddfSDavid du Colombier 	rp->owner = dp;
611410ea80bSDavid du Colombier 	dnagenever(dp, 1);
6127dd7cddfSDavid du Colombier 	rp->db = 1;
6134f8f669cSDavid du Colombier 	rp->ttl = intval(entry, pair, "ttl", rp->ttl);
6146dc4800dSDavid du Colombier 	rrattach(rp, Notauthoritative);
6157dd7cddfSDavid du Colombier }
6167dd7cddfSDavid du Colombier static void
6177dd7cddfSDavid du Colombier dbtuple2cache(Ndbtuple *t)
6187dd7cddfSDavid du Colombier {
6197dd7cddfSDavid du Colombier 	Ndbtuple *et, *nt;
6207dd7cddfSDavid du Colombier 	DN *dp;
6217dd7cddfSDavid du Colombier 
6224f8f669cSDavid du Colombier 	for(et = t; et; et = et->entry)
6237dd7cddfSDavid du Colombier 		if(strcmp(et->attr, "dom") == 0){
6247dd7cddfSDavid du Colombier 			dp = dnlookup(et->val, Cin, 1);
6257dd7cddfSDavid du Colombier 
6267dd7cddfSDavid du Colombier 			/* first same line */
6277dd7cddfSDavid du Colombier 			for(nt = et->line; nt != et; nt = nt->line){
6287dd7cddfSDavid du Colombier 				dbpair2cache(dp, t, nt);
6297dd7cddfSDavid du Colombier 				nt->ptr = 1;
6307dd7cddfSDavid du Colombier 			}
6317dd7cddfSDavid du Colombier 
6327dd7cddfSDavid du Colombier 			/* then rest of entry */
6337dd7cddfSDavid du Colombier 			for(nt = t; nt; nt = nt->entry){
6347dd7cddfSDavid du Colombier 				if(nt->ptr == 0)
6357dd7cddfSDavid du Colombier 					dbpair2cache(dp, t, nt);
6367dd7cddfSDavid du Colombier 				nt->ptr = 0;
6377dd7cddfSDavid du Colombier 			}
6387dd7cddfSDavid du Colombier 		}
6397dd7cddfSDavid du Colombier }
6407dd7cddfSDavid du Colombier static void
6417dd7cddfSDavid du Colombier dbfile2cache(Ndb *db)
6427dd7cddfSDavid du Colombier {
6437dd7cddfSDavid du Colombier 	Ndbtuple *t;
6447dd7cddfSDavid du Colombier 
64559cc4ca5SDavid du Colombier 	if(debug)
6464f8f669cSDavid du Colombier 		dnslog("rereading %s", db->file);
6477dd7cddfSDavid du Colombier 	Bseek(&db->b, 0, 0);
6487dd7cddfSDavid du Colombier 	while(t = ndbparse(db)){
6497dd7cddfSDavid du Colombier 		dbtuple2cache(t);
6507dd7cddfSDavid du Colombier 		ndbfree(t);
6517dd7cddfSDavid du Colombier 	}
6527dd7cddfSDavid du Colombier }
6534f8f669cSDavid du Colombier 
6544f8f669cSDavid du Colombier /* called with dblock held */
6554f8f669cSDavid du Colombier static void
6564f8f669cSDavid du Colombier loaddomsrvs(void)
6574f8f669cSDavid du Colombier {
6584f8f669cSDavid du Colombier 	Ndbs s;
6594f8f669cSDavid du Colombier 
6604f8f669cSDavid du Colombier 	if (!cfg.inside || !cfg.straddle || !cfg.serve)
6614f8f669cSDavid du Colombier 		return;
6624f8f669cSDavid du Colombier 	if (indoms) {
6634f8f669cSDavid du Colombier 		ndbfree(indoms);
6644f8f669cSDavid du Colombier 		ndbfree(innmsrvs);
6654f8f669cSDavid du Colombier 		ndbfree(outnmsrvs);
6664f8f669cSDavid du Colombier 		indoms = innmsrvs = outnmsrvs = nil;
6674f8f669cSDavid du Colombier 	}
6684f8f669cSDavid du Colombier 	if (db == nil)
6694f8f669cSDavid du Colombier 		opendatabase();
6704f8f669cSDavid du Colombier 	free(ndbgetvalue(db, &s, "sys", "inside-dom", "dom", &indoms));
6714f8f669cSDavid du Colombier 	free(ndbgetvalue(db, &s, "sys", "inside-ns",  "ip",  &innmsrvs));
6724f8f669cSDavid du Colombier 	free(ndbgetvalue(db, &s, "sys", "outside-ns", "ip",  &outnmsrvs));
6734f8f669cSDavid du Colombier 	dnslog("[%d] ndb changed: reloaded inside-dom, inside-ns, outside-ns",
6744f8f669cSDavid du Colombier 		getpid());
6754f8f669cSDavid du Colombier }
6764f8f669cSDavid du Colombier 
6777dd7cddfSDavid du Colombier void
6787dd7cddfSDavid du Colombier db2cache(int doit)
6797dd7cddfSDavid du Colombier {
680530fef66SDavid du Colombier 	ulong youngest;
6817dd7cddfSDavid du Colombier 	Ndb *ndb;
6829a747e4fSDavid du Colombier 	Dir *d;
6834f8f669cSDavid du Colombier 	static ulong lastcheck, lastyoungest;
6847dd7cddfSDavid du Colombier 
685dc5a79c1SDavid du Colombier 	/* no faster than once every 2 minutes */
6867dd7cddfSDavid du Colombier 	if(now < lastcheck + 2*Min && !doit)
6877dd7cddfSDavid du Colombier 		return;
6887dd7cddfSDavid du Colombier 
689dc5a79c1SDavid du Colombier 	refresh_areas(owned);
690dc5a79c1SDavid du Colombier 
6917dd7cddfSDavid du Colombier 	lock(&dblock);
6927dd7cddfSDavid du Colombier 
6937dd7cddfSDavid du Colombier 	if(opendatabase() < 0){
6947dd7cddfSDavid du Colombier 		unlock(&dblock);
6957dd7cddfSDavid du Colombier 		return;
6967dd7cddfSDavid du Colombier 	}
6977dd7cddfSDavid du Colombier 
6987dd7cddfSDavid du Colombier 	/*
6997dd7cddfSDavid du Colombier 	 *  file may be changing as we are reading it, so loop till
7007dd7cddfSDavid du Colombier 	 *  mod times are consistent.
7017dd7cddfSDavid du Colombier 	 *
7027dd7cddfSDavid du Colombier 	 *  we don't use the times in the ndb records because they may
7037dd7cddfSDavid du Colombier 	 *  change outside of refreshing our cached knowledge.
7047dd7cddfSDavid du Colombier 	 */
7057dd7cddfSDavid du Colombier 	for(;;){
7067dd7cddfSDavid du Colombier 		lastcheck = now;
7077dd7cddfSDavid du Colombier 		youngest = 0;
7084f8f669cSDavid du Colombier 		for(ndb = db; ndb; ndb = ndb->next)
7094f8f669cSDavid du Colombier 			/* dirfstat avoids walking the mount table each time */
7109a747e4fSDavid du Colombier 			if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
7119a747e4fSDavid du Colombier 			   (d = dirstat(ndb->file)) != nil){
712530fef66SDavid du Colombier 				if(d->mtime > youngest)
713530fef66SDavid du Colombier 					youngest = d->mtime;
7149a747e4fSDavid du Colombier 				free(d);
7157dd7cddfSDavid du Colombier 			}
716b85a8364SDavid du Colombier 		if(!doit && youngest == lastyoungest)
717b85a8364SDavid du Colombier 			break;
7187dd7cddfSDavid du Colombier 
7197dd7cddfSDavid du Colombier 		/* forget our area definition */
7207dd7cddfSDavid du Colombier 		freearea(&owned);
7217dd7cddfSDavid du Colombier 		freearea(&delegated);
7227dd7cddfSDavid du Colombier 
7237dd7cddfSDavid du Colombier 		/* reopen all the files (to get oldest for time stamp) */
7247dd7cddfSDavid du Colombier 		for(ndb = db; ndb; ndb = ndb->next)
7257dd7cddfSDavid du Colombier 			ndbreopen(ndb);
7267dd7cddfSDavid du Colombier 
7274f8f669cSDavid du Colombier 		/* reload straddle-server configuration */
7284f8f669cSDavid du Colombier 		loaddomsrvs();
7294f8f669cSDavid du Colombier 
7304f8f669cSDavid du Colombier 		if(cfg.cachedb){
7317dd7cddfSDavid du Colombier 			/* mark all db records as timed out */
7327dd7cddfSDavid du Colombier 			dnagedb();
7337dd7cddfSDavid du Colombier 
7347dd7cddfSDavid du Colombier 			/* read in new entries */
7357dd7cddfSDavid du Colombier 			for(ndb = db; ndb; ndb = ndb->next)
7367dd7cddfSDavid du Colombier 				dbfile2cache(ndb);
7377dd7cddfSDavid du Colombier 
7384f8f669cSDavid du Colombier 			/* mark as authoritative anything in our domain */
7397dd7cddfSDavid du Colombier 			dnauthdb();
7407dd7cddfSDavid du Colombier 
7417dd7cddfSDavid du Colombier 			/* remove old entries */
7427dd7cddfSDavid du Colombier 			dnageall(1);
7434f8f669cSDavid du Colombier 		} else
7447dd7cddfSDavid du Colombier 			/* read all the soa's to get database defaults */
7457dd7cddfSDavid du Colombier 			for(ndb = db; ndb; ndb = ndb->next)
7467dd7cddfSDavid du Colombier 				dbfile2area(ndb);
7477dd7cddfSDavid du Colombier 
7487dd7cddfSDavid du Colombier 		doit = 0;
7497dd7cddfSDavid du Colombier 		lastyoungest = youngest;
7503ff48bf5SDavid du Colombier 		createptrs();
7517dd7cddfSDavid du Colombier 	}
7527dd7cddfSDavid du Colombier 
7537dd7cddfSDavid du Colombier 	unlock(&dblock);
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier 
75621abd8f2SDavid du Colombier void
75721abd8f2SDavid du Colombier dnforceage(void)
75821abd8f2SDavid du Colombier {
75921abd8f2SDavid du Colombier 	lock(&dblock);
76021abd8f2SDavid du Colombier 	dnageall(1);
76121abd8f2SDavid du Colombier 	unlock(&dblock);
76221abd8f2SDavid du Colombier }
76321abd8f2SDavid du Colombier 
764b322bd99SDavid du Colombier extern uchar	ipaddr[IPaddrlen];	/* my ip address */
7657dd7cddfSDavid du Colombier 
7667dd7cddfSDavid du Colombier /*
7677dd7cddfSDavid du Colombier  *  get all my xxx
76853874d13SDavid du Colombier  *  caller ndbfrees the result
7697dd7cddfSDavid du Colombier  */
7707dd7cddfSDavid du Colombier Ndbtuple*
7717dd7cddfSDavid du Colombier lookupinfo(char *attr)
7727dd7cddfSDavid du Colombier {
7737dd7cddfSDavid du Colombier 	char buf[64];
7747dd7cddfSDavid du Colombier 	char *a[2];
77553874d13SDavid du Colombier 	Ndbtuple *t;
7767dd7cddfSDavid du Colombier 
7779a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%I", ipaddr);
7787dd7cddfSDavid du Colombier 	a[0] = attr;
7797dd7cddfSDavid du Colombier 
7807dd7cddfSDavid du Colombier 	lock(&dblock);
7817dd7cddfSDavid du Colombier 	if(opendatabase() < 0){
7827dd7cddfSDavid du Colombier 		unlock(&dblock);
7837dd7cddfSDavid du Colombier 		return nil;
7847dd7cddfSDavid du Colombier 	}
7857dd7cddfSDavid du Colombier 	t = ndbipinfo(db, "ip", buf, a, 1);
7867dd7cddfSDavid du Colombier 	unlock(&dblock);
7877dd7cddfSDavid du Colombier 	return t;
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier 
79059cc4ca5SDavid du Colombier char *localservers =	  "local#dns#servers";
79159cc4ca5SDavid du Colombier char *localserverprefix = "local#dns#server";
79259cc4ca5SDavid du Colombier 
7937dd7cddfSDavid du Colombier /*
7948246a6ddSDavid du Colombier  *  return non-zero if this is a bad delegation
7957dd7cddfSDavid du Colombier  */
7967dd7cddfSDavid du Colombier int
7977dd7cddfSDavid du Colombier baddelegation(RR *rp, RR *nsrp, uchar *addr)
7987dd7cddfSDavid du Colombier {
7997dd7cddfSDavid du Colombier 	Ndbtuple *nt;
800adb31a62SDavid du Colombier 	static int whined;
8017dd7cddfSDavid du Colombier 	static Ndbtuple *t;
8027dd7cddfSDavid du Colombier 
8037dd7cddfSDavid du Colombier 	if(t == nil)
8047dd7cddfSDavid du Colombier 		t = lookupinfo("dom");
8057dd7cddfSDavid du Colombier 	if(t == nil)
8067dd7cddfSDavid du Colombier 		return 0;
8077dd7cddfSDavid du Colombier 
8087dd7cddfSDavid du Colombier 	for(; rp; rp = rp->next){
8097dd7cddfSDavid du Colombier 		if(rp->type != Tns)
8107dd7cddfSDavid du Colombier 			continue;
8117dd7cddfSDavid du Colombier 
8127dd7cddfSDavid du Colombier 		/* see if delegation is looping */
8137dd7cddfSDavid du Colombier 		if(nsrp)
8147dd7cddfSDavid du Colombier 		if(rp->owner != nsrp->owner)
81559cc4ca5SDavid du Colombier 		if(subsume(rp->owner->name, nsrp->owner->name) &&
81659cc4ca5SDavid du Colombier 		   strcmp(nsrp->owner->name, localservers) != 0){
8174f8f669cSDavid du Colombier 			dnslog("delegation loop %R -> %R from %I",
8184f8f669cSDavid du Colombier 				nsrp, rp, addr);
8197dd7cddfSDavid du Colombier 			return 1;
8207dd7cddfSDavid du Colombier 		}
8217dd7cddfSDavid du Colombier 
8227dd7cddfSDavid du Colombier 		/* see if delegating to us what we don't own */
8237dd7cddfSDavid du Colombier 		for(nt = t; nt != nil; nt = nt->entry)
8247dd7cddfSDavid du Colombier 			if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
8257dd7cddfSDavid du Colombier 				break;
8267dd7cddfSDavid du Colombier 		if(nt != nil && !inmyarea(rp->owner->name)){
827adb31a62SDavid du Colombier 			if (!whined) {
828adb31a62SDavid du Colombier 				whined = 1;
829adb31a62SDavid du Colombier 				dnslog("bad delegation %R from %I; "
830adb31a62SDavid du Colombier 					"no further logging of them", rp, addr);
831adb31a62SDavid du Colombier 			}
8327dd7cddfSDavid du Colombier 			return 1;
8337dd7cddfSDavid du Colombier 		}
8347dd7cddfSDavid du Colombier 	}
8357dd7cddfSDavid du Colombier 
8367dd7cddfSDavid du Colombier 	return 0;
8377dd7cddfSDavid du Colombier }
8387dd7cddfSDavid du Colombier 
8394e153993SDavid du Colombier int
840a41547ffSDavid du Colombier myaddr(char *addr)
841a41547ffSDavid du Colombier {
842a41547ffSDavid du Colombier 	char *name, *line, *sp;
843a41547ffSDavid du Colombier 	char buf[64];
844a41547ffSDavid du Colombier 	Biobuf *bp;
845a41547ffSDavid du Colombier 
846a41547ffSDavid du Colombier 	snprint(buf, sizeof buf, "%I", ipaddr);
847a41547ffSDavid du Colombier 	if (strcmp(addr, buf) == 0) {
848a41547ffSDavid du Colombier 		dnslog("rejecting my ip %s as local dns server", addr);
849a41547ffSDavid du Colombier 		return 1;
850a41547ffSDavid du Colombier 	}
851a41547ffSDavid du Colombier 
852a41547ffSDavid du Colombier 	name = smprint("%s/ipselftab", mntpt);
853a41547ffSDavid du Colombier 	bp = Bopen(name, OREAD);
854a41547ffSDavid du Colombier 	free(name);
855a41547ffSDavid du Colombier 	if (bp != nil) {
856a41547ffSDavid du Colombier 		while ((line = Brdline(bp, '\n')) != nil) {
857a41547ffSDavid du Colombier 			line[Blinelen(bp) - 1] = '\0';
858a41547ffSDavid du Colombier 			sp = strchr(line, ' ');
859a41547ffSDavid du Colombier 			if (sp) {
860a41547ffSDavid du Colombier 				*sp = '\0';
861a41547ffSDavid du Colombier 				if (strcmp(addr, line) == 0) {
862a41547ffSDavid du Colombier 					dnslog("rejecting my ip %s as local dns server",
863a41547ffSDavid du Colombier 						addr);
864a41547ffSDavid du Colombier 					return 1;
865a41547ffSDavid du Colombier 				}
866a41547ffSDavid du Colombier 			}
867a41547ffSDavid du Colombier 		}
868a41547ffSDavid du Colombier 		Bterm(bp);
869a41547ffSDavid du Colombier 	}
870a41547ffSDavid du Colombier 	return 0;
871a41547ffSDavid du Colombier }
872a41547ffSDavid du Colombier 
873a41547ffSDavid du Colombier static char *locdns[20];
8744f927735SDavid du Colombier static QLock locdnslck;
875a41547ffSDavid du Colombier 
8767dd7cddfSDavid du Colombier static void
8777dd7cddfSDavid du Colombier addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
8787dd7cddfSDavid du Colombier {
879a41547ffSDavid du Colombier 	int n;
8807dd7cddfSDavid du Colombier 	DN *nsdp;
8817dd7cddfSDavid du Colombier 	RR *rp;
8827dd7cddfSDavid du Colombier 	char buf[32];
883*d9924332SDavid du Colombier 	uchar ip[IPaddrlen];
8847dd7cddfSDavid du Colombier 
885a41547ffSDavid du Colombier 	/* reject our own ip addresses so we don't query ourselves via udp */
886a41547ffSDavid du Colombier 	if (myaddr(ipaddr))
887a41547ffSDavid du Colombier 		return;
888a41547ffSDavid du Colombier 
8894e153993SDavid du Colombier 	qlock(&locdnslck);
890a41547ffSDavid du Colombier 	for (n = 0; n < i && n < nelem(locdns) && locdns[n]; n++)
891a41547ffSDavid du Colombier 		if (strcmp(locdns[n], ipaddr) == 0) {
892a41547ffSDavid du Colombier 			dnslog("rejecting duplicate local dns server ip %s",
893a41547ffSDavid du Colombier 				ipaddr);
8944e153993SDavid du Colombier 			qunlock(&locdnslck);
895a41547ffSDavid du Colombier 			return;
896a41547ffSDavid du Colombier 		}
897a41547ffSDavid du Colombier 	if (n < nelem(locdns))
898a41547ffSDavid du Colombier 		if (locdns[n] == nil || ++n < nelem(locdns))
8994f927735SDavid du Colombier 			locdns[n] = strdup(ipaddr); /* remember 1st few local ns */
9004e153993SDavid du Colombier 	qunlock(&locdnslck);
901a41547ffSDavid du Colombier 
9027dd7cddfSDavid du Colombier 	/* ns record for name server, make up an impossible name */
9037dd7cddfSDavid du Colombier 	rp = rralloc(Tns);
9044f8f669cSDavid du Colombier 	snprint(buf, sizeof buf, "%s%d", localserverprefix, i);
9057dd7cddfSDavid du Colombier 	nsdp = dnlookup(buf, class, 1);
9067dd7cddfSDavid du Colombier 	rp->host = nsdp;
907a41547ffSDavid du Colombier 	rp->owner = dp;			/* e.g., local#dns#servers */
9087dd7cddfSDavid du Colombier 	rp->local = 1;
9097dd7cddfSDavid du Colombier 	rp->db = 1;
910a41547ffSDavid du Colombier //	rp->ttl = 10*Min;		/* seems too short */
911a41547ffSDavid du Colombier 	rp->ttl = (1UL<<31)-1;
9126dc4800dSDavid du Colombier 	rrattach(rp, Authoritative);	/* will not attach rrs in my area */
9137dd7cddfSDavid du Colombier 
914*d9924332SDavid du Colombier 	/* A or AAAA record */
915*d9924332SDavid du Colombier 	if (parseip(ip, ipaddr) >= 0 && isv4(ip))
9167dd7cddfSDavid du Colombier 		rp = rralloc(Ta);
917*d9924332SDavid du Colombier 	else
918*d9924332SDavid du Colombier 		rp = rralloc(Taaaa);
9197dd7cddfSDavid du Colombier 	rp->ip = dnlookup(ipaddr, class, 1);
9207dd7cddfSDavid du Colombier 	rp->owner = nsdp;
9217dd7cddfSDavid du Colombier 	rp->local = 1;
9227dd7cddfSDavid du Colombier 	rp->db = 1;
923a41547ffSDavid du Colombier //	rp->ttl = 10*Min;		/* seems too short */
924a41547ffSDavid du Colombier 	rp->ttl = (1UL<<31)-1;
9256dc4800dSDavid du Colombier 	rrattach(rp, Authoritative);	/* will not attach rrs in my area */
926a41547ffSDavid du Colombier 
927a41547ffSDavid du Colombier 	dnslog("added local dns server %s at %s", buf, ipaddr);
9287dd7cddfSDavid du Colombier }
9297dd7cddfSDavid du Colombier 
9307dd7cddfSDavid du Colombier /*
9317dd7cddfSDavid du Colombier  *  return list of dns server addresses to use when
9327dd7cddfSDavid du Colombier  *  acting just as a resolver.
9337dd7cddfSDavid du Colombier  */
9347dd7cddfSDavid du Colombier RR*
9357dd7cddfSDavid du Colombier dnsservers(int class)
9367dd7cddfSDavid du Colombier {
9374f8f669cSDavid du Colombier 	int i, n;
9384f927735SDavid du Colombier 	char *p;
9394f8f669cSDavid du Colombier 	char *args[5];
9407dd7cddfSDavid du Colombier 	Ndbtuple *t, *nt;
9417dd7cddfSDavid du Colombier 	RR *nsrp;
9427dd7cddfSDavid du Colombier 	DN *dp;
9437dd7cddfSDavid du Colombier 
94459cc4ca5SDavid du Colombier 	dp = dnlookup(localservers, class, 1);
9457dd7cddfSDavid du Colombier 	nsrp = rrlookup(dp, Tns, NOneg);
9467dd7cddfSDavid du Colombier 	if(nsrp != nil)
9477dd7cddfSDavid du Colombier 		return nsrp;
9487dd7cddfSDavid du Colombier 
949b322bd99SDavid du Colombier 	p = getenv("DNSSERVER");		/* list of ip addresses */
9507dd7cddfSDavid du Colombier 	if(p != nil){
9514f927735SDavid du Colombier 		n = tokenize(p, args, nelem(args));
9527dd7cddfSDavid du Colombier 		for(i = 0; i < n; i++)
9537dd7cddfSDavid du Colombier 			addlocaldnsserver(dp, class, args[i], i);
9544f927735SDavid du Colombier 		free(p);
9557dd7cddfSDavid du Colombier 	} else {
956b322bd99SDavid du Colombier 		t = lookupinfo("@dns");		/* @dns=ip1 @dns=ip2 ... */
9577dd7cddfSDavid du Colombier 		if(t == nil)
9587dd7cddfSDavid du Colombier 			return nil;
9597dd7cddfSDavid du Colombier 		i = 0;
9607dd7cddfSDavid du Colombier 		for(nt = t; nt != nil; nt = nt->entry){
9617dd7cddfSDavid du Colombier 			addlocaldnsserver(dp, class, nt->val, i);
9627dd7cddfSDavid du Colombier 			i++;
9637dd7cddfSDavid du Colombier 		}
9647dd7cddfSDavid du Colombier 		ndbfree(t);
9657dd7cddfSDavid du Colombier 	}
9667dd7cddfSDavid du Colombier 
9677dd7cddfSDavid du Colombier 	return rrlookup(dp, Tns, NOneg);
9687dd7cddfSDavid du Colombier }
9697dd7cddfSDavid du Colombier 
9707dd7cddfSDavid du Colombier static void
9717dd7cddfSDavid du Colombier addlocaldnsdomain(DN *dp, int class, char *domain)
9727dd7cddfSDavid du Colombier {
9737dd7cddfSDavid du Colombier 	RR *rp;
9747dd7cddfSDavid du Colombier 
975225077b0SDavid du Colombier 	/* ptr record */
9767dd7cddfSDavid du Colombier 	rp = rralloc(Tptr);
9777dd7cddfSDavid du Colombier 	rp->ptr = dnlookup(domain, class, 1);
9787dd7cddfSDavid du Colombier 	rp->owner = dp;
9797dd7cddfSDavid du Colombier 	rp->db = 1;
9807dd7cddfSDavid du Colombier 	rp->ttl = 10*Min;
9816dc4800dSDavid du Colombier 	rrattach(rp, Authoritative);
9827dd7cddfSDavid du Colombier }
9837dd7cddfSDavid du Colombier 
9847dd7cddfSDavid du Colombier /*
9857dd7cddfSDavid du Colombier  *  return list of domains to use when resolving names without '.'s
9867dd7cddfSDavid du Colombier  */
9877dd7cddfSDavid du Colombier RR*
9887dd7cddfSDavid du Colombier domainlist(int class)
9897dd7cddfSDavid du Colombier {
9907dd7cddfSDavid du Colombier 	Ndbtuple *t, *nt;
9917dd7cddfSDavid du Colombier 	RR *rp;
9927dd7cddfSDavid du Colombier 	DN *dp;
9937dd7cddfSDavid du Colombier 
9947dd7cddfSDavid du Colombier 	dp = dnlookup("local#dns#domains", class, 1);
9957dd7cddfSDavid du Colombier 	rp = rrlookup(dp, Tptr, NOneg);
9967dd7cddfSDavid du Colombier 	if(rp != nil)
9977dd7cddfSDavid du Colombier 		return rp;
9987dd7cddfSDavid du Colombier 
9997dd7cddfSDavid du Colombier 	t = lookupinfo("dnsdomain");
10007dd7cddfSDavid du Colombier 	if(t == nil)
10017dd7cddfSDavid du Colombier 		return nil;
10027dd7cddfSDavid du Colombier 	for(nt = t; nt != nil; nt = nt->entry)
10037dd7cddfSDavid du Colombier 		addlocaldnsdomain(dp, class, nt->val);
10047dd7cddfSDavid du Colombier 	ndbfree(t);
10057dd7cddfSDavid du Colombier 
10067dd7cddfSDavid du Colombier 	return rrlookup(dp, Tptr, NOneg);
10077dd7cddfSDavid du Colombier }
10083ff48bf5SDavid du Colombier 
10093ff48bf5SDavid du Colombier char *v4ptrdom = ".in-addr.arpa";
10107def40e1SDavid du Colombier char *v6ptrdom = ".ip6.arpa";		/* ip6.int deprecated, rfc 3152 */
10113ff48bf5SDavid du Colombier 
10123ff48bf5SDavid du Colombier char *attribs[] = {
10133ff48bf5SDavid du Colombier 	"ipmask",
10143ff48bf5SDavid du Colombier 	0
10153ff48bf5SDavid du Colombier };
10163ff48bf5SDavid du Colombier 
10173ff48bf5SDavid du Colombier /*
101853874d13SDavid du Colombier  *  create ptrs that are in our v4 areas
10193ff48bf5SDavid du Colombier  */
10203ff48bf5SDavid du Colombier static void
102153874d13SDavid du Colombier createv4ptrs(void)
10223ff48bf5SDavid du Colombier {
10233ff48bf5SDavid du Colombier 	int len, dlen, n;
102453874d13SDavid du Colombier 	char *dom;
10254f8f669cSDavid du Colombier 	char buf[Domlen+1], ipa[48];
10266b0d5c8bSDavid du Colombier 	char *f[40];
10274f8f669cSDavid du Colombier 	uchar net[IPaddrlen], mask[IPaddrlen];
10284f8f669cSDavid du Colombier 	Area *s;
10293ff48bf5SDavid du Colombier 	Ndbtuple *t, *nt;
10303ff48bf5SDavid du Colombier 
10313ff48bf5SDavid du Colombier 	dlen = strlen(v4ptrdom);
10323ff48bf5SDavid du Colombier 	for(s = owned; s; s = s->next){
103353874d13SDavid du Colombier 		dom = s->soarr->owner->name;
103453874d13SDavid du Colombier 		len = strlen(dom);
103553874d13SDavid du Colombier 		if((len <= dlen || cistrcmp(dom+len-dlen, v4ptrdom) != 0) &&
103653874d13SDavid du Colombier 		    cistrcmp(dom, v4ptrdom+1) != 0)
10373ff48bf5SDavid du Colombier 			continue;
10383ff48bf5SDavid du Colombier 
10393ff48bf5SDavid du Colombier 		/* get mask and net value */
104053874d13SDavid du Colombier 		strncpy(buf, dom, sizeof buf);
10414f8f669cSDavid du Colombier 		buf[sizeof buf-1] = 0;
104253874d13SDavid du Colombier 		/* buf contains something like 178.204.in-addr.arpa (n==4) */
10433ff48bf5SDavid du Colombier 		n = getfields(buf, f, nelem(f), 0, ".");
10443ff48bf5SDavid du Colombier 		memset(mask, 0xff, IPaddrlen);
10453ff48bf5SDavid du Colombier 		ipmove(net, v4prefix);
10463ff48bf5SDavid du Colombier 		switch(n){
10473ff48bf5SDavid du Colombier 		case 3:			/* /8 */
10483ff48bf5SDavid du Colombier 			net[IPv4off] = atoi(f[0]);
10493ff48bf5SDavid du Colombier 			mask[IPv4off+1] = 0;
10503ff48bf5SDavid du Colombier 			mask[IPv4off+2] = 0;
10513ff48bf5SDavid du Colombier 			mask[IPv4off+3] = 0;
10523ff48bf5SDavid du Colombier 			break;
10533ff48bf5SDavid du Colombier 		case 4:			/* /16 */
10543ff48bf5SDavid du Colombier 			net[IPv4off] = atoi(f[1]);
10553ff48bf5SDavid du Colombier 			net[IPv4off+1] = atoi(f[0]);
10563ff48bf5SDavid du Colombier 			mask[IPv4off+2] = 0;
10573ff48bf5SDavid du Colombier 			mask[IPv4off+3] = 0;
10583ff48bf5SDavid du Colombier 			break;
10593ff48bf5SDavid du Colombier 		case 5:			/* /24 */
10603ff48bf5SDavid du Colombier 			net[IPv4off] = atoi(f[2]);
10613ff48bf5SDavid du Colombier 			net[IPv4off+1] = atoi(f[1]);
10623ff48bf5SDavid du Colombier 			net[IPv4off+2] = atoi(f[0]);
10633ff48bf5SDavid du Colombier 			mask[IPv4off+3] = 0;
10643ff48bf5SDavid du Colombier 			break;
1065225077b0SDavid du Colombier 		case 6:		/* rfc2317: classless in-addr.arpa delegation */
10663ff48bf5SDavid du Colombier 			net[IPv4off] = atoi(f[3]);
10673ff48bf5SDavid du Colombier 			net[IPv4off+1] = atoi(f[2]);
10683ff48bf5SDavid du Colombier 			net[IPv4off+2] = atoi(f[1]);
10693ff48bf5SDavid du Colombier 			net[IPv4off+3] = atoi(f[0]);
10703ff48bf5SDavid du Colombier 			sprint(ipa, "%I", net);
10713ff48bf5SDavid du Colombier 			t = ndbipinfo(db, "ip", ipa, attribs, 1);
107208fd2d13SDavid du Colombier 			if(t == nil)	/* could be a reverse with no forward */
107308fd2d13SDavid du Colombier 				continue;
10743ff48bf5SDavid du Colombier 			nt = look(t, t, "ipmask");
10753ff48bf5SDavid du Colombier 			if(nt == nil){		/* we're confused */
10763ff48bf5SDavid du Colombier 				ndbfree(t);
10773ff48bf5SDavid du Colombier 				continue;
10783ff48bf5SDavid du Colombier 			}
10793ff48bf5SDavid du Colombier 			parseipmask(mask, nt->val);
1080018fc28bSDavid du Colombier 			ndbfree(t);
10813ff48bf5SDavid du Colombier 			n = 5;
10823ff48bf5SDavid du Colombier 			break;
10833ff48bf5SDavid du Colombier 		default:
10843ff48bf5SDavid du Colombier 			continue;
10853ff48bf5SDavid du Colombier 		}
10863ff48bf5SDavid du Colombier 
10874f8f669cSDavid du Colombier 		/*
10884f8f669cSDavid du Colombier 		 * go through all domain entries looking for RR's
108953874d13SDavid du Colombier 		 * in this network and create ptrs.
109053874d13SDavid du Colombier 		 * +2 for ".in-addr.arpa".
10914f8f669cSDavid du Colombier 		 */
1092617c0e1eSDavid du Colombier 		dnptr(net, mask, dom, Ta, 4+2-n, Ptrttl);
10933ff48bf5SDavid du Colombier 	}
10943ff48bf5SDavid du Colombier }
10954f8f669cSDavid du Colombier 
109653874d13SDavid du Colombier /* convert bytes to nibbles, big-endian */
109753874d13SDavid du Colombier void
109853874d13SDavid du Colombier bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes)
109953874d13SDavid du Colombier {
110053874d13SDavid du Colombier 	while (nbytes-- > 0) {
110153874d13SDavid du Colombier 		*nibbles++ = *bytes >> Nibwidth;
110253874d13SDavid du Colombier 		*nibbles++ = *bytes++ & Nibmask;
110353874d13SDavid du Colombier 	}
110453874d13SDavid du Colombier }
110553874d13SDavid du Colombier 
110653874d13SDavid du Colombier void
110753874d13SDavid du Colombier nibbles2bytes(uchar *bytes, uchar *nibbles, int nnibs)
110853874d13SDavid du Colombier {
110953874d13SDavid du Colombier 	for (; nnibs >= 2; nnibs -= 2) {
111053874d13SDavid du Colombier 		*bytes++ = nibbles[0] << Nibwidth | (nibbles[1]&Nibmask);
111153874d13SDavid du Colombier 		nibbles += 2;
111253874d13SDavid du Colombier 	}
111353874d13SDavid du Colombier 	if (nnibs > 0)
111453874d13SDavid du Colombier 		*bytes = nibbles[0] << Nibwidth;
111553874d13SDavid du Colombier }
111653874d13SDavid du Colombier 
111753874d13SDavid du Colombier /*
111853874d13SDavid du Colombier  *  create ptrs that are in our v6 areas.  see rfc3596
111953874d13SDavid du Colombier  */
112053874d13SDavid du Colombier static void
112153874d13SDavid du Colombier createv6ptrs(void)
112253874d13SDavid du Colombier {
112353874d13SDavid du Colombier 	int len, dlen, i, n, pfxnibs;
112453874d13SDavid du Colombier 	char *dom;
112553874d13SDavid du Colombier 	char buf[Domlen+1];
112653874d13SDavid du Colombier 	char *f[40];
112753874d13SDavid du Colombier 	uchar net[IPaddrlen], mask[IPaddrlen];
112853874d13SDavid du Colombier 	uchar nibnet[IPaddrlen*2], nibmask[IPaddrlen*2];
112953874d13SDavid du Colombier 	Area *s;
113053874d13SDavid du Colombier 
113153874d13SDavid du Colombier 	dlen = strlen(v6ptrdom);
113253874d13SDavid du Colombier 	for(s = owned; s; s = s->next){
113353874d13SDavid du Colombier 		dom = s->soarr->owner->name;
113453874d13SDavid du Colombier 		len = strlen(dom);
113553874d13SDavid du Colombier 		if((len <= dlen || cistrcmp(dom+len-dlen, v6ptrdom) != 0) &&
113653874d13SDavid du Colombier 		    cistrcmp(dom, v6ptrdom+1) != 0)
113753874d13SDavid du Colombier 			continue;
113853874d13SDavid du Colombier 
113953874d13SDavid du Colombier 		/* get mask and net value */
114053874d13SDavid du Colombier 		strncpy(buf, dom, sizeof buf);
114153874d13SDavid du Colombier 		buf[sizeof buf-1] = 0;
114253874d13SDavid du Colombier 		/* buf contains something like 2.0.0.2.ip6.arpa (n==6) */
114353874d13SDavid du Colombier 		n = getfields(buf, f, nelem(f), 0, ".");
11444f927735SDavid du Colombier 		pfxnibs = n - 2;		/* 2 for .ip6.arpa */
114553874d13SDavid du Colombier 		if (pfxnibs < 0 || pfxnibs > V6maxrevdomdepth)
114653874d13SDavid du Colombier 			continue;
114753874d13SDavid du Colombier 
114853874d13SDavid du Colombier 		memset(net, 0, IPaddrlen);
114953874d13SDavid du Colombier 		memset(mask, 0xff, IPaddrlen);
115053874d13SDavid du Colombier 		bytes2nibbles(nibnet, net, IPaddrlen);
115153874d13SDavid du Colombier 		bytes2nibbles(nibmask, mask, IPaddrlen);
115253874d13SDavid du Colombier 
115353874d13SDavid du Colombier 		/* copy prefix of f, in reverse order, to start of net. */
115453874d13SDavid du Colombier 		for (i = 0; i < pfxnibs; i++)
115553874d13SDavid du Colombier 			nibnet[i] = strtol(f[pfxnibs - 1 - i], nil, 16);
115653874d13SDavid du Colombier 		/* zero nibbles of mask after prefix in net */
115753874d13SDavid du Colombier 		memset(nibmask + pfxnibs, 0, V6maxrevdomdepth - pfxnibs);
115853874d13SDavid du Colombier 
115953874d13SDavid du Colombier 		nibbles2bytes(net, nibnet, 2*IPaddrlen);
116053874d13SDavid du Colombier 		nibbles2bytes(mask, nibmask, 2*IPaddrlen);
116153874d13SDavid du Colombier 
116253874d13SDavid du Colombier 		/*
116353874d13SDavid du Colombier 		 * go through all domain entries looking for RR's
116453874d13SDavid du Colombier 		 * in this network and create ptrs.
116553874d13SDavid du Colombier 		 */
1166617c0e1eSDavid du Colombier 		dnptr(net, mask, dom, Taaaa, V6maxrevdomdepth - pfxnibs, Ptrttl);
116753874d13SDavid du Colombier 	}
116853874d13SDavid du Colombier }
116953874d13SDavid du Colombier 
117053874d13SDavid du Colombier /*
117153874d13SDavid du Colombier  *  create ptrs that are in our areas
117253874d13SDavid du Colombier  */
117353874d13SDavid du Colombier static void
117453874d13SDavid du Colombier createptrs(void)
117553874d13SDavid du Colombier {
117653874d13SDavid du Colombier 	createv4ptrs();
117753874d13SDavid du Colombier 	createv6ptrs();
117853874d13SDavid du Colombier }
117953874d13SDavid du Colombier 
11804f8f669cSDavid du Colombier /*
11814f8f669cSDavid du Colombier  * is this domain (or DOMAIN or Domain or dOMAIN)
11824f8f669cSDavid du Colombier  * internal to our organisation (behind our firewall)?
11834f8f669cSDavid du Colombier  * only inside straddling servers care, everybody else gets told `yes',
11844f8f669cSDavid du Colombier  * so they'll use mntpt for their queries.
11854f8f669cSDavid du Colombier  */
11864f8f669cSDavid du Colombier int
11874f8f669cSDavid du Colombier insideaddr(char *dom)
11884f8f669cSDavid du Colombier {
11894f8f669cSDavid du Colombier 	int domlen, vallen, rv;
11904f8f669cSDavid du Colombier 	Ndbtuple *t;
11914f8f669cSDavid du Colombier 
11924f8f669cSDavid du Colombier 	if (!cfg.inside || !cfg.straddle || !cfg.serve)
11934f8f669cSDavid du Colombier 		return 1;
11944f8f669cSDavid du Colombier 
11954f8f669cSDavid du Colombier 	lock(&dblock);
11964f8f669cSDavid du Colombier 	if (indoms == nil)
11974f8f669cSDavid du Colombier 		loaddomsrvs();
11984f8f669cSDavid du Colombier 	if (indoms == nil) {
11994f8f669cSDavid du Colombier 		unlock(&dblock);
12004f8f669cSDavid du Colombier 		return 1;	/* no "inside" sys, try inside nameservers */
12014f8f669cSDavid du Colombier 	}
12024f8f669cSDavid du Colombier 
12034f8f669cSDavid du Colombier 	rv = 0;
12044f8f669cSDavid du Colombier 	domlen = strlen(dom);
12054f8f669cSDavid du Colombier 	for (t = indoms; t != nil; t = t->entry) {
12064f8f669cSDavid du Colombier 		if (strcmp(t->attr, "dom") != 0)
12074f8f669cSDavid du Colombier 			continue;
12084f8f669cSDavid du Colombier 		vallen = strlen(t->val);
12094f8f669cSDavid du Colombier 		if (cistrcmp(dom, t->val) == 0 ||
12104f8f669cSDavid du Colombier 		    domlen > vallen &&
12114f8f669cSDavid du Colombier 		     cistrcmp(dom + domlen - vallen, t->val) == 0 &&
12124f8f669cSDavid du Colombier 		     dom[domlen - vallen - 1] == '.') {
12134f8f669cSDavid du Colombier 			rv = 1;
12144f8f669cSDavid du Colombier 			break;
12154f8f669cSDavid du Colombier 		}
12164f8f669cSDavid du Colombier 	}
12174f8f669cSDavid du Colombier 	unlock(&dblock);
12184f8f669cSDavid du Colombier 	return rv;
12194f8f669cSDavid du Colombier }
12204f8f669cSDavid du Colombier 
12214f8f669cSDavid du Colombier int
12224f8f669cSDavid du Colombier insidens(uchar *ip)
12234f8f669cSDavid du Colombier {
12244f8f669cSDavid du Colombier 	uchar ipa[IPaddrlen];
12254f8f669cSDavid du Colombier 	Ndbtuple *t;
12264f8f669cSDavid du Colombier 
12274f8f669cSDavid du Colombier 	for (t = innmsrvs; t != nil; t = t->entry)
12284f8f669cSDavid du Colombier 		if (strcmp(t->attr, "ip") == 0) {
12294f8f669cSDavid du Colombier 			parseip(ipa, t->val);
12304f8f669cSDavid du Colombier 			if (memcmp(ipa, ip, sizeof ipa) == 0)
12314f8f669cSDavid du Colombier 				return 1;
12324f8f669cSDavid du Colombier 		}
12334f8f669cSDavid du Colombier 	return 0;
12344f8f669cSDavid du Colombier }
12354f8f669cSDavid du Colombier 
12364f8f669cSDavid du Colombier uchar *
12374f8f669cSDavid du Colombier outsidens(int n)
12384f8f669cSDavid du Colombier {
12394f8f669cSDavid du Colombier 	int i;
12404f8f669cSDavid du Colombier 	Ndbtuple *t;
12414f8f669cSDavid du Colombier 	static uchar ipa[IPaddrlen];
12424f8f669cSDavid du Colombier 
12434f8f669cSDavid du Colombier 	i = 0;
12444f8f669cSDavid du Colombier 	for (t = outnmsrvs; t != nil; t = t->entry)
12454f8f669cSDavid du Colombier 		if (strcmp(t->attr, "ip") == 0 && i++ == n) {
12464f8f669cSDavid du Colombier 			parseip(ipa, t->val);
12474f8f669cSDavid du Colombier 			return ipa;
12484f8f669cSDavid du Colombier 		}
12494f8f669cSDavid du Colombier 	return nil;
12504f8f669cSDavid du Colombier }
1251