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
nstrcpy(char * to,char * from,int len)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
opendatabase(void)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*
dblookup(char * name,int class,int type,int auth,int ttl)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;
1033e12c5d1SDavid du Colombier
1043e12c5d1SDavid du Colombier /* so far only internet lookups are implemented */
1053e12c5d1SDavid du Colombier if(class != Cin)
1063e12c5d1SDavid du Colombier return 0;
1073e12c5d1SDavid du Colombier
1087dd7cddfSDavid du Colombier err = Rname;
109*c3617180SDavid du Colombier rp = nil;
1107dd7cddfSDavid du Colombier
111219b2ee8SDavid du Colombier if(type == Tall){
1127dd7cddfSDavid du Colombier for (type = Ta; type < Tall; type++)
113*c3617180SDavid du Colombier if(implemented[type]) {
114*c3617180SDavid du Colombier tp = dblookup(name, class, type, auth, ttl);
115*c3617180SDavid du Colombier lock(&dnlock);
116*c3617180SDavid du Colombier rrcat(&rp, tp);
117530fef66SDavid du Colombier unlock(&dnlock);
118*c3617180SDavid du Colombier }
119219b2ee8SDavid du Colombier return rp;
120219b2ee8SDavid du Colombier }
121bd389b36SDavid du Colombier
122219b2ee8SDavid du Colombier lock(&dblock);
1233ff48bf5SDavid du Colombier dp = dnlookup(name, class, 1);
1244f8f669cSDavid du Colombier
1257dd7cddfSDavid du Colombier if(opendatabase() < 0)
126bd389b36SDavid du Colombier goto out;
1277dd7cddfSDavid du Colombier if(dp->rr)
1287dd7cddfSDavid du Colombier err = 0;
1293e12c5d1SDavid du Colombier
1303e12c5d1SDavid du Colombier /* first try the given name */
1314f8f669cSDavid du Colombier if(cfg.cachedb)
1327dd7cddfSDavid du Colombier rp = rrlookup(dp, type, NOneg);
1337dd7cddfSDavid du Colombier else
1343ff48bf5SDavid du Colombier rp = dblookup1(name, type, auth, ttl);
1353e12c5d1SDavid du Colombier if(rp)
136bd389b36SDavid du Colombier goto out;
1373e12c5d1SDavid du Colombier
1383e12c5d1SDavid du Colombier /* try lower case version */
1393e12c5d1SDavid du Colombier for(cp = name; *cp; cp++)
1403e12c5d1SDavid du Colombier *cp = tolower(*cp);
1414f8f669cSDavid du Colombier if(cfg.cachedb)
1427dd7cddfSDavid du Colombier rp = rrlookup(dp, type, NOneg);
1437dd7cddfSDavid du Colombier else
1443ff48bf5SDavid du Colombier rp = dblookup1(name, type, auth, ttl);
1453e12c5d1SDavid du Colombier if(rp)
146bd389b36SDavid du Colombier goto out;
1473e12c5d1SDavid du Colombier
1487dd7cddfSDavid du Colombier /* walk the domain name trying the wildcard '*' at each position */
1497dd7cddfSDavid du Colombier for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
1504f8f669cSDavid du Colombier snprint(buf, sizeof buf, "*%s", wild);
1517dd7cddfSDavid du Colombier ndp = dnlookup(buf, class, 1);
1527dd7cddfSDavid du Colombier if(ndp->rr)
1537dd7cddfSDavid du Colombier err = 0;
1544f8f669cSDavid du Colombier if(cfg.cachedb)
1557dd7cddfSDavid du Colombier rp = rrlookup(ndp, type, NOneg);
1567dd7cddfSDavid du Colombier else
1577dd7cddfSDavid du Colombier rp = dblookup1(buf, type, auth, ttl);
1587dd7cddfSDavid du Colombier if(rp)
1597dd7cddfSDavid du Colombier break;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier out:
1627dd7cddfSDavid du Colombier /* add owner to uncached records */
1634f8f669cSDavid du Colombier if(rp)
1643e12c5d1SDavid du Colombier for(tp = rp; tp; tp = tp->next)
1653e12c5d1SDavid du Colombier tp->owner = dp;
1664f8f669cSDavid du Colombier else {
167a41547ffSDavid du Colombier /*
168a41547ffSDavid du Colombier * don't call it non-existent if it's not ours
169a41547ffSDavid du Colombier * (unless we're a resolver).
170a41547ffSDavid du Colombier */
171a41547ffSDavid du Colombier if(err == Rname && (!inmyarea(name) || cfg.resolver))
172271b8d73SDavid du Colombier err = Rserver;
1734f8f669cSDavid du Colombier dp->respcode = err;
174fb7f0c93SDavid du Colombier }
1757dd7cddfSDavid du Colombier
176bd389b36SDavid du Colombier unlock(&dblock);
1773e12c5d1SDavid du Colombier return rp;
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier
1804f8f669cSDavid du Colombier static ulong
intval(Ndbtuple * entry,Ndbtuple * pair,char * attr,ulong def)1814f8f669cSDavid du Colombier intval(Ndbtuple *entry, Ndbtuple *pair, char *attr, ulong def)
1824f8f669cSDavid du Colombier {
1834f8f669cSDavid du Colombier Ndbtuple *t = look(entry, pair, attr);
1844f8f669cSDavid du Colombier
1854f8f669cSDavid du Colombier return (t? strtoul(t->val, 0, 10): def);
1864f8f669cSDavid du Colombier }
1874f8f669cSDavid du Colombier
1883e12c5d1SDavid du Colombier /*
1893e12c5d1SDavid du Colombier * lookup an RR in the network database
1903e12c5d1SDavid du Colombier */
1913e12c5d1SDavid du Colombier static RR*
dblookup1(char * name,int type,int auth,int ttl)1927dd7cddfSDavid du Colombier dblookup1(char *name, int type, int auth, int ttl)
1933e12c5d1SDavid du Colombier {
1943e12c5d1SDavid du Colombier Ndbtuple *t, *nt;
1953e12c5d1SDavid du Colombier RR *rp, *list, **l;
1963e12c5d1SDavid du Colombier Ndbs s;
19757837e0bSDavid du Colombier char dname[Domlen];
1983e12c5d1SDavid du Colombier char *attr;
1993e12c5d1SDavid du Colombier DN *dp;
2003e12c5d1SDavid du Colombier RR *(*f)(Ndbtuple*, Ndbtuple*);
2017dd7cddfSDavid du Colombier int found, x;
2023e12c5d1SDavid du Colombier
2034f8f669cSDavid du Colombier dp = nil;
2043e12c5d1SDavid du Colombier switch(type){
2057dd7cddfSDavid du Colombier case Tptr:
2067dd7cddfSDavid du Colombier attr = "ptr";
2077dd7cddfSDavid du Colombier f = ptrrr;
2087dd7cddfSDavid du Colombier break;
2093e12c5d1SDavid du Colombier case Ta:
2103e12c5d1SDavid du Colombier attr = "ip";
2113e12c5d1SDavid du Colombier f = addrrr;
2123e12c5d1SDavid du Colombier break;
213d9924332SDavid du Colombier case Taaaa:
214d9924332SDavid du Colombier attr = "ipv6";
215d9924332SDavid du Colombier f = addrrr;
216d9924332SDavid du Colombier break;
2179a747e4fSDavid du Colombier case Tnull:
2189a747e4fSDavid du Colombier attr = "nullrr";
2199a747e4fSDavid du Colombier f = nullrr;
2209a747e4fSDavid du Colombier break;
2213e12c5d1SDavid du Colombier case Tns:
2223e12c5d1SDavid du Colombier attr = "ns";
2233e12c5d1SDavid du Colombier f = nsrr;
2243e12c5d1SDavid du Colombier break;
2253e12c5d1SDavid du Colombier case Tsoa:
2263e12c5d1SDavid du Colombier attr = "soa";
2273e12c5d1SDavid du Colombier f = soarr;
2283e12c5d1SDavid du Colombier break;
2294f8f669cSDavid du Colombier case Tsrv:
2304f8f669cSDavid du Colombier attr = "srv";
2314f8f669cSDavid du Colombier f = srvrr;
2324f8f669cSDavid du Colombier break;
2333e12c5d1SDavid du Colombier case Tmx:
2343e12c5d1SDavid du Colombier attr = "mx";
2353e12c5d1SDavid du Colombier f = mxrr;
2363e12c5d1SDavid du Colombier break;
2377dd7cddfSDavid du Colombier case Tcname:
2387dd7cddfSDavid du Colombier attr = "cname";
2397dd7cddfSDavid du Colombier f = cnamerr;
2407dd7cddfSDavid du Colombier break;
2417dd7cddfSDavid du Colombier case Taxfr:
2427dd7cddfSDavid du Colombier case Tixfr:
2437dd7cddfSDavid du Colombier return doaxfr(db, name);
2443e12c5d1SDavid du Colombier default:
2454f8f669cSDavid du Colombier // dnslog("dnlookup1(%s) bad type", name);
2467dd7cddfSDavid du Colombier return nil;
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier
2493e12c5d1SDavid du Colombier /*
2503e12c5d1SDavid du Colombier * find a matching entry in the database
2513e12c5d1SDavid du Colombier */
2524f8f669cSDavid du Colombier t = nil;
25357837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "dom", name, attr, &t));
254219b2ee8SDavid du Colombier
255219b2ee8SDavid du Colombier /*
256219b2ee8SDavid du Colombier * hack for local names
257219b2ee8SDavid du Colombier */
2584f8f669cSDavid du Colombier if(t == nil && strchr(name, '.') == nil)
25957837e0bSDavid du Colombier free(ndbgetvalue(db, &s, "sys", name, attr, &t));
2604f8f669cSDavid du Colombier if(t == nil) {
2614f8f669cSDavid du Colombier // dnslog("dnlookup1(%s) name not found", name);
2627dd7cddfSDavid du Colombier return nil;
2634f8f669cSDavid du Colombier }
2647dd7cddfSDavid du Colombier
2657dd7cddfSDavid du Colombier /* search whole entry for default domain name */
26657837e0bSDavid du Colombier strncpy(dname, name, sizeof dname);
2677dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry)
2687dd7cddfSDavid du Colombier if(strcmp(nt->attr, "dom") == 0){
26957837e0bSDavid du Colombier nstrcpy(dname, nt->val, sizeof dname);
2707dd7cddfSDavid du Colombier break;
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier
2737dd7cddfSDavid du Colombier /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
2744f8f669cSDavid du Colombier x = intval(t, s.t, "ttl", 0);
2757dd7cddfSDavid du Colombier if(x > ttl)
2767dd7cddfSDavid du Colombier ttl = x;
2777dd7cddfSDavid du Colombier
2787dd7cddfSDavid du Colombier /* default ttl is one day */
2797dd7cddfSDavid du Colombier if(ttl < 0)
2807dd7cddfSDavid du Colombier ttl = DEFTTL;
2813e12c5d1SDavid du Colombier
2823e12c5d1SDavid du Colombier /*
2833e12c5d1SDavid du Colombier * The database has 2 levels of precedence; line and entry.
2843e12c5d1SDavid du Colombier * Pairs on the same line bind tighter than pairs in the
2853e12c5d1SDavid du Colombier * same entry, so we search the line first.
2863e12c5d1SDavid du Colombier */
2877dd7cddfSDavid du Colombier found = 0;
2883e12c5d1SDavid du Colombier list = 0;
2893e12c5d1SDavid du Colombier l = &list;
2903e12c5d1SDavid du Colombier for(nt = s.t;; ){
2917dd7cddfSDavid du Colombier if(found == 0 && strcmp(nt->attr, "dom") == 0){
29257837e0bSDavid du Colombier nstrcpy(dname, nt->val, sizeof dname);
2937dd7cddfSDavid du Colombier found = 1;
2947dd7cddfSDavid du Colombier }
2953e12c5d1SDavid du Colombier if(cistrcmp(attr, nt->attr) == 0){
2963e12c5d1SDavid du Colombier rp = (*f)(t, nt);
2973e12c5d1SDavid du Colombier rp->auth = auth;
2983e12c5d1SDavid du Colombier rp->db = 1;
2997dd7cddfSDavid du Colombier if(ttl)
3007dd7cddfSDavid du Colombier rp->ttl = ttl;
3014f8f669cSDavid du Colombier if(dp == nil)
3027dd7cddfSDavid du Colombier dp = dnlookup(dname, Cin, 1);
3033e12c5d1SDavid du Colombier rp->owner = dp;
3043e12c5d1SDavid du Colombier *l = rp;
3053e12c5d1SDavid du Colombier l = &rp->next;
3063e12c5d1SDavid du Colombier nt->ptr = 1;
3073e12c5d1SDavid du Colombier }
3083e12c5d1SDavid du Colombier nt = nt->line;
3093e12c5d1SDavid du Colombier if(nt == s.t)
3103e12c5d1SDavid du Colombier break;
3113e12c5d1SDavid du Colombier }
3123e12c5d1SDavid du Colombier
3133e12c5d1SDavid du Colombier /* search whole entry */
3143e12c5d1SDavid du Colombier for(nt = t; nt; nt = nt->entry)
3153e12c5d1SDavid du Colombier if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
3163e12c5d1SDavid du Colombier rp = (*f)(t, nt);
3173e12c5d1SDavid du Colombier rp->db = 1;
3187dd7cddfSDavid du Colombier if(ttl)
3197dd7cddfSDavid du Colombier rp->ttl = ttl;
3203e12c5d1SDavid du Colombier rp->auth = auth;
3214f8f669cSDavid du Colombier if(dp == nil)
3227dd7cddfSDavid du Colombier dp = dnlookup(dname, Cin, 1);
3233e12c5d1SDavid du Colombier rp->owner = dp;
3243e12c5d1SDavid du Colombier *l = rp;
3253e12c5d1SDavid du Colombier l = &rp->next;
3263e12c5d1SDavid du Colombier }
3273e12c5d1SDavid du Colombier ndbfree(t);
3283e12c5d1SDavid du Colombier
3294f8f669cSDavid du Colombier // dnslog("dnlookup1(%s) -> %#p", name, list);
3303e12c5d1SDavid du Colombier return list;
3313e12c5d1SDavid du Colombier }
3323e12c5d1SDavid du Colombier
3333e12c5d1SDavid du Colombier /*
3343e12c5d1SDavid du Colombier * make various types of resource records from a database entry
3353e12c5d1SDavid du Colombier */
3363e12c5d1SDavid du Colombier static RR*
addrrr(Ndbtuple * entry,Ndbtuple * pair)3373e12c5d1SDavid du Colombier addrrr(Ndbtuple *entry, Ndbtuple *pair)
3383e12c5d1SDavid du Colombier {
3393e12c5d1SDavid du Colombier RR *rp;
3405d459b5aSDavid du Colombier uchar addr[IPaddrlen];
3413e12c5d1SDavid du Colombier
3423e12c5d1SDavid du Colombier USED(entry);
3435d459b5aSDavid du Colombier parseip(addr, pair->val);
3445d459b5aSDavid du Colombier if(isv4(addr))
3453e12c5d1SDavid du Colombier rp = rralloc(Ta);
3465d459b5aSDavid du Colombier else
3475d459b5aSDavid du Colombier rp = rralloc(Taaaa);
3483e12c5d1SDavid du Colombier rp->ip = dnlookup(pair->val, Cin, 1);
3493e12c5d1SDavid du Colombier return rp;
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier static RR*
nullrr(Ndbtuple * entry,Ndbtuple * pair)3529a747e4fSDavid du Colombier nullrr(Ndbtuple *entry, Ndbtuple *pair)
3539a747e4fSDavid du Colombier {
3549a747e4fSDavid du Colombier RR *rp;
3559a747e4fSDavid du Colombier
3569a747e4fSDavid du Colombier USED(entry);
3579a747e4fSDavid du Colombier rp = rralloc(Tnull);
3589a747e4fSDavid du Colombier rp->null->data = (uchar*)estrdup(pair->val);
3599a747e4fSDavid du Colombier rp->null->dlen = strlen((char*)rp->null->data);
3609a747e4fSDavid du Colombier return rp;
3619a747e4fSDavid du Colombier }
36260845620SDavid du Colombier /*
36360845620SDavid du Colombier * txt rr strings are at most 255 bytes long. one
36460845620SDavid du Colombier * can represent longer strings by multiple concatenated
36560845620SDavid du Colombier * <= 255 byte ones.
36660845620SDavid du Colombier */
3679a747e4fSDavid du Colombier static RR*
txtrr(Ndbtuple * entry,Ndbtuple * pair)3689a747e4fSDavid du Colombier txtrr(Ndbtuple *entry, Ndbtuple *pair)
3699a747e4fSDavid du Colombier {
3709a747e4fSDavid du Colombier RR *rp;
37160845620SDavid du Colombier Txt *t, **l;
37260845620SDavid du Colombier int i, len, sofar;
3739a747e4fSDavid du Colombier
3749a747e4fSDavid du Colombier USED(entry);
3759a747e4fSDavid du Colombier rp = rralloc(Ttxt);
37660845620SDavid du Colombier l = &rp->txt;
37760845620SDavid du Colombier rp->txt = nil;
37860845620SDavid du Colombier len = strlen(pair->val);
37960845620SDavid du Colombier sofar = 0;
38060845620SDavid du Colombier while(len > sofar){
38160845620SDavid du Colombier t = emalloc(sizeof(*t));
38260845620SDavid du Colombier t->next = nil;
38360845620SDavid du Colombier
38460845620SDavid du Colombier i = len-sofar;
38560845620SDavid du Colombier if(i > 255)
38660845620SDavid du Colombier i = 255;
38760845620SDavid du Colombier
38860845620SDavid du Colombier t->p = emalloc(i+1);
38960845620SDavid du Colombier memmove(t->p, pair->val+sofar, i);
39060845620SDavid du Colombier t->p[i] = 0;
39160845620SDavid du Colombier sofar += i;
39260845620SDavid du Colombier
39360845620SDavid du Colombier *l = t;
39460845620SDavid du Colombier l = &t->next;
39560845620SDavid du Colombier }
3969a747e4fSDavid du Colombier return rp;
3979a747e4fSDavid du Colombier }
3989a747e4fSDavid du Colombier static RR*
cnamerr(Ndbtuple * entry,Ndbtuple * pair)3997dd7cddfSDavid du Colombier cnamerr(Ndbtuple *entry, Ndbtuple *pair)
4007dd7cddfSDavid du Colombier {
4017dd7cddfSDavid du Colombier RR *rp;
4027dd7cddfSDavid du Colombier
4037dd7cddfSDavid du Colombier USED(entry);
4047dd7cddfSDavid du Colombier rp = rralloc(Tcname);
4057dd7cddfSDavid du Colombier rp->host = dnlookup(pair->val, Cin, 1);
4067dd7cddfSDavid du Colombier return rp;
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier static RR*
mxrr(Ndbtuple * entry,Ndbtuple * pair)4093e12c5d1SDavid du Colombier mxrr(Ndbtuple *entry, Ndbtuple *pair)
4103e12c5d1SDavid du Colombier {
4113e12c5d1SDavid du Colombier RR *rp;
4123e12c5d1SDavid du Colombier
4133e12c5d1SDavid du Colombier rp = rralloc(Tmx);
4143e12c5d1SDavid du Colombier rp->host = dnlookup(pair->val, Cin, 1);
4154f8f669cSDavid du Colombier rp->pref = intval(entry, pair, "pref", 1);
4163e12c5d1SDavid du Colombier return rp;
4173e12c5d1SDavid du Colombier }
4183e12c5d1SDavid du Colombier static RR*
nsrr(Ndbtuple * entry,Ndbtuple * pair)4193e12c5d1SDavid du Colombier nsrr(Ndbtuple *entry, Ndbtuple *pair)
4203e12c5d1SDavid du Colombier {
4213e12c5d1SDavid du Colombier RR *rp;
4227dd7cddfSDavid du Colombier Ndbtuple *t;
4233e12c5d1SDavid du Colombier
4243e12c5d1SDavid du Colombier rp = rralloc(Tns);
4253e12c5d1SDavid du Colombier rp->host = dnlookup(pair->val, Cin, 1);
4267dd7cddfSDavid du Colombier t = look(entry, pair, "soa");
4277dd7cddfSDavid du Colombier if(t && t->val[0] == 0)
4283e12c5d1SDavid du Colombier rp->local = 1;
4293e12c5d1SDavid du Colombier return rp;
4303e12c5d1SDavid du Colombier }
4317dd7cddfSDavid du Colombier static RR*
ptrrr(Ndbtuple * entry,Ndbtuple * pair)4327dd7cddfSDavid du Colombier ptrrr(Ndbtuple *entry, Ndbtuple *pair)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier RR *rp;
4353e12c5d1SDavid du Colombier
4367dd7cddfSDavid du Colombier USED(entry);
4377dd7cddfSDavid du Colombier rp = rralloc(Tns);
4387dd7cddfSDavid du Colombier rp->ptr = dnlookup(pair->val, Cin, 1);
4397dd7cddfSDavid du Colombier return rp;
4407dd7cddfSDavid du Colombier }
4413e12c5d1SDavid du Colombier static RR*
soarr(Ndbtuple * entry,Ndbtuple * pair)4423e12c5d1SDavid du Colombier soarr(Ndbtuple *entry, Ndbtuple *pair)
4433e12c5d1SDavid du Colombier {
4443e12c5d1SDavid du Colombier RR *rp;
4457dd7cddfSDavid du Colombier Ndbtuple *ns, *mb, *t;
4463e12c5d1SDavid du Colombier char mailbox[Domlen];
4477dd7cddfSDavid du Colombier Ndb *ndb;
4487dd7cddfSDavid du Colombier char *p;
4493e12c5d1SDavid du Colombier
4503e12c5d1SDavid du Colombier rp = rralloc(Tsoa);
4517dd7cddfSDavid du Colombier rp->soa->serial = 1;
4527dd7cddfSDavid du Colombier for(ndb = db; ndb; ndb = ndb->next)
4537dd7cddfSDavid du Colombier if(ndb->mtime > rp->soa->serial)
4547dd7cddfSDavid du Colombier rp->soa->serial = ndb->mtime;
4554f8f669cSDavid du Colombier
4564f8f669cSDavid du Colombier rp->soa->retry = intval(entry, pair, "retry", Hour);
4574f8f669cSDavid du Colombier rp->soa->expire = intval(entry, pair, "expire", Day);
4584f8f669cSDavid du Colombier rp->soa->minttl = intval(entry, pair, "ttl", Day);
4594f8f669cSDavid du Colombier rp->soa->refresh = intval(entry, pair, "refresh", Day);
4604f8f669cSDavid du Colombier rp->soa->serial = intval(entry, pair, "serial", rp->soa->serial);
4617dd7cddfSDavid du Colombier
4623e12c5d1SDavid du Colombier ns = look(entry, pair, "ns");
4634f8f669cSDavid du Colombier if(ns == nil)
4643e12c5d1SDavid du Colombier ns = look(entry, pair, "dom");
4653e12c5d1SDavid du Colombier rp->host = dnlookup(ns->val, Cin, 1);
4667dd7cddfSDavid du Colombier
4677dd7cddfSDavid du Colombier /* accept all of:
4687dd7cddfSDavid du Colombier * mbox=person
4697dd7cddfSDavid du Colombier * mbox=person@machine.dom
4707dd7cddfSDavid du Colombier * mbox=person.machine.dom
4717dd7cddfSDavid du Colombier */
4727dd7cddfSDavid du Colombier mb = look(entry, pair, "mbox");
4737dd7cddfSDavid du Colombier if(mb == nil)
4743e12c5d1SDavid du Colombier mb = look(entry, pair, "mb");
4754f8f669cSDavid du Colombier if(mb)
4767dd7cddfSDavid du Colombier if(strchr(mb->val, '.')) {
4777dd7cddfSDavid du Colombier p = strchr(mb->val, '@');
4787dd7cddfSDavid du Colombier if(p != nil)
4797dd7cddfSDavid du Colombier *p = '.';
4803e12c5d1SDavid du Colombier rp->rmb = dnlookup(mb->val, Cin, 1);
4817dd7cddfSDavid du Colombier } else {
4824f8f669cSDavid du Colombier snprint(mailbox, sizeof mailbox, "%s.%s",
4837dd7cddfSDavid du Colombier mb->val, ns->val);
4843e12c5d1SDavid du Colombier rp->rmb = dnlookup(mailbox, Cin, 1);
4853e12c5d1SDavid du Colombier }
4864f8f669cSDavid du Colombier else {
4874f8f669cSDavid du Colombier snprint(mailbox, sizeof mailbox, "postmaster.%s", ns->val);
4883e12c5d1SDavid du Colombier rp->rmb = dnlookup(mailbox, Cin, 1);
4893e12c5d1SDavid du Colombier }
490dc5a79c1SDavid du Colombier
4914f8f669cSDavid du Colombier /*
4924f8f669cSDavid du Colombier * hang dns slaves off of the soa. this is
493dc5a79c1SDavid du Colombier * for managing the area.
494dc5a79c1SDavid du Colombier */
495dc5a79c1SDavid du Colombier for(t = entry; t != nil; t = t->entry)
496dc5a79c1SDavid du Colombier if(strcmp(t->attr, "dnsslave") == 0)
497dc5a79c1SDavid du Colombier addserver(&rp->soa->slaves, t->val);
498dc5a79c1SDavid du Colombier
4993e12c5d1SDavid du Colombier return rp;
5003e12c5d1SDavid du Colombier }
5013e12c5d1SDavid du Colombier
5024f8f669cSDavid du Colombier static RR*
srvrr(Ndbtuple * entry,Ndbtuple * pair)5034f8f669cSDavid du Colombier srvrr(Ndbtuple *entry, Ndbtuple *pair)
5044f8f669cSDavid du Colombier {
5054f8f669cSDavid du Colombier RR *rp;
5064f8f669cSDavid du Colombier
5074f8f669cSDavid du Colombier rp = rralloc(Tsrv);
508225077b0SDavid du Colombier rp->host = dnlookup(pair->val, Cin, 1);
5094f8f669cSDavid du Colombier rp->srv->pri = intval(entry, pair, "pri", 0);
5104f8f669cSDavid du Colombier rp->srv->weight = intval(entry, pair, "weight", 0);
51153874d13SDavid du Colombier /* TODO: translate service name to port # */
512225077b0SDavid du Colombier rp->port = intval(entry, pair, "port", 0);
5134f8f669cSDavid du Colombier return rp;
5144f8f669cSDavid du Colombier }
5154f8f669cSDavid du Colombier
5163e12c5d1SDavid du Colombier /*
5173e12c5d1SDavid du Colombier * Look for a pair with the given attribute. look first on the same line,
5183e12c5d1SDavid du Colombier * then in the whole entry.
5193e12c5d1SDavid du Colombier */
5203e12c5d1SDavid du Colombier static Ndbtuple*
look(Ndbtuple * entry,Ndbtuple * line,char * attr)5213e12c5d1SDavid du Colombier look(Ndbtuple *entry, Ndbtuple *line, char *attr)
5223e12c5d1SDavid du Colombier {
5233e12c5d1SDavid du Colombier Ndbtuple *nt;
5243e12c5d1SDavid du Colombier
5253e12c5d1SDavid du Colombier /* first look on same line (closer binding) */
5263e12c5d1SDavid du Colombier for(nt = line;;){
5273e12c5d1SDavid du Colombier if(cistrcmp(attr, nt->attr) == 0)
5283e12c5d1SDavid du Colombier return nt;
5293e12c5d1SDavid du Colombier nt = nt->line;
5303e12c5d1SDavid du Colombier if(nt == line)
5313e12c5d1SDavid du Colombier break;
5323e12c5d1SDavid du Colombier }
5333e12c5d1SDavid du Colombier /* search whole tuple */
5343e12c5d1SDavid du Colombier for(nt = entry; nt; nt = nt->entry)
5353e12c5d1SDavid du Colombier if(cistrcmp(attr, nt->attr) == 0)
5363e12c5d1SDavid du Colombier return nt;
5373e12c5d1SDavid du Colombier return 0;
5383e12c5d1SDavid du Colombier }
5393e12c5d1SDavid du Colombier
5407dd7cddfSDavid du Colombier static RR**
linkrr(RR * rp,DN * dp,RR ** l)5417dd7cddfSDavid du Colombier linkrr(RR *rp, DN *dp, RR **l)
5427dd7cddfSDavid du Colombier {
5437dd7cddfSDavid du Colombier rp->owner = dp;
5447dd7cddfSDavid du Colombier rp->auth = 1;
5457dd7cddfSDavid du Colombier rp->db = 1;
5467dd7cddfSDavid du Colombier *l = rp;
5477dd7cddfSDavid du Colombier return &rp->next;
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier
5507dd7cddfSDavid du Colombier /* these are answered specially by the tcp version */
5517dd7cddfSDavid du Colombier static RR*
doaxfr(Ndb * db,char * name)5527dd7cddfSDavid du Colombier doaxfr(Ndb *db, char *name)
5537dd7cddfSDavid du Colombier {
5547dd7cddfSDavid du Colombier USED(db, name);
5557dd7cddfSDavid du Colombier return 0;
5567dd7cddfSDavid du Colombier }
5577dd7cddfSDavid du Colombier
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier /*
5607dd7cddfSDavid du Colombier * read the all the soa's from the database to determine area's.
5617dd7cddfSDavid du Colombier * this is only used when we're not caching the database.
5627dd7cddfSDavid du Colombier */
5637dd7cddfSDavid du Colombier static void
dbfile2area(Ndb * db)5647dd7cddfSDavid du Colombier dbfile2area(Ndb *db)
5657dd7cddfSDavid du Colombier {
5667dd7cddfSDavid du Colombier Ndbtuple *t;
5677dd7cddfSDavid du Colombier
56859cc4ca5SDavid du Colombier if(debug)
5694f8f669cSDavid du Colombier dnslog("rereading %s", db->file);
5707dd7cddfSDavid du Colombier Bseek(&db->b, 0, 0);
5714f8f669cSDavid du Colombier while(t = ndbparse(db))
5727dd7cddfSDavid du Colombier ndbfree(t);
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier
5757dd7cddfSDavid du Colombier /*
5767dd7cddfSDavid du Colombier * read the database into the cache
5777dd7cddfSDavid du Colombier */
5787dd7cddfSDavid du Colombier static void
dbpair2cache(DN * dp,Ndbtuple * entry,Ndbtuple * pair)5797dd7cddfSDavid du Colombier dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
5807dd7cddfSDavid du Colombier {
5817dd7cddfSDavid du Colombier RR *rp;
5823ff48bf5SDavid du Colombier static ulong ord;
5837dd7cddfSDavid du Colombier
5847dd7cddfSDavid du Colombier rp = 0;
585d9924332SDavid du Colombier if(cistrcmp(pair->attr, "ip") == 0 ||
586d9924332SDavid du Colombier cistrcmp(pair->attr, "ipv6") == 0){
5873ff48bf5SDavid du Colombier dp->ordinal = ord++;
5887dd7cddfSDavid du Colombier rp = addrrr(entry, pair);
5894f8f669cSDavid du Colombier } else if(cistrcmp(pair->attr, "ns") == 0)
5907dd7cddfSDavid du Colombier rp = nsrr(entry, pair);
5914f8f669cSDavid du Colombier else if(cistrcmp(pair->attr, "soa") == 0) {
5927dd7cddfSDavid du Colombier rp = soarr(entry, pair);
5937dd7cddfSDavid du Colombier addarea(dp, rp, pair);
5944f8f669cSDavid du Colombier } else if(cistrcmp(pair->attr, "mx") == 0)
5957dd7cddfSDavid du Colombier rp = mxrr(entry, pair);
59676783259SDavid du Colombier else if(cistrcmp(pair->attr, "srv") == 0)
59776783259SDavid du Colombier rp = srvrr(entry, pair);
5984f8f669cSDavid du Colombier else if(cistrcmp(pair->attr, "cname") == 0)
5997dd7cddfSDavid du Colombier rp = cnamerr(entry, pair);
6004f8f669cSDavid du Colombier else if(cistrcmp(pair->attr, "nullrr") == 0)
6019a747e4fSDavid du Colombier rp = nullrr(entry, pair);
6024f8f669cSDavid du Colombier else if(cistrcmp(pair->attr, "txtrr") == 0)
6039a747e4fSDavid du Colombier rp = txtrr(entry, pair);
6044f8f669cSDavid du Colombier if(rp == nil)
6057dd7cddfSDavid du Colombier return;
6067dd7cddfSDavid du Colombier
6077dd7cddfSDavid du Colombier rp->owner = dp;
608410ea80bSDavid du Colombier dnagenever(dp, 1);
6097dd7cddfSDavid du Colombier rp->db = 1;
6104f8f669cSDavid du Colombier rp->ttl = intval(entry, pair, "ttl", rp->ttl);
6116dc4800dSDavid du Colombier rrattach(rp, Notauthoritative);
6127dd7cddfSDavid du Colombier }
6137dd7cddfSDavid du Colombier static void
dbtuple2cache(Ndbtuple * t)6147dd7cddfSDavid du Colombier dbtuple2cache(Ndbtuple *t)
6157dd7cddfSDavid du Colombier {
6167dd7cddfSDavid du Colombier Ndbtuple *et, *nt;
6177dd7cddfSDavid du Colombier DN *dp;
6187dd7cddfSDavid du Colombier
6194f8f669cSDavid du Colombier for(et = t; et; et = et->entry)
6207dd7cddfSDavid du Colombier if(strcmp(et->attr, "dom") == 0){
6217dd7cddfSDavid du Colombier dp = dnlookup(et->val, Cin, 1);
6227dd7cddfSDavid du Colombier
6237dd7cddfSDavid du Colombier /* first same line */
6247dd7cddfSDavid du Colombier for(nt = et->line; nt != et; nt = nt->line){
6257dd7cddfSDavid du Colombier dbpair2cache(dp, t, nt);
6267dd7cddfSDavid du Colombier nt->ptr = 1;
6277dd7cddfSDavid du Colombier }
6287dd7cddfSDavid du Colombier
6297dd7cddfSDavid du Colombier /* then rest of entry */
6307dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){
6317dd7cddfSDavid du Colombier if(nt->ptr == 0)
6327dd7cddfSDavid du Colombier dbpair2cache(dp, t, nt);
6337dd7cddfSDavid du Colombier nt->ptr = 0;
6347dd7cddfSDavid du Colombier }
6357dd7cddfSDavid du Colombier }
6367dd7cddfSDavid du Colombier }
6377dd7cddfSDavid du Colombier static void
dbfile2cache(Ndb * db)6387dd7cddfSDavid du Colombier dbfile2cache(Ndb *db)
6397dd7cddfSDavid du Colombier {
6407dd7cddfSDavid du Colombier Ndbtuple *t;
6417dd7cddfSDavid du Colombier
64259cc4ca5SDavid du Colombier if(debug)
6434f8f669cSDavid du Colombier dnslog("rereading %s", db->file);
6447dd7cddfSDavid du Colombier Bseek(&db->b, 0, 0);
6457dd7cddfSDavid du Colombier while(t = ndbparse(db)){
6467dd7cddfSDavid du Colombier dbtuple2cache(t);
6477dd7cddfSDavid du Colombier ndbfree(t);
6487dd7cddfSDavid du Colombier }
6497dd7cddfSDavid du Colombier }
6504f8f669cSDavid du Colombier
6514f8f669cSDavid du Colombier /* called with dblock held */
6524f8f669cSDavid du Colombier static void
loaddomsrvs(void)6534f8f669cSDavid du Colombier loaddomsrvs(void)
6544f8f669cSDavid du Colombier {
6554f8f669cSDavid du Colombier Ndbs s;
6564f8f669cSDavid du Colombier
6574f8f669cSDavid du Colombier if (!cfg.inside || !cfg.straddle || !cfg.serve)
6584f8f669cSDavid du Colombier return;
6594f8f669cSDavid du Colombier if (indoms) {
6604f8f669cSDavid du Colombier ndbfree(indoms);
6614f8f669cSDavid du Colombier ndbfree(innmsrvs);
6624f8f669cSDavid du Colombier ndbfree(outnmsrvs);
6634f8f669cSDavid du Colombier indoms = innmsrvs = outnmsrvs = nil;
6644f8f669cSDavid du Colombier }
6654f8f669cSDavid du Colombier if (db == nil)
6664f8f669cSDavid du Colombier opendatabase();
6674f8f669cSDavid du Colombier free(ndbgetvalue(db, &s, "sys", "inside-dom", "dom", &indoms));
6684f8f669cSDavid du Colombier free(ndbgetvalue(db, &s, "sys", "inside-ns", "ip", &innmsrvs));
6694f8f669cSDavid du Colombier free(ndbgetvalue(db, &s, "sys", "outside-ns", "ip", &outnmsrvs));
6704f8f669cSDavid du Colombier dnslog("[%d] ndb changed: reloaded inside-dom, inside-ns, outside-ns",
6714f8f669cSDavid du Colombier getpid());
6724f8f669cSDavid du Colombier }
6734f8f669cSDavid du Colombier
6747dd7cddfSDavid du Colombier void
db2cache(int doit)6757dd7cddfSDavid du Colombier db2cache(int doit)
6767dd7cddfSDavid du Colombier {
677530fef66SDavid du Colombier ulong youngest;
6787dd7cddfSDavid du Colombier Ndb *ndb;
6799a747e4fSDavid du Colombier Dir *d;
6804f8f669cSDavid du Colombier static ulong lastcheck, lastyoungest;
6817dd7cddfSDavid du Colombier
682dc5a79c1SDavid du Colombier /* no faster than once every 2 minutes */
6837dd7cddfSDavid du Colombier if(now < lastcheck + 2*Min && !doit)
6847dd7cddfSDavid du Colombier return;
6857dd7cddfSDavid du Colombier
686dc5a79c1SDavid du Colombier refresh_areas(owned);
687dc5a79c1SDavid du Colombier
6887dd7cddfSDavid du Colombier lock(&dblock);
6897dd7cddfSDavid du Colombier
6907dd7cddfSDavid du Colombier if(opendatabase() < 0){
6917dd7cddfSDavid du Colombier unlock(&dblock);
6927dd7cddfSDavid du Colombier return;
6937dd7cddfSDavid du Colombier }
6947dd7cddfSDavid du Colombier
6957dd7cddfSDavid du Colombier /*
6967dd7cddfSDavid du Colombier * file may be changing as we are reading it, so loop till
6977dd7cddfSDavid du Colombier * mod times are consistent.
6987dd7cddfSDavid du Colombier *
6997dd7cddfSDavid du Colombier * we don't use the times in the ndb records because they may
7007dd7cddfSDavid du Colombier * change outside of refreshing our cached knowledge.
7017dd7cddfSDavid du Colombier */
7027dd7cddfSDavid du Colombier for(;;){
7037dd7cddfSDavid du Colombier lastcheck = now;
7047dd7cddfSDavid du Colombier youngest = 0;
7054f8f669cSDavid du Colombier for(ndb = db; ndb; ndb = ndb->next)
7064f8f669cSDavid du Colombier /* dirfstat avoids walking the mount table each time */
7079a747e4fSDavid du Colombier if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
7089a747e4fSDavid du Colombier (d = dirstat(ndb->file)) != nil){
709530fef66SDavid du Colombier if(d->mtime > youngest)
710530fef66SDavid du Colombier youngest = d->mtime;
7119a747e4fSDavid du Colombier free(d);
7127dd7cddfSDavid du Colombier }
713b85a8364SDavid du Colombier if(!doit && youngest == lastyoungest)
714b85a8364SDavid du Colombier break;
7157dd7cddfSDavid du Colombier
7167dd7cddfSDavid du Colombier /* forget our area definition */
7177dd7cddfSDavid du Colombier freearea(&owned);
7187dd7cddfSDavid du Colombier freearea(&delegated);
7197dd7cddfSDavid du Colombier
7207dd7cddfSDavid du Colombier /* reopen all the files (to get oldest for time stamp) */
7217dd7cddfSDavid du Colombier for(ndb = db; ndb; ndb = ndb->next)
7227dd7cddfSDavid du Colombier ndbreopen(ndb);
7237dd7cddfSDavid du Colombier
7244f8f669cSDavid du Colombier /* reload straddle-server configuration */
7254f8f669cSDavid du Colombier loaddomsrvs();
7264f8f669cSDavid du Colombier
7274f8f669cSDavid du Colombier if(cfg.cachedb){
7287dd7cddfSDavid du Colombier /* mark all db records as timed out */
7297dd7cddfSDavid du Colombier dnagedb();
7307dd7cddfSDavid du Colombier
7317dd7cddfSDavid du Colombier /* read in new entries */
7327dd7cddfSDavid du Colombier for(ndb = db; ndb; ndb = ndb->next)
7337dd7cddfSDavid du Colombier dbfile2cache(ndb);
7347dd7cddfSDavid du Colombier
7354f8f669cSDavid du Colombier /* mark as authoritative anything in our domain */
7367dd7cddfSDavid du Colombier dnauthdb();
7377dd7cddfSDavid du Colombier
7387dd7cddfSDavid du Colombier /* remove old entries */
7397dd7cddfSDavid du Colombier dnageall(1);
7404f8f669cSDavid du Colombier } else
7417dd7cddfSDavid du Colombier /* read all the soa's to get database defaults */
7427dd7cddfSDavid du Colombier for(ndb = db; ndb; ndb = ndb->next)
7437dd7cddfSDavid du Colombier dbfile2area(ndb);
7447dd7cddfSDavid du Colombier
7457dd7cddfSDavid du Colombier doit = 0;
7467dd7cddfSDavid du Colombier lastyoungest = youngest;
7473ff48bf5SDavid du Colombier createptrs();
7487dd7cddfSDavid du Colombier }
7497dd7cddfSDavid du Colombier
7507dd7cddfSDavid du Colombier unlock(&dblock);
7517dd7cddfSDavid du Colombier }
7527dd7cddfSDavid du Colombier
75321abd8f2SDavid du Colombier void
dnforceage(void)75421abd8f2SDavid du Colombier dnforceage(void)
75521abd8f2SDavid du Colombier {
75621abd8f2SDavid du Colombier lock(&dblock);
75721abd8f2SDavid du Colombier dnageall(1);
75821abd8f2SDavid du Colombier unlock(&dblock);
75921abd8f2SDavid du Colombier }
76021abd8f2SDavid du Colombier
761b322bd99SDavid du Colombier extern uchar ipaddr[IPaddrlen]; /* my ip address */
7627dd7cddfSDavid du Colombier
7637dd7cddfSDavid du Colombier /*
7647dd7cddfSDavid du Colombier * get all my xxx
76553874d13SDavid du Colombier * caller ndbfrees the result
7667dd7cddfSDavid du Colombier */
7677dd7cddfSDavid du Colombier Ndbtuple*
lookupinfo(char * attr)7687dd7cddfSDavid du Colombier lookupinfo(char *attr)
7697dd7cddfSDavid du Colombier {
7707dd7cddfSDavid du Colombier char buf[64];
7717dd7cddfSDavid du Colombier char *a[2];
77253874d13SDavid du Colombier Ndbtuple *t;
7737dd7cddfSDavid du Colombier
7749a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%I", ipaddr);
7757dd7cddfSDavid du Colombier a[0] = attr;
7767dd7cddfSDavid du Colombier
7777dd7cddfSDavid du Colombier lock(&dblock);
7787dd7cddfSDavid du Colombier if(opendatabase() < 0){
7797dd7cddfSDavid du Colombier unlock(&dblock);
7807dd7cddfSDavid du Colombier return nil;
7817dd7cddfSDavid du Colombier }
7827dd7cddfSDavid du Colombier t = ndbipinfo(db, "ip", buf, a, 1);
7837dd7cddfSDavid du Colombier unlock(&dblock);
7847dd7cddfSDavid du Colombier return t;
7857dd7cddfSDavid du Colombier }
7867dd7cddfSDavid du Colombier
78759cc4ca5SDavid du Colombier char *localservers = "local#dns#servers";
78859cc4ca5SDavid du Colombier char *localserverprefix = "local#dns#server";
78959cc4ca5SDavid du Colombier
7907dd7cddfSDavid du Colombier /*
7918246a6ddSDavid du Colombier * return non-zero if this is a bad delegation
7927dd7cddfSDavid du Colombier */
7937dd7cddfSDavid du Colombier int
baddelegation(RR * rp,RR * nsrp,uchar * addr)7947dd7cddfSDavid du Colombier baddelegation(RR *rp, RR *nsrp, uchar *addr)
7957dd7cddfSDavid du Colombier {
7967dd7cddfSDavid du Colombier Ndbtuple *nt;
797adb31a62SDavid du Colombier static int whined;
7987dd7cddfSDavid du Colombier static Ndbtuple *t;
7997dd7cddfSDavid du Colombier
8007dd7cddfSDavid du Colombier if(t == nil)
8017dd7cddfSDavid du Colombier t = lookupinfo("dom");
8027dd7cddfSDavid du Colombier if(t == nil)
8037dd7cddfSDavid du Colombier return 0;
8047dd7cddfSDavid du Colombier
8057dd7cddfSDavid du Colombier for(; rp; rp = rp->next){
8067dd7cddfSDavid du Colombier if(rp->type != Tns)
8077dd7cddfSDavid du Colombier continue;
8087dd7cddfSDavid du Colombier
8097dd7cddfSDavid du Colombier /* see if delegation is looping */
8107dd7cddfSDavid du Colombier if(nsrp)
8117dd7cddfSDavid du Colombier if(rp->owner != nsrp->owner)
81259cc4ca5SDavid du Colombier if(subsume(rp->owner->name, nsrp->owner->name) &&
81359cc4ca5SDavid du Colombier strcmp(nsrp->owner->name, localservers) != 0){
8144f8f669cSDavid du Colombier dnslog("delegation loop %R -> %R from %I",
8154f8f669cSDavid du Colombier nsrp, rp, addr);
8167dd7cddfSDavid du Colombier return 1;
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier
8197dd7cddfSDavid du Colombier /* see if delegating to us what we don't own */
8207dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry)
8217dd7cddfSDavid du Colombier if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
8227dd7cddfSDavid du Colombier break;
8237dd7cddfSDavid du Colombier if(nt != nil && !inmyarea(rp->owner->name)){
824adb31a62SDavid du Colombier if (!whined) {
825adb31a62SDavid du Colombier whined = 1;
826adb31a62SDavid du Colombier dnslog("bad delegation %R from %I; "
827adb31a62SDavid du Colombier "no further logging of them", rp, addr);
828adb31a62SDavid du Colombier }
8297dd7cddfSDavid du Colombier return 1;
8307dd7cddfSDavid du Colombier }
8317dd7cddfSDavid du Colombier }
8327dd7cddfSDavid du Colombier
8337dd7cddfSDavid du Colombier return 0;
8347dd7cddfSDavid du Colombier }
8357dd7cddfSDavid du Colombier
8364e153993SDavid du Colombier int
myaddr(char * addr)837a41547ffSDavid du Colombier myaddr(char *addr)
838a41547ffSDavid du Colombier {
839a41547ffSDavid du Colombier char *name, *line, *sp;
840a41547ffSDavid du Colombier char buf[64];
841a41547ffSDavid du Colombier Biobuf *bp;
842a41547ffSDavid du Colombier
843a41547ffSDavid du Colombier snprint(buf, sizeof buf, "%I", ipaddr);
844a41547ffSDavid du Colombier if (strcmp(addr, buf) == 0) {
845a41547ffSDavid du Colombier dnslog("rejecting my ip %s as local dns server", addr);
846a41547ffSDavid du Colombier return 1;
847a41547ffSDavid du Colombier }
848a41547ffSDavid du Colombier
849a41547ffSDavid du Colombier name = smprint("%s/ipselftab", mntpt);
850a41547ffSDavid du Colombier bp = Bopen(name, OREAD);
851a41547ffSDavid du Colombier free(name);
852a41547ffSDavid du Colombier if (bp != nil) {
853a41547ffSDavid du Colombier while ((line = Brdline(bp, '\n')) != nil) {
854a41547ffSDavid du Colombier line[Blinelen(bp) - 1] = '\0';
855a41547ffSDavid du Colombier sp = strchr(line, ' ');
856a41547ffSDavid du Colombier if (sp) {
857a41547ffSDavid du Colombier *sp = '\0';
858a41547ffSDavid du Colombier if (strcmp(addr, line) == 0) {
859a41547ffSDavid du Colombier dnslog("rejecting my ip %s as local dns server",
860a41547ffSDavid du Colombier addr);
861a41547ffSDavid du Colombier return 1;
862a41547ffSDavid du Colombier }
863a41547ffSDavid du Colombier }
864a41547ffSDavid du Colombier }
865a41547ffSDavid du Colombier Bterm(bp);
866a41547ffSDavid du Colombier }
867a41547ffSDavid du Colombier return 0;
868a41547ffSDavid du Colombier }
869a41547ffSDavid du Colombier
870a41547ffSDavid du Colombier static char *locdns[20];
8714f927735SDavid du Colombier static QLock locdnslck;
872a41547ffSDavid du Colombier
8737dd7cddfSDavid du Colombier static void
addlocaldnsserver(DN * dp,int class,char * ipaddr,int i)8747dd7cddfSDavid du Colombier addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
8757dd7cddfSDavid du Colombier {
876a41547ffSDavid du Colombier int n;
8777dd7cddfSDavid du Colombier DN *nsdp;
8787dd7cddfSDavid du Colombier RR *rp;
8797dd7cddfSDavid du Colombier char buf[32];
880d9924332SDavid du Colombier uchar ip[IPaddrlen];
8817dd7cddfSDavid du Colombier
882a41547ffSDavid du Colombier /* reject our own ip addresses so we don't query ourselves via udp */
883a41547ffSDavid du Colombier if (myaddr(ipaddr))
884a41547ffSDavid du Colombier return;
885a41547ffSDavid du Colombier
8864e153993SDavid du Colombier qlock(&locdnslck);
887a41547ffSDavid du Colombier for (n = 0; n < i && n < nelem(locdns) && locdns[n]; n++)
888a41547ffSDavid du Colombier if (strcmp(locdns[n], ipaddr) == 0) {
889a41547ffSDavid du Colombier dnslog("rejecting duplicate local dns server ip %s",
890a41547ffSDavid du Colombier ipaddr);
8914e153993SDavid du Colombier qunlock(&locdnslck);
892a41547ffSDavid du Colombier return;
893a41547ffSDavid du Colombier }
894a41547ffSDavid du Colombier if (n < nelem(locdns))
895a41547ffSDavid du Colombier if (locdns[n] == nil || ++n < nelem(locdns))
8964f927735SDavid du Colombier locdns[n] = strdup(ipaddr); /* remember 1st few local ns */
8974e153993SDavid du Colombier qunlock(&locdnslck);
898a41547ffSDavid du Colombier
8997dd7cddfSDavid du Colombier /* ns record for name server, make up an impossible name */
9007dd7cddfSDavid du Colombier rp = rralloc(Tns);
9014f8f669cSDavid du Colombier snprint(buf, sizeof buf, "%s%d", localserverprefix, i);
9027dd7cddfSDavid du Colombier nsdp = dnlookup(buf, class, 1);
9037dd7cddfSDavid du Colombier rp->host = nsdp;
904a41547ffSDavid du Colombier rp->owner = dp; /* e.g., local#dns#servers */
9057dd7cddfSDavid du Colombier rp->local = 1;
9067dd7cddfSDavid du Colombier rp->db = 1;
907a41547ffSDavid du Colombier // rp->ttl = 10*Min; /* seems too short */
908a41547ffSDavid du Colombier rp->ttl = (1UL<<31)-1;
9096dc4800dSDavid du Colombier rrattach(rp, Authoritative); /* will not attach rrs in my area */
9107dd7cddfSDavid du Colombier
911d9924332SDavid du Colombier /* A or AAAA record */
912d9924332SDavid du Colombier if (parseip(ip, ipaddr) >= 0 && isv4(ip))
9137dd7cddfSDavid du Colombier rp = rralloc(Ta);
914d9924332SDavid du Colombier else
915d9924332SDavid du Colombier rp = rralloc(Taaaa);
9167dd7cddfSDavid du Colombier rp->ip = dnlookup(ipaddr, class, 1);
9177dd7cddfSDavid du Colombier rp->owner = nsdp;
9187dd7cddfSDavid du Colombier rp->local = 1;
9197dd7cddfSDavid du Colombier rp->db = 1;
920a41547ffSDavid du Colombier // rp->ttl = 10*Min; /* seems too short */
921a41547ffSDavid du Colombier rp->ttl = (1UL<<31)-1;
9226dc4800dSDavid du Colombier rrattach(rp, Authoritative); /* will not attach rrs in my area */
923a41547ffSDavid du Colombier
924a41547ffSDavid du Colombier dnslog("added local dns server %s at %s", buf, ipaddr);
9257dd7cddfSDavid du Colombier }
9267dd7cddfSDavid du Colombier
9277dd7cddfSDavid du Colombier /*
9287dd7cddfSDavid du Colombier * return list of dns server addresses to use when
9297dd7cddfSDavid du Colombier * acting just as a resolver.
9307dd7cddfSDavid du Colombier */
9317dd7cddfSDavid du Colombier RR*
dnsservers(int class)9327dd7cddfSDavid du Colombier dnsservers(int class)
9337dd7cddfSDavid du Colombier {
9344f8f669cSDavid du Colombier int i, n;
9354f927735SDavid du Colombier char *p;
9364f8f669cSDavid du Colombier char *args[5];
9377dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
9387dd7cddfSDavid du Colombier RR *nsrp;
9397dd7cddfSDavid du Colombier DN *dp;
9407dd7cddfSDavid du Colombier
94159cc4ca5SDavid du Colombier dp = dnlookup(localservers, class, 1);
9427dd7cddfSDavid du Colombier nsrp = rrlookup(dp, Tns, NOneg);
9437dd7cddfSDavid du Colombier if(nsrp != nil)
9447dd7cddfSDavid du Colombier return nsrp;
9457dd7cddfSDavid du Colombier
946b322bd99SDavid du Colombier p = getenv("DNSSERVER"); /* list of ip addresses */
9477dd7cddfSDavid du Colombier if(p != nil){
9484f927735SDavid du Colombier n = tokenize(p, args, nelem(args));
9497dd7cddfSDavid du Colombier for(i = 0; i < n; i++)
9507dd7cddfSDavid du Colombier addlocaldnsserver(dp, class, args[i], i);
9514f927735SDavid du Colombier free(p);
9527dd7cddfSDavid du Colombier } else {
953b322bd99SDavid du Colombier t = lookupinfo("@dns"); /* @dns=ip1 @dns=ip2 ... */
9547dd7cddfSDavid du Colombier if(t == nil)
9557dd7cddfSDavid du Colombier return nil;
9567dd7cddfSDavid du Colombier i = 0;
9577dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry){
9587dd7cddfSDavid du Colombier addlocaldnsserver(dp, class, nt->val, i);
9597dd7cddfSDavid du Colombier i++;
9607dd7cddfSDavid du Colombier }
9617dd7cddfSDavid du Colombier ndbfree(t);
9627dd7cddfSDavid du Colombier }
9637dd7cddfSDavid du Colombier
9647dd7cddfSDavid du Colombier return rrlookup(dp, Tns, NOneg);
9657dd7cddfSDavid du Colombier }
9667dd7cddfSDavid du Colombier
9677dd7cddfSDavid du Colombier static void
addlocaldnsdomain(DN * dp,int class,char * domain)9687dd7cddfSDavid du Colombier addlocaldnsdomain(DN *dp, int class, char *domain)
9697dd7cddfSDavid du Colombier {
9707dd7cddfSDavid du Colombier RR *rp;
9717dd7cddfSDavid du Colombier
972225077b0SDavid du Colombier /* ptr record */
9737dd7cddfSDavid du Colombier rp = rralloc(Tptr);
9747dd7cddfSDavid du Colombier rp->ptr = dnlookup(domain, class, 1);
9757dd7cddfSDavid du Colombier rp->owner = dp;
9767dd7cddfSDavid du Colombier rp->db = 1;
9777dd7cddfSDavid du Colombier rp->ttl = 10*Min;
9786dc4800dSDavid du Colombier rrattach(rp, Authoritative);
9797dd7cddfSDavid du Colombier }
9807dd7cddfSDavid du Colombier
9817dd7cddfSDavid du Colombier /*
9827dd7cddfSDavid du Colombier * return list of domains to use when resolving names without '.'s
9837dd7cddfSDavid du Colombier */
9847dd7cddfSDavid du Colombier RR*
domainlist(int class)9857dd7cddfSDavid du Colombier domainlist(int class)
9867dd7cddfSDavid du Colombier {
9877dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
9887dd7cddfSDavid du Colombier RR *rp;
9897dd7cddfSDavid du Colombier DN *dp;
9907dd7cddfSDavid du Colombier
9917dd7cddfSDavid du Colombier dp = dnlookup("local#dns#domains", class, 1);
9927dd7cddfSDavid du Colombier rp = rrlookup(dp, Tptr, NOneg);
9937dd7cddfSDavid du Colombier if(rp != nil)
9947dd7cddfSDavid du Colombier return rp;
9957dd7cddfSDavid du Colombier
9967dd7cddfSDavid du Colombier t = lookupinfo("dnsdomain");
9977dd7cddfSDavid du Colombier if(t == nil)
9987dd7cddfSDavid du Colombier return nil;
9997dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry)
10007dd7cddfSDavid du Colombier addlocaldnsdomain(dp, class, nt->val);
10017dd7cddfSDavid du Colombier ndbfree(t);
10027dd7cddfSDavid du Colombier
10037dd7cddfSDavid du Colombier return rrlookup(dp, Tptr, NOneg);
10047dd7cddfSDavid du Colombier }
10053ff48bf5SDavid du Colombier
10063ff48bf5SDavid du Colombier char *v4ptrdom = ".in-addr.arpa";
10077def40e1SDavid du Colombier char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */
10083ff48bf5SDavid du Colombier
10093ff48bf5SDavid du Colombier char *attribs[] = {
10103ff48bf5SDavid du Colombier "ipmask",
10113ff48bf5SDavid du Colombier 0
10123ff48bf5SDavid du Colombier };
10133ff48bf5SDavid du Colombier
10143ff48bf5SDavid du Colombier /*
101553874d13SDavid du Colombier * create ptrs that are in our v4 areas
10163ff48bf5SDavid du Colombier */
10173ff48bf5SDavid du Colombier static void
createv4ptrs(void)101853874d13SDavid du Colombier createv4ptrs(void)
10193ff48bf5SDavid du Colombier {
10203ff48bf5SDavid du Colombier int len, dlen, n;
102153874d13SDavid du Colombier char *dom;
10224f8f669cSDavid du Colombier char buf[Domlen+1], ipa[48];
10236b0d5c8bSDavid du Colombier char *f[40];
10244f8f669cSDavid du Colombier uchar net[IPaddrlen], mask[IPaddrlen];
10254f8f669cSDavid du Colombier Area *s;
10263ff48bf5SDavid du Colombier Ndbtuple *t, *nt;
10273ff48bf5SDavid du Colombier
10283ff48bf5SDavid du Colombier dlen = strlen(v4ptrdom);
10293ff48bf5SDavid du Colombier for(s = owned; s; s = s->next){
103053874d13SDavid du Colombier dom = s->soarr->owner->name;
103153874d13SDavid du Colombier len = strlen(dom);
103253874d13SDavid du Colombier if((len <= dlen || cistrcmp(dom+len-dlen, v4ptrdom) != 0) &&
103353874d13SDavid du Colombier cistrcmp(dom, v4ptrdom+1) != 0)
10343ff48bf5SDavid du Colombier continue;
10353ff48bf5SDavid du Colombier
10363ff48bf5SDavid du Colombier /* get mask and net value */
103753874d13SDavid du Colombier strncpy(buf, dom, sizeof buf);
10384f8f669cSDavid du Colombier buf[sizeof buf-1] = 0;
103953874d13SDavid du Colombier /* buf contains something like 178.204.in-addr.arpa (n==4) */
10403ff48bf5SDavid du Colombier n = getfields(buf, f, nelem(f), 0, ".");
10413ff48bf5SDavid du Colombier memset(mask, 0xff, IPaddrlen);
10423ff48bf5SDavid du Colombier ipmove(net, v4prefix);
10433ff48bf5SDavid du Colombier switch(n){
10443ff48bf5SDavid du Colombier case 3: /* /8 */
10453ff48bf5SDavid du Colombier net[IPv4off] = atoi(f[0]);
10463ff48bf5SDavid du Colombier mask[IPv4off+1] = 0;
10473ff48bf5SDavid du Colombier mask[IPv4off+2] = 0;
10483ff48bf5SDavid du Colombier mask[IPv4off+3] = 0;
10493ff48bf5SDavid du Colombier break;
10503ff48bf5SDavid du Colombier case 4: /* /16 */
10513ff48bf5SDavid du Colombier net[IPv4off] = atoi(f[1]);
10523ff48bf5SDavid du Colombier net[IPv4off+1] = atoi(f[0]);
10533ff48bf5SDavid du Colombier mask[IPv4off+2] = 0;
10543ff48bf5SDavid du Colombier mask[IPv4off+3] = 0;
10553ff48bf5SDavid du Colombier break;
10563ff48bf5SDavid du Colombier case 5: /* /24 */
10573ff48bf5SDavid du Colombier net[IPv4off] = atoi(f[2]);
10583ff48bf5SDavid du Colombier net[IPv4off+1] = atoi(f[1]);
10593ff48bf5SDavid du Colombier net[IPv4off+2] = atoi(f[0]);
10603ff48bf5SDavid du Colombier mask[IPv4off+3] = 0;
10613ff48bf5SDavid du Colombier break;
1062225077b0SDavid du Colombier case 6: /* rfc2317: classless in-addr.arpa delegation */
10633ff48bf5SDavid du Colombier net[IPv4off] = atoi(f[3]);
10643ff48bf5SDavid du Colombier net[IPv4off+1] = atoi(f[2]);
10653ff48bf5SDavid du Colombier net[IPv4off+2] = atoi(f[1]);
10663ff48bf5SDavid du Colombier net[IPv4off+3] = atoi(f[0]);
10673ff48bf5SDavid du Colombier sprint(ipa, "%I", net);
10683ff48bf5SDavid du Colombier t = ndbipinfo(db, "ip", ipa, attribs, 1);
106908fd2d13SDavid du Colombier if(t == nil) /* could be a reverse with no forward */
107008fd2d13SDavid du Colombier continue;
10713ff48bf5SDavid du Colombier nt = look(t, t, "ipmask");
10723ff48bf5SDavid du Colombier if(nt == nil){ /* we're confused */
10733ff48bf5SDavid du Colombier ndbfree(t);
10743ff48bf5SDavid du Colombier continue;
10753ff48bf5SDavid du Colombier }
10763ff48bf5SDavid du Colombier parseipmask(mask, nt->val);
1077018fc28bSDavid du Colombier ndbfree(t);
10783ff48bf5SDavid du Colombier n = 5;
10793ff48bf5SDavid du Colombier break;
10803ff48bf5SDavid du Colombier default:
10813ff48bf5SDavid du Colombier continue;
10823ff48bf5SDavid du Colombier }
10833ff48bf5SDavid du Colombier
10844f8f669cSDavid du Colombier /*
10854f8f669cSDavid du Colombier * go through all domain entries looking for RR's
108653874d13SDavid du Colombier * in this network and create ptrs.
108753874d13SDavid du Colombier * +2 for ".in-addr.arpa".
10884f8f669cSDavid du Colombier */
1089617c0e1eSDavid du Colombier dnptr(net, mask, dom, Ta, 4+2-n, Ptrttl);
10903ff48bf5SDavid du Colombier }
10913ff48bf5SDavid du Colombier }
10924f8f669cSDavid du Colombier
109353874d13SDavid du Colombier /* convert bytes to nibbles, big-endian */
109453874d13SDavid du Colombier void
bytes2nibbles(uchar * nibbles,uchar * bytes,int nbytes)109553874d13SDavid du Colombier bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes)
109653874d13SDavid du Colombier {
109753874d13SDavid du Colombier while (nbytes-- > 0) {
109853874d13SDavid du Colombier *nibbles++ = *bytes >> Nibwidth;
109953874d13SDavid du Colombier *nibbles++ = *bytes++ & Nibmask;
110053874d13SDavid du Colombier }
110153874d13SDavid du Colombier }
110253874d13SDavid du Colombier
110353874d13SDavid du Colombier void
nibbles2bytes(uchar * bytes,uchar * nibbles,int nnibs)110453874d13SDavid du Colombier nibbles2bytes(uchar *bytes, uchar *nibbles, int nnibs)
110553874d13SDavid du Colombier {
110653874d13SDavid du Colombier for (; nnibs >= 2; nnibs -= 2) {
110753874d13SDavid du Colombier *bytes++ = nibbles[0] << Nibwidth | (nibbles[1]&Nibmask);
110853874d13SDavid du Colombier nibbles += 2;
110953874d13SDavid du Colombier }
111053874d13SDavid du Colombier if (nnibs > 0)
111153874d13SDavid du Colombier *bytes = nibbles[0] << Nibwidth;
111253874d13SDavid du Colombier }
111353874d13SDavid du Colombier
111453874d13SDavid du Colombier /*
111553874d13SDavid du Colombier * create ptrs that are in our v6 areas. see rfc3596
111653874d13SDavid du Colombier */
111753874d13SDavid du Colombier static void
createv6ptrs(void)111853874d13SDavid du Colombier createv6ptrs(void)
111953874d13SDavid du Colombier {
112053874d13SDavid du Colombier int len, dlen, i, n, pfxnibs;
112153874d13SDavid du Colombier char *dom;
112253874d13SDavid du Colombier char buf[Domlen+1];
112353874d13SDavid du Colombier char *f[40];
112453874d13SDavid du Colombier uchar net[IPaddrlen], mask[IPaddrlen];
112553874d13SDavid du Colombier uchar nibnet[IPaddrlen*2], nibmask[IPaddrlen*2];
112653874d13SDavid du Colombier Area *s;
112753874d13SDavid du Colombier
112853874d13SDavid du Colombier dlen = strlen(v6ptrdom);
112953874d13SDavid du Colombier for(s = owned; s; s = s->next){
113053874d13SDavid du Colombier dom = s->soarr->owner->name;
113153874d13SDavid du Colombier len = strlen(dom);
113253874d13SDavid du Colombier if((len <= dlen || cistrcmp(dom+len-dlen, v6ptrdom) != 0) &&
113353874d13SDavid du Colombier cistrcmp(dom, v6ptrdom+1) != 0)
113453874d13SDavid du Colombier continue;
113553874d13SDavid du Colombier
113653874d13SDavid du Colombier /* get mask and net value */
113753874d13SDavid du Colombier strncpy(buf, dom, sizeof buf);
113853874d13SDavid du Colombier buf[sizeof buf-1] = 0;
113953874d13SDavid du Colombier /* buf contains something like 2.0.0.2.ip6.arpa (n==6) */
114053874d13SDavid du Colombier n = getfields(buf, f, nelem(f), 0, ".");
11414f927735SDavid du Colombier pfxnibs = n - 2; /* 2 for .ip6.arpa */
114253874d13SDavid du Colombier if (pfxnibs < 0 || pfxnibs > V6maxrevdomdepth)
114353874d13SDavid du Colombier continue;
114453874d13SDavid du Colombier
114553874d13SDavid du Colombier memset(net, 0, IPaddrlen);
114653874d13SDavid du Colombier memset(mask, 0xff, IPaddrlen);
114753874d13SDavid du Colombier bytes2nibbles(nibnet, net, IPaddrlen);
114853874d13SDavid du Colombier bytes2nibbles(nibmask, mask, IPaddrlen);
114953874d13SDavid du Colombier
115053874d13SDavid du Colombier /* copy prefix of f, in reverse order, to start of net. */
115153874d13SDavid du Colombier for (i = 0; i < pfxnibs; i++)
115253874d13SDavid du Colombier nibnet[i] = strtol(f[pfxnibs - 1 - i], nil, 16);
115353874d13SDavid du Colombier /* zero nibbles of mask after prefix in net */
115453874d13SDavid du Colombier memset(nibmask + pfxnibs, 0, V6maxrevdomdepth - pfxnibs);
115553874d13SDavid du Colombier
115653874d13SDavid du Colombier nibbles2bytes(net, nibnet, 2*IPaddrlen);
115753874d13SDavid du Colombier nibbles2bytes(mask, nibmask, 2*IPaddrlen);
115853874d13SDavid du Colombier
115953874d13SDavid du Colombier /*
116053874d13SDavid du Colombier * go through all domain entries looking for RR's
116153874d13SDavid du Colombier * in this network and create ptrs.
116253874d13SDavid du Colombier */
1163617c0e1eSDavid du Colombier dnptr(net, mask, dom, Taaaa, V6maxrevdomdepth - pfxnibs, Ptrttl);
116453874d13SDavid du Colombier }
116553874d13SDavid du Colombier }
116653874d13SDavid du Colombier
116753874d13SDavid du Colombier /*
116853874d13SDavid du Colombier * create ptrs that are in our areas
116953874d13SDavid du Colombier */
117053874d13SDavid du Colombier static void
createptrs(void)117153874d13SDavid du Colombier createptrs(void)
117253874d13SDavid du Colombier {
117353874d13SDavid du Colombier createv4ptrs();
117453874d13SDavid du Colombier createv6ptrs();
117553874d13SDavid du Colombier }
117653874d13SDavid du Colombier
11774f8f669cSDavid du Colombier /*
11784f8f669cSDavid du Colombier * is this domain (or DOMAIN or Domain or dOMAIN)
11794f8f669cSDavid du Colombier * internal to our organisation (behind our firewall)?
11804f8f669cSDavid du Colombier * only inside straddling servers care, everybody else gets told `yes',
11814f8f669cSDavid du Colombier * so they'll use mntpt for their queries.
11824f8f669cSDavid du Colombier */
11834f8f669cSDavid du Colombier int
insideaddr(char * dom)11844f8f669cSDavid du Colombier insideaddr(char *dom)
11854f8f669cSDavid du Colombier {
11864f8f669cSDavid du Colombier int domlen, vallen, rv;
11874f8f669cSDavid du Colombier Ndbtuple *t;
11884f8f669cSDavid du Colombier
11894f8f669cSDavid du Colombier if (!cfg.inside || !cfg.straddle || !cfg.serve)
11904f8f669cSDavid du Colombier return 1;
119159f7772cSDavid du Colombier if (dom[0] == '\0' || strcmp(dom, ".") == 0) /* dns root? */
119259f7772cSDavid du Colombier return 1; /* hack for initialisation */
11934f8f669cSDavid du Colombier
11944f8f669cSDavid du Colombier lock(&dblock);
11954f8f669cSDavid du Colombier if (indoms == nil)
11964f8f669cSDavid du Colombier loaddomsrvs();
11974f8f669cSDavid du Colombier if (indoms == nil) {
11984f8f669cSDavid du Colombier unlock(&dblock);
119959f7772cSDavid du Colombier return 1; /* no "inside-dom" sys, try inside nameservers */
12004f8f669cSDavid du Colombier }
12014f8f669cSDavid du Colombier
12024f8f669cSDavid du Colombier rv = 0;
12034f8f669cSDavid du Colombier domlen = strlen(dom);
12044f8f669cSDavid du Colombier for (t = indoms; t != nil; t = t->entry) {
12054f8f669cSDavid du Colombier if (strcmp(t->attr, "dom") != 0)
12064f8f669cSDavid du Colombier continue;
12074f8f669cSDavid du Colombier vallen = strlen(t->val);
12084f8f669cSDavid du Colombier if (cistrcmp(dom, t->val) == 0 ||
12094f8f669cSDavid du Colombier domlen > vallen &&
12104f8f669cSDavid du Colombier cistrcmp(dom + domlen - vallen, t->val) == 0 &&
12114f8f669cSDavid du Colombier dom[domlen - vallen - 1] == '.') {
12124f8f669cSDavid du Colombier rv = 1;
12134f8f669cSDavid du Colombier break;
12144f8f669cSDavid du Colombier }
12154f8f669cSDavid du Colombier }
12164f8f669cSDavid du Colombier unlock(&dblock);
12174f8f669cSDavid du Colombier return rv;
12184f8f669cSDavid du Colombier }
12194f8f669cSDavid du Colombier
12204f8f669cSDavid du Colombier int
insidens(uchar * ip)12214f8f669cSDavid du Colombier insidens(uchar *ip)
12224f8f669cSDavid du Colombier {
12234f8f669cSDavid du Colombier uchar ipa[IPaddrlen];
12244f8f669cSDavid du Colombier Ndbtuple *t;
12254f8f669cSDavid du Colombier
12264f8f669cSDavid du Colombier for (t = innmsrvs; t != nil; t = t->entry)
12274f8f669cSDavid du Colombier if (strcmp(t->attr, "ip") == 0) {
12284f8f669cSDavid du Colombier parseip(ipa, t->val);
12294f8f669cSDavid du Colombier if (memcmp(ipa, ip, sizeof ipa) == 0)
12304f8f669cSDavid du Colombier return 1;
12314f8f669cSDavid du Colombier }
12324f8f669cSDavid du Colombier return 0;
12334f8f669cSDavid du Colombier }
12344f8f669cSDavid du Colombier
12354f8f669cSDavid du Colombier uchar *
outsidens(int n)12364f8f669cSDavid du Colombier outsidens(int n)
12374f8f669cSDavid du Colombier {
12384f8f669cSDavid du Colombier int i;
12394f8f669cSDavid du Colombier Ndbtuple *t;
12404f8f669cSDavid du Colombier static uchar ipa[IPaddrlen];
12414f8f669cSDavid du Colombier
12424f8f669cSDavid du Colombier i = 0;
12434f8f669cSDavid du Colombier for (t = outnmsrvs; t != nil; t = t->entry)
12444f8f669cSDavid du Colombier if (strcmp(t->attr, "ip") == 0 && i++ == n) {
12454f8f669cSDavid du Colombier parseip(ipa, t->val);
12464f8f669cSDavid du Colombier return ipa;
12474f8f669cSDavid du Colombier }
12484f8f669cSDavid du Colombier return nil;
12494f8f669cSDavid du Colombier }
1250