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