13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <ip.h> 47dd7cddfSDavid du Colombier #include <pool.h> 59a747e4fSDavid du Colombier #include <ctype.h> 63e12c5d1SDavid du Colombier #include "dns.h" 73e12c5d1SDavid du Colombier 821abd8f2SDavid du Colombier /* 921abd8f2SDavid du Colombier * this comment used to say `our target is 4000 names cached, this should 1021abd8f2SDavid du Colombier * be larger on large servers'. dns at Bell Labs starts off with 1121abd8f2SDavid du Colombier * about 1780 names. 1221abd8f2SDavid du Colombier * 1321abd8f2SDavid du Colombier * aging seems to corrupt the cache, so raise the trigger from 4000 until we 14410ea80bSDavid du Colombier * figure it out. 1521abd8f2SDavid du Colombier */ 1621abd8f2SDavid du Colombier enum { 17410ea80bSDavid du Colombier Deftarget = 8000, 1821abd8f2SDavid du Colombier }; 1981730632SDavid du Colombier enum { 2081730632SDavid du Colombier Minage = 10*60, 21f46c709fSDavid du Colombier Defagefreq = 30*60, /* age names this often (seconds) */ 2281730632SDavid du Colombier }; 2381730632SDavid du Colombier 243e12c5d1SDavid du Colombier /* 253e12c5d1SDavid du Colombier * Hash table for domain names. The hash is based only on the 263e12c5d1SDavid du Colombier * first element of the domain name. 273e12c5d1SDavid du Colombier */ 287dd7cddfSDavid du Colombier DN *ht[HTLEN]; 293e12c5d1SDavid du Colombier 304f8f669cSDavid du Colombier static struct { 317dd7cddfSDavid du Colombier Lock; 327dd7cddfSDavid du Colombier ulong names; /* names allocated */ 337dd7cddfSDavid du Colombier ulong oldest; /* longest we'll leave a name around */ 347dd7cddfSDavid du Colombier int active; 357dd7cddfSDavid du Colombier int mutex; 364f8f669cSDavid du Colombier ushort id; /* same size as in packet */ 377dd7cddfSDavid du Colombier } dnvars; 383e12c5d1SDavid du Colombier 393e12c5d1SDavid du Colombier /* names of RR types */ 403e12c5d1SDavid du Colombier char *rrtname[] = 413e12c5d1SDavid du Colombier { 423e12c5d1SDavid du Colombier [Ta] "ip", 433e12c5d1SDavid du Colombier [Tns] "ns", 443e12c5d1SDavid du Colombier [Tmd] "md", 453e12c5d1SDavid du Colombier [Tmf] "mf", 463e12c5d1SDavid du Colombier [Tcname] "cname", 473e12c5d1SDavid du Colombier [Tsoa] "soa", 483e12c5d1SDavid du Colombier [Tmb] "mb", 493e12c5d1SDavid du Colombier [Tmg] "mg", 503e12c5d1SDavid du Colombier [Tmr] "mr", 513e12c5d1SDavid du Colombier [Tnull] "null", 523e12c5d1SDavid du Colombier [Twks] "wks", 533e12c5d1SDavid du Colombier [Tptr] "ptr", 543e12c5d1SDavid du Colombier [Thinfo] "hinfo", 553e12c5d1SDavid du Colombier [Tminfo] "minfo", 563e12c5d1SDavid du Colombier [Tmx] "mx", 573e12c5d1SDavid du Colombier [Ttxt] "txt", 587dd7cddfSDavid du Colombier [Trp] "rp", 59ab3dc52fSDavid du Colombier [Tafsdb] "afsdb", 60ab3dc52fSDavid du Colombier [Tx25] "x.25", 61ab3dc52fSDavid du Colombier [Tisdn] "isdn", 62ab3dc52fSDavid du Colombier [Trt] "rt", 63ab3dc52fSDavid du Colombier [Tnsap] "nsap", 64ab3dc52fSDavid du Colombier [Tnsapptr] "nsap-ptr", 657dd7cddfSDavid du Colombier [Tsig] "sig", 66ab3dc52fSDavid du Colombier [Tkey] "key", 67ab3dc52fSDavid du Colombier [Tpx] "px", 68ab3dc52fSDavid du Colombier [Tgpos] "gpos", 695d459b5aSDavid du Colombier [Taaaa] "ipv6", 70ab3dc52fSDavid du Colombier [Tloc] "loc", 71ab3dc52fSDavid du Colombier [Tnxt] "nxt", 72ab3dc52fSDavid du Colombier [Teid] "eid", 73ab3dc52fSDavid du Colombier [Tnimloc] "nimrod", 74ab3dc52fSDavid du Colombier [Tsrv] "srv", 75ab3dc52fSDavid du Colombier [Tatma] "atma", 76ab3dc52fSDavid du Colombier [Tnaptr] "naptr", 77ab3dc52fSDavid du Colombier [Tkx] "kx", 78ab3dc52fSDavid du Colombier [Tcert] "cert", 79ab3dc52fSDavid du Colombier [Ta6] "a6", 80ab3dc52fSDavid du Colombier [Tdname] "dname", 81ab3dc52fSDavid du Colombier [Tsink] "sink", 82ab3dc52fSDavid du Colombier [Topt] "opt", 83ab3dc52fSDavid du Colombier [Tapl] "apl", 84ab3dc52fSDavid du Colombier [Tds] "ds", 85ab3dc52fSDavid du Colombier [Tsshfp] "sshfp", 86ab3dc52fSDavid du Colombier [Tipseckey] "ipseckey", 87ab3dc52fSDavid du Colombier [Trrsig] "rrsig", 88ab3dc52fSDavid du Colombier [Tnsec] "nsec", 89ab3dc52fSDavid du Colombier [Tdnskey] "dnskey", 90ab3dc52fSDavid du Colombier [Tspf] "spf", 91ab3dc52fSDavid du Colombier [Tuinfo] "uinfo", 92ab3dc52fSDavid du Colombier [Tuid] "uid", 93ab3dc52fSDavid du Colombier [Tgid] "gid", 94ab3dc52fSDavid du Colombier [Tunspec] "unspec", 95ab3dc52fSDavid du Colombier [Ttkey] "tkey", 96ab3dc52fSDavid du Colombier [Ttsig] "tsig", 977dd7cddfSDavid du Colombier [Tixfr] "ixfr", 987dd7cddfSDavid du Colombier [Taxfr] "axfr", 99ab3dc52fSDavid du Colombier [Tmailb] "mailb", 100ab3dc52fSDavid du Colombier [Tmaila] "maila", 101219b2ee8SDavid du Colombier [Tall] "all", 1023e12c5d1SDavid du Colombier 0, 1033e12c5d1SDavid du Colombier }; 1043e12c5d1SDavid du Colombier 1053e12c5d1SDavid du Colombier /* names of response codes */ 106271b8d73SDavid du Colombier char *rname[Rmask+1] = 1073e12c5d1SDavid du Colombier { 1083e12c5d1SDavid du Colombier [Rok] "ok", 1093e12c5d1SDavid du Colombier [Rformat] "format error", 1103e12c5d1SDavid du Colombier [Rserver] "server failure", 1113e12c5d1SDavid du Colombier [Rname] "bad name", 1123e12c5d1SDavid du Colombier [Runimplimented] "unimplemented", 1133e12c5d1SDavid du Colombier [Rrefused] "we don't like you", 114ab3dc52fSDavid du Colombier [Ryxdomain] "name should not exist", 115ab3dc52fSDavid du Colombier [Ryxrrset] "rr set should not exist", 116ab3dc52fSDavid du Colombier [Rnxrrset] "rr set should exist", 117ab3dc52fSDavid du Colombier [Rnotauth] "not authorative", 118ab3dc52fSDavid du Colombier [Rnotzone] "not in zone", 119ab3dc52fSDavid du Colombier [Rbadvers] "bad opt version", 120ab3dc52fSDavid du Colombier /* [Rbadsig] "bad signature", */ 121ab3dc52fSDavid du Colombier [Rbadkey] "bad key", 122ab3dc52fSDavid du Colombier [Rbadtime] "bad signature time", 123ab3dc52fSDavid du Colombier [Rbadmode] "bad mode", 124ab3dc52fSDavid du Colombier [Rbadname] "duplicate key name", 125ab3dc52fSDavid du Colombier [Rbadalg] "bad algorithm", 1263e12c5d1SDavid du Colombier }; 1274f8f669cSDavid du Colombier unsigned nrname = nelem(rname); 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier /* names of op codes */ 1303e12c5d1SDavid du Colombier char *opname[] = 1313e12c5d1SDavid du Colombier { 1323e12c5d1SDavid du Colombier [Oquery] "query", 133ab3dc52fSDavid du Colombier [Oinverse] "inverse query (retired)", 1343e12c5d1SDavid du Colombier [Ostatus] "status", 135ab3dc52fSDavid du Colombier [Oupdate] "update", 1363e12c5d1SDavid du Colombier }; 1373e12c5d1SDavid du Colombier 13821abd8f2SDavid du Colombier ulong target = Deftarget; 139bd389b36SDavid du Colombier Lock dnlock; 1403e12c5d1SDavid du Colombier 141f46c709fSDavid du Colombier static ulong agefreq = Defagefreq; 142f46c709fSDavid du Colombier 143225077b0SDavid du Colombier static int rrequiv(RR *r1, RR *r2); 1449a747e4fSDavid du Colombier static int sencodefmt(Fmt*); 14559cc4ca5SDavid du Colombier 146254fe3d3SDavid du Colombier static void 147254fe3d3SDavid du Colombier ding(void*, char *msg) 148254fe3d3SDavid du Colombier { 149254fe3d3SDavid du Colombier if(strstr(msg, "alarm") != nil) { 150254fe3d3SDavid du Colombier stats.alarms++; 151254fe3d3SDavid du Colombier noted(NCONT); /* resume with system call error */ 152254fe3d3SDavid du Colombier } else 153254fe3d3SDavid du Colombier noted(NDFLT); /* die */ 154254fe3d3SDavid du Colombier } 155254fe3d3SDavid du Colombier 1563e12c5d1SDavid du Colombier void 1573e12c5d1SDavid du Colombier dninit(void) 1583e12c5d1SDavid du Colombier { 1599a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 1609a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 1619a747e4fSDavid du Colombier fmtinstall('V', eipfmt); 1629a747e4fSDavid du Colombier fmtinstall('R', rrfmt); 1639a747e4fSDavid du Colombier fmtinstall('Q', rravfmt); 1649a747e4fSDavid du Colombier fmtinstall('H', sencodefmt); 1657dd7cddfSDavid du Colombier 1667dd7cddfSDavid du Colombier dnvars.oldest = maxage; 1677dd7cddfSDavid du Colombier dnvars.names = 0; 1684f8f669cSDavid du Colombier dnvars.id = truerand(); /* don't start with same id every time */ 169254fe3d3SDavid du Colombier 170254fe3d3SDavid du Colombier notify(ding); 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier /* 1743e12c5d1SDavid du Colombier * hash for a domain name 1753e12c5d1SDavid du Colombier */ 1763e12c5d1SDavid du Colombier static ulong 1773e12c5d1SDavid du Colombier dnhash(char *name) 1783e12c5d1SDavid du Colombier { 1793e12c5d1SDavid du Colombier ulong hash; 1803e12c5d1SDavid du Colombier uchar *val = (uchar*)name; 1813e12c5d1SDavid du Colombier 1827dd7cddfSDavid du Colombier for(hash = 0; *val; val++) 1834f8f669cSDavid du Colombier hash = hash*13 + tolower(*val)-'a'; 1843e12c5d1SDavid du Colombier return hash % HTLEN; 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier /* 1883e12c5d1SDavid du Colombier * lookup a symbol. if enter is not zero and the name is 1893e12c5d1SDavid du Colombier * not found, create it. 1903e12c5d1SDavid du Colombier */ 1913e12c5d1SDavid du Colombier DN* 1923e12c5d1SDavid du Colombier dnlookup(char *name, int class, int enter) 1933e12c5d1SDavid du Colombier { 1943e12c5d1SDavid du Colombier DN **l; 1953e12c5d1SDavid du Colombier DN *dp; 1963e12c5d1SDavid du Colombier 1973ff48bf5SDavid du Colombier l = &ht[dnhash(name)]; 198bd389b36SDavid du Colombier lock(&dnlock); 1993e12c5d1SDavid du Colombier for(dp = *l; dp; dp = dp->next) { 2007dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 2013ff48bf5SDavid du Colombier if(dp->class == class && cistrcmp(dp->name, name) == 0){ 2027dd7cddfSDavid du Colombier dp->referenced = now; 203bd389b36SDavid du Colombier unlock(&dnlock); 2043e12c5d1SDavid du Colombier return dp; 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier l = &dp->next; 2073e12c5d1SDavid du Colombier } 2084f8f669cSDavid du Colombier 2094f8f669cSDavid du Colombier if(!enter){ 210bd389b36SDavid du Colombier unlock(&dnlock); 2113e12c5d1SDavid du Colombier return 0; 2123e12c5d1SDavid du Colombier } 2137dd7cddfSDavid du Colombier dnvars.names++; 2149a747e4fSDavid du Colombier dp = emalloc(sizeof(*dp)); 2157dd7cddfSDavid du Colombier dp->magic = DNmagic; 2169a747e4fSDavid du Colombier dp->name = estrdup(name); 2174f8f669cSDavid du Colombier assert(dp->name != nil); 2183e12c5d1SDavid du Colombier dp->class = class; 2193e12c5d1SDavid du Colombier dp->rr = 0; 2207dd7cddfSDavid du Colombier dp->referenced = now; 221530fef66SDavid du Colombier /* add new DN to tail of the hash list. *l points to last next ptr. */ 222530fef66SDavid du Colombier dp->next = nil; 2233e12c5d1SDavid du Colombier *l = dp; 224bd389b36SDavid du Colombier unlock(&dnlock); 2257dd7cddfSDavid du Colombier 2263e12c5d1SDavid du Colombier return dp; 2273e12c5d1SDavid du Colombier } 2283e12c5d1SDavid du Colombier 229225077b0SDavid du Colombier static int 230225077b0SDavid du Colombier rrsame(RR *rr1, RR *rr2) 231225077b0SDavid du Colombier { 232225077b0SDavid du Colombier return rr1 == rr2 || rr2 && rrequiv(rr1, rr2) && 233225077b0SDavid du Colombier rr1->db == rr2->db && rr1->auth == rr2->auth; 234225077b0SDavid du Colombier } 235225077b0SDavid du Colombier 236225077b0SDavid du Colombier static int 237225077b0SDavid du Colombier rronlist(RR *rp, RR *lp) 238225077b0SDavid du Colombier { 239225077b0SDavid du Colombier for(; lp; lp = lp->next) 2404f927735SDavid du Colombier if (rrsame(lp, rp)) 241225077b0SDavid du Colombier return 1; 242225077b0SDavid du Colombier return 0; 243225077b0SDavid du Colombier } 244225077b0SDavid du Colombier 2453e12c5d1SDavid du Colombier /* 2464f927735SDavid du Colombier * dump the stats 247219b2ee8SDavid du Colombier */ 248219b2ee8SDavid du Colombier void 2494f927735SDavid du Colombier dnstats(char *file) 250219b2ee8SDavid du Colombier { 251219b2ee8SDavid du Colombier int i, fd; 252219b2ee8SDavid du Colombier 25321abd8f2SDavid du Colombier fd = create(file, OWRITE, 0666); 254219b2ee8SDavid du Colombier if(fd < 0) 255219b2ee8SDavid du Colombier return; 256a41547ffSDavid du Colombier 257a41547ffSDavid du Colombier qlock(&stats); 2584f927735SDavid du Colombier fprint(fd, "# system %s\n", sysname()); 259f46c709fSDavid du Colombier fprint(fd, "# slave procs high-water mark\t%lud\n", stats.slavehiwat); 260f46c709fSDavid du Colombier fprint(fd, "# queries received by 9p\t%lud\n", stats.qrecvd9p); 261f46c709fSDavid du Colombier fprint(fd, "# queries received by udp\t%lud\n", stats.qrecvdudp); 262f46c709fSDavid du Colombier fprint(fd, "# queries answered from memory\t%lud\n", stats.answinmem); 263f46c709fSDavid du Colombier fprint(fd, "# queries sent by udp\t%lud\n", stats.qsent); 264a41547ffSDavid du Colombier for (i = 0; i < nelem(stats.under10ths); i++) 265a41547ffSDavid du Colombier if (stats.under10ths[i] || i == nelem(stats.under10ths) - 1) 266f46c709fSDavid du Colombier fprint(fd, "# responses arriving within %.1f s.\t%lud\n", 267a41547ffSDavid du Colombier (double)(i+1)/10, stats.under10ths[i]); 268f46c709fSDavid du Colombier fprint(fd, "\n# queries sent & timed-out\t%lud\n", stats.tmout); 269f46c709fSDavid du Colombier fprint(fd, "# cname queries timed-out\t%lud\n", stats.tmoutcname); 270f46c709fSDavid du Colombier fprint(fd, "# ipv6 queries timed-out\t%lud\n", stats.tmoutv6); 271f46c709fSDavid du Colombier fprint(fd, "\n# negative answers received\t%lud\n", stats.negans); 2720319257bSDavid du Colombier fprint(fd, "# negative answers w Rserver set\t%lud\n", stats.negserver); 2730319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation\t%lud\n", 2740319257bSDavid du Colombier stats.negbaddeleg); 2750319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation & no answers\t%lud\n", 2760319257bSDavid du Colombier stats.negbdnoans); 2770319257bSDavid du Colombier fprint(fd, "# negative answers w no Rname set\t%lud\n", stats.negnorname); 278f46c709fSDavid du Colombier fprint(fd, "# negative answers cached\t%lud\n", stats.negcached); 279a41547ffSDavid du Colombier qunlock(&stats); 280a41547ffSDavid du Colombier 281219b2ee8SDavid du Colombier lock(&dnlock); 2826d8e4566SDavid du Colombier fprint(fd, "\n# domain names %lud target %lud\n", dnvars.names, target); 2834f927735SDavid du Colombier unlock(&dnlock); 2844f927735SDavid du Colombier close(fd); 2854f927735SDavid du Colombier } 2864f927735SDavid du Colombier 2874f927735SDavid du Colombier /* 2884f927735SDavid du Colombier * dump the cache 2894f927735SDavid du Colombier */ 2904f927735SDavid du Colombier void 2914f927735SDavid du Colombier dndump(char *file) 2924f927735SDavid du Colombier { 2934f927735SDavid du Colombier int i, fd; 2944f927735SDavid du Colombier DN *dp; 2954f927735SDavid du Colombier RR *rp; 2964f927735SDavid du Colombier 2974f927735SDavid du Colombier fd = create(file, OWRITE, 0666); 2984f927735SDavid du Colombier if(fd < 0) 2994f927735SDavid du Colombier return; 3004f927735SDavid du Colombier 3014f927735SDavid du Colombier lock(&dnlock); 3024f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++) 303219b2ee8SDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 304219b2ee8SDavid du Colombier fprint(fd, "%s\n", dp->name); 305225077b0SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) { 3066d8e4566SDavid du Colombier fprint(fd, "\t%R %c%c %lud/%lud\n", 3074f8f669cSDavid du Colombier rp, rp->auth? 'A': 'U', 3087dd7cddfSDavid du Colombier rp->db? 'D': 'N', rp->expire, rp->ttl); 309225077b0SDavid du Colombier if (rronlist(rp, rp->next)) 310225077b0SDavid du Colombier fprint(fd, "*** duplicate:\n"); 311225077b0SDavid du Colombier } 312219b2ee8SDavid du Colombier } 313219b2ee8SDavid du Colombier unlock(&dnlock); 314219b2ee8SDavid du Colombier close(fd); 315219b2ee8SDavid du Colombier } 316219b2ee8SDavid du Colombier 317219b2ee8SDavid du Colombier /* 3187dd7cddfSDavid du Colombier * purge all records 3197dd7cddfSDavid du Colombier */ 3207dd7cddfSDavid du Colombier void 3217dd7cddfSDavid du Colombier dnpurge(void) 3227dd7cddfSDavid du Colombier { 3237dd7cddfSDavid du Colombier DN *dp; 324a4285193SDavid du Colombier RR *rp, *srp; 3257dd7cddfSDavid du Colombier int i; 3267dd7cddfSDavid du Colombier 3277dd7cddfSDavid du Colombier lock(&dnlock); 3287dd7cddfSDavid du Colombier 3297dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 3307dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 331a4285193SDavid du Colombier srp = rp = dp->rr; 3327dd7cddfSDavid du Colombier dp->rr = nil; 3337dd7cddfSDavid du Colombier for(; rp != nil; rp = rp->next) 3347dd7cddfSDavid du Colombier rp->cached = 0; 335a4285193SDavid du Colombier rrfreelist(srp); 3367dd7cddfSDavid du Colombier } 3377dd7cddfSDavid du Colombier 3387dd7cddfSDavid du Colombier unlock(&dnlock); 3397dd7cddfSDavid du Colombier } 3407dd7cddfSDavid du Colombier 341d2fd7a44SDavid du Colombier /* 342d2fd7a44SDavid du Colombier * delete rp from *l, free rp. 343d2fd7a44SDavid du Colombier * call with dnlock held. 344d2fd7a44SDavid du Colombier */ 345225077b0SDavid du Colombier static void 346225077b0SDavid du Colombier rrdelete(RR **l, RR *rp) 347225077b0SDavid du Colombier { 348225077b0SDavid du Colombier *l = rp->next; 349225077b0SDavid du Colombier rp->cached = 0; /* avoid blowing an assertion in rrfree */ 350225077b0SDavid du Colombier rrfree(rp); 351225077b0SDavid du Colombier } 352225077b0SDavid du Colombier 3537dd7cddfSDavid du Colombier /* 354d2fd7a44SDavid du Colombier * check the age of resource records, free any that have timed out. 355d2fd7a44SDavid du Colombier * call with dnlock held. 3563e12c5d1SDavid du Colombier */ 3573e12c5d1SDavid du Colombier void 3583e12c5d1SDavid du Colombier dnage(DN *dp) 3593e12c5d1SDavid du Colombier { 3603e12c5d1SDavid du Colombier RR **l; 3613e12c5d1SDavid du Colombier RR *rp, *next; 3627dd7cddfSDavid du Colombier ulong diff; 3633e12c5d1SDavid du Colombier 3647dd7cddfSDavid du Colombier diff = now - dp->referenced; 3656dc4800dSDavid du Colombier if(diff < Reserved || dp->keep) 3667dd7cddfSDavid du Colombier return; 3677dd7cddfSDavid du Colombier 3683e12c5d1SDavid du Colombier l = &dp->rr; 3693e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = next){ 3707dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 3713e12c5d1SDavid du Colombier next = rp->next; 372225077b0SDavid du Colombier if(!rp->db && (rp->expire < now || diff > dnvars.oldest)) 373225077b0SDavid du Colombier rrdelete(l, rp); 374225077b0SDavid du Colombier else 3753e12c5d1SDavid du Colombier l = &rp->next; 3763e12c5d1SDavid du Colombier } 3773e12c5d1SDavid du Colombier } 3783e12c5d1SDavid du Colombier 3796dc4800dSDavid du Colombier #define MARK(dp) { if (dp) (dp)->keep = 1; } 380a41547ffSDavid du Colombier 381410ea80bSDavid du Colombier /* mark a domain name and those in its RRs as never to be aged */ 382a41547ffSDavid du Colombier void 383410ea80bSDavid du Colombier dnagenever(DN *dp, int dolock) 384a41547ffSDavid du Colombier { 385a41547ffSDavid du Colombier RR *rp; 386a41547ffSDavid du Colombier 387410ea80bSDavid du Colombier if (dolock) 388a41547ffSDavid du Colombier lock(&dnlock); 389a41547ffSDavid du Colombier 390410ea80bSDavid du Colombier /* mark all referenced domain names */ 391410ea80bSDavid du Colombier MARK(dp); 392a41547ffSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 393a41547ffSDavid du Colombier MARK(rp->owner); 394410ea80bSDavid du Colombier if(rp->negative){ 395410ea80bSDavid du Colombier MARK(rp->negsoaowner); 396410ea80bSDavid du Colombier continue; 397410ea80bSDavid du Colombier } 398a41547ffSDavid du Colombier switch(rp->type){ 399410ea80bSDavid du Colombier case Thinfo: 400410ea80bSDavid du Colombier MARK(rp->cpu); 401410ea80bSDavid du Colombier MARK(rp->os); 402410ea80bSDavid du Colombier break; 403410ea80bSDavid du Colombier case Ttxt: 404410ea80bSDavid du Colombier break; 405410ea80bSDavid du Colombier case Tcname: 406410ea80bSDavid du Colombier case Tmb: 407410ea80bSDavid du Colombier case Tmd: 408410ea80bSDavid du Colombier case Tmf: 409a41547ffSDavid du Colombier case Tns: 410410ea80bSDavid du Colombier case Tmx: 411410ea80bSDavid du Colombier case Tsrv: 412a41547ffSDavid du Colombier MARK(rp->host); 413a41547ffSDavid du Colombier break; 414410ea80bSDavid du Colombier case Tmg: 415410ea80bSDavid du Colombier case Tmr: 416410ea80bSDavid du Colombier MARK(rp->mb); 417410ea80bSDavid du Colombier break; 418410ea80bSDavid du Colombier case Tminfo: 419410ea80bSDavid du Colombier MARK(rp->rmb); 420410ea80bSDavid du Colombier MARK(rp->mb); 421410ea80bSDavid du Colombier break; 422410ea80bSDavid du Colombier case Trp: 423410ea80bSDavid du Colombier MARK(rp->rmb); 424410ea80bSDavid du Colombier MARK(rp->rp); 425410ea80bSDavid du Colombier break; 426410ea80bSDavid du Colombier case Ta: 427410ea80bSDavid du Colombier case Taaaa: 428410ea80bSDavid du Colombier MARK(rp->ip); 429410ea80bSDavid du Colombier break; 430410ea80bSDavid du Colombier case Tptr: 431410ea80bSDavid du Colombier MARK(rp->ptr); 432410ea80bSDavid du Colombier break; 433410ea80bSDavid du Colombier case Tsoa: 434410ea80bSDavid du Colombier MARK(rp->host); 435410ea80bSDavid du Colombier MARK(rp->rmb); 436410ea80bSDavid du Colombier break; 437a41547ffSDavid du Colombier } 438a41547ffSDavid du Colombier } 439410ea80bSDavid du Colombier 440410ea80bSDavid du Colombier if (dolock) 441410ea80bSDavid du Colombier unlock(&dnlock); 4426dc4800dSDavid du Colombier } 443a41547ffSDavid du Colombier 444410ea80bSDavid du Colombier /* mark all current domain names as never to be aged */ 445410ea80bSDavid du Colombier void 446410ea80bSDavid du Colombier dnageallnever(void) 447410ea80bSDavid du Colombier { 448410ea80bSDavid du Colombier int i; 449410ea80bSDavid du Colombier DN *dp; 450410ea80bSDavid du Colombier 451410ea80bSDavid du Colombier lock(&dnlock); 452410ea80bSDavid du Colombier 453410ea80bSDavid du Colombier /* mark all referenced domain names */ 454410ea80bSDavid du Colombier for(i = 0; i < HTLEN; i++) 455410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 456410ea80bSDavid du Colombier dnagenever(dp, 0); 457410ea80bSDavid du Colombier 458a41547ffSDavid du Colombier unlock(&dnlock); 459a41547ffSDavid du Colombier 460a41547ffSDavid du Colombier dnslog("%ld initial domain names; target is %ld", dnvars.names, target); 461a41547ffSDavid du Colombier if(dnvars.names >= target) 462a41547ffSDavid du Colombier dnslog("more initial domain names (%ld) than target (%ld)", 463a41547ffSDavid du Colombier dnvars.names, target); 464a41547ffSDavid du Colombier } 465a41547ffSDavid du Colombier 4666dc4800dSDavid du Colombier #define REF(dp) { if (dp) (dp)->refs++; } 4676dc4800dSDavid du Colombier 4687dd7cddfSDavid du Colombier /* 4697dd7cddfSDavid du Colombier * periodicly sweep for old records and remove unreferenced domain names 4707dd7cddfSDavid du Colombier * 4717dd7cddfSDavid du Colombier * only called when all other threads are locked out 4727dd7cddfSDavid du Colombier */ 4737dd7cddfSDavid du Colombier void 4747dd7cddfSDavid du Colombier dnageall(int doit) 4757dd7cddfSDavid du Colombier { 4767dd7cddfSDavid du Colombier DN *dp, **l; 477225077b0SDavid du Colombier int i; 4787dd7cddfSDavid du Colombier RR *rp; 4797dd7cddfSDavid du Colombier static ulong nextage; 4807dd7cddfSDavid du Colombier 4814f8f669cSDavid du Colombier if(dnvars.names < target || (now < nextage && !doit)){ 4827dd7cddfSDavid du Colombier dnvars.oldest = maxage; 4837dd7cddfSDavid du Colombier return; 4847dd7cddfSDavid du Colombier } 4857dd7cddfSDavid du Colombier 4864f8f669cSDavid du Colombier if(dnvars.names >= target) { 4873cbadd90SDavid du Colombier dnslog("more names (%lud) than target (%lud)", dnvars.names, 4883cbadd90SDavid du Colombier target); 4897dd7cddfSDavid du Colombier dnvars.oldest /= 2; 49081730632SDavid du Colombier if (dnvars.oldest < Minage) 49181730632SDavid du Colombier dnvars.oldest = Minage; /* don't be silly */ 4924f8f669cSDavid du Colombier } 493f46c709fSDavid du Colombier if (agefreq > dnvars.oldest / 2) 494f46c709fSDavid du Colombier nextage = now + dnvars.oldest / 2; 495f46c709fSDavid du Colombier else 496f46c709fSDavid du Colombier nextage = now + agefreq; 4977dd7cddfSDavid du Colombier 4987dd7cddfSDavid du Colombier lock(&dnlock); 4997dd7cddfSDavid du Colombier 5007dd7cddfSDavid du Colombier /* time out all old entries (and set refs to 0) */ 5017dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 5027dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 5037dd7cddfSDavid du Colombier dp->refs = 0; 5047dd7cddfSDavid du Colombier dnage(dp); 5057dd7cddfSDavid du Colombier } 5067dd7cddfSDavid du Colombier 5077dd7cddfSDavid du Colombier /* mark all referenced domain names */ 5087dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 5097dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 5107dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 5117dd7cddfSDavid du Colombier REF(rp->owner); 5127dd7cddfSDavid du Colombier if(rp->negative){ 5137dd7cddfSDavid du Colombier REF(rp->negsoaowner); 5147dd7cddfSDavid du Colombier continue; 5157dd7cddfSDavid du Colombier } 5167dd7cddfSDavid du Colombier switch(rp->type){ 5177dd7cddfSDavid du Colombier case Thinfo: 5187dd7cddfSDavid du Colombier REF(rp->cpu); 5197dd7cddfSDavid du Colombier REF(rp->os); 5207dd7cddfSDavid du Colombier break; 5217dd7cddfSDavid du Colombier case Ttxt: 5227dd7cddfSDavid du Colombier break; 5237dd7cddfSDavid du Colombier case Tcname: 5247dd7cddfSDavid du Colombier case Tmb: 5257dd7cddfSDavid du Colombier case Tmd: 5267dd7cddfSDavid du Colombier case Tmf: 5277dd7cddfSDavid du Colombier case Tns: 5284f8f669cSDavid du Colombier case Tmx: 529225077b0SDavid du Colombier case Tsrv: 5307dd7cddfSDavid du Colombier REF(rp->host); 5317dd7cddfSDavid du Colombier break; 5327dd7cddfSDavid du Colombier case Tmg: 5337dd7cddfSDavid du Colombier case Tmr: 5347dd7cddfSDavid du Colombier REF(rp->mb); 5357dd7cddfSDavid du Colombier break; 5367dd7cddfSDavid du Colombier case Tminfo: 5377dd7cddfSDavid du Colombier REF(rp->rmb); 5387dd7cddfSDavid du Colombier REF(rp->mb); 5397dd7cddfSDavid du Colombier break; 5407dd7cddfSDavid du Colombier case Trp: 5417dd7cddfSDavid du Colombier REF(rp->rmb); 54260845620SDavid du Colombier REF(rp->rp); 5437dd7cddfSDavid du Colombier break; 5447dd7cddfSDavid du Colombier case Ta: 5455d459b5aSDavid du Colombier case Taaaa: 5467dd7cddfSDavid du Colombier REF(rp->ip); 5477dd7cddfSDavid du Colombier break; 5487dd7cddfSDavid du Colombier case Tptr: 5497dd7cddfSDavid du Colombier REF(rp->ptr); 5507dd7cddfSDavid du Colombier break; 5517dd7cddfSDavid du Colombier case Tsoa: 5527dd7cddfSDavid du Colombier REF(rp->host); 5537dd7cddfSDavid du Colombier REF(rp->rmb); 5547dd7cddfSDavid du Colombier break; 5557dd7cddfSDavid du Colombier } 5567dd7cddfSDavid du Colombier } 5577dd7cddfSDavid du Colombier 5587dd7cddfSDavid du Colombier /* sweep and remove unreferenced domain names */ 5597dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++){ 5607dd7cddfSDavid du Colombier l = &ht[i]; 5617dd7cddfSDavid du Colombier for(dp = *l; dp; dp = *l){ 562a41547ffSDavid du Colombier if(dp->rr == 0 && dp->refs == 0 && !dp->keep){ 56334f77ae3SDavid du Colombier assert(dp->magic == DNmagic); 5647dd7cddfSDavid du Colombier *l = dp->next; 5654f8f669cSDavid du Colombier 5667dd7cddfSDavid du Colombier if(dp->name) 5677dd7cddfSDavid du Colombier free(dp->name); 56834f77ae3SDavid du Colombier dp->magic = ~dp->magic; 5697dd7cddfSDavid du Colombier dnvars.names--; 5704f8f669cSDavid du Colombier memset(dp, 0, sizeof *dp); /* cause trouble */ 5717dd7cddfSDavid du Colombier free(dp); 5724f8f669cSDavid du Colombier 5737dd7cddfSDavid du Colombier continue; 5747dd7cddfSDavid du Colombier } 5757dd7cddfSDavid du Colombier l = &dp->next; 5767dd7cddfSDavid du Colombier } 5777dd7cddfSDavid du Colombier } 5787dd7cddfSDavid du Colombier 5797dd7cddfSDavid du Colombier unlock(&dnlock); 5807dd7cddfSDavid du Colombier } 5817dd7cddfSDavid du Colombier 5827dd7cddfSDavid du Colombier /* 5837dd7cddfSDavid du Colombier * timeout all database records (used when rereading db) 5847dd7cddfSDavid du Colombier */ 5857dd7cddfSDavid du Colombier void 5867dd7cddfSDavid du Colombier dnagedb(void) 5877dd7cddfSDavid du Colombier { 5887dd7cddfSDavid du Colombier DN *dp; 5897dd7cddfSDavid du Colombier int i; 5907dd7cddfSDavid du Colombier RR *rp; 5917dd7cddfSDavid du Colombier 5927dd7cddfSDavid du Colombier lock(&dnlock); 5937dd7cddfSDavid du Colombier 5947dd7cddfSDavid du Colombier /* time out all database entries */ 5957dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 596410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) { 597410ea80bSDavid du Colombier dp->keep = 0; 5987dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 5997dd7cddfSDavid du Colombier if(rp->db) 6007dd7cddfSDavid du Colombier rp->expire = 0; 601410ea80bSDavid du Colombier } 6027dd7cddfSDavid du Colombier 6037dd7cddfSDavid du Colombier unlock(&dnlock); 6047dd7cddfSDavid du Colombier } 6057dd7cddfSDavid du Colombier 6067dd7cddfSDavid du Colombier /* 6074f8f669cSDavid du Colombier * mark all local db records about my area as authoritative, 6084f8f669cSDavid du Colombier * time out any others 6097dd7cddfSDavid du Colombier */ 6107dd7cddfSDavid du Colombier void 6117dd7cddfSDavid du Colombier dnauthdb(void) 6127dd7cddfSDavid du Colombier { 6136b0d5c8bSDavid du Colombier int i; 6144f8f669cSDavid du Colombier ulong minttl; 6156b0d5c8bSDavid du Colombier Area *area; 6164f8f669cSDavid du Colombier DN *dp; 6177dd7cddfSDavid du Colombier RR *rp; 6187dd7cddfSDavid du Colombier 6197dd7cddfSDavid du Colombier lock(&dnlock); 6207dd7cddfSDavid du Colombier 6217dd7cddfSDavid du Colombier /* time out all database entries */ 6227dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 6237dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 6247dd7cddfSDavid du Colombier area = inmyarea(dp->name); 6257dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 6267dd7cddfSDavid du Colombier if(rp->db){ 6277dd7cddfSDavid du Colombier if(area){ 6284f8f669cSDavid du Colombier minttl = area->soarr->soa->minttl; 6294f8f669cSDavid du Colombier if(rp->ttl < minttl) 6304f8f669cSDavid du Colombier rp->ttl = minttl; 6317dd7cddfSDavid du Colombier rp->auth = 1; 6327dd7cddfSDavid du Colombier } 6337dd7cddfSDavid du Colombier if(rp->expire == 0){ 6347dd7cddfSDavid du Colombier rp->db = 0; 6357dd7cddfSDavid du Colombier dp->referenced = now-Reserved-1; 6367dd7cddfSDavid du Colombier } 6377dd7cddfSDavid du Colombier } 6387dd7cddfSDavid du Colombier } 6397dd7cddfSDavid du Colombier 6407dd7cddfSDavid du Colombier unlock(&dnlock); 6417dd7cddfSDavid du Colombier } 6427dd7cddfSDavid du Colombier 6437dd7cddfSDavid du Colombier /* 6447dd7cddfSDavid du Colombier * keep track of other processes to know if we can 6457dd7cddfSDavid du Colombier * garbage collect. block while garbage collecting. 6467dd7cddfSDavid du Colombier */ 6477dd7cddfSDavid du Colombier int 648b4b9fc2fSDavid du Colombier getactivity(Request *req, int recursive) 6497dd7cddfSDavid du Colombier { 6507dd7cddfSDavid du Colombier int rv; 6517dd7cddfSDavid du Colombier 6524f8f669cSDavid du Colombier if(traceactivity) 6534f8f669cSDavid du Colombier dnslog("get: %d active by pid %d from %p", 6544f8f669cSDavid du Colombier dnvars.active, getpid(), getcallerpc(&req)); 6557dd7cddfSDavid du Colombier lock(&dnvars); 656b4b9fc2fSDavid du Colombier /* 657b4b9fc2fSDavid du Colombier * can't block here if we're already holding one 658b4b9fc2fSDavid du Colombier * of the dnvars.active (recursive). will deadlock. 659b4b9fc2fSDavid du Colombier */ 660b4b9fc2fSDavid du Colombier while(!recursive && dnvars.mutex){ 6617dd7cddfSDavid du Colombier unlock(&dnvars); 662d6d99297SDavid du Colombier sleep(100); /* tune; was 200 */ 6637dd7cddfSDavid du Colombier lock(&dnvars); 6647dd7cddfSDavid du Colombier } 6657dd7cddfSDavid du Colombier rv = ++dnvars.active; 6664f8f669cSDavid du Colombier now = time(nil); 667a41547ffSDavid du Colombier nowns = nsec(); 6687dd7cddfSDavid du Colombier req->id = ++dnvars.id; 6697dd7cddfSDavid du Colombier unlock(&dnvars); 6707dd7cddfSDavid du Colombier 6717dd7cddfSDavid du Colombier return rv; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier void 674b4b9fc2fSDavid du Colombier putactivity(int recursive) 6757dd7cddfSDavid du Colombier { 6767dd7cddfSDavid du Colombier static ulong lastclean; 6777dd7cddfSDavid du Colombier 6784f8f669cSDavid du Colombier if(traceactivity) 6794f8f669cSDavid du Colombier dnslog("put: %d active by pid %d", 6804f8f669cSDavid du Colombier dnvars.active, getpid()); 6817dd7cddfSDavid du Colombier lock(&dnvars); 6827dd7cddfSDavid du Colombier dnvars.active--; 6834f8f669cSDavid du Colombier assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */ 6847dd7cddfSDavid du Colombier 6857dd7cddfSDavid du Colombier /* 6867dd7cddfSDavid du Colombier * clean out old entries and check for new db periodicly 687b4b9fc2fSDavid du Colombier * can't block here if being called to let go a "recursive" lock 688b4b9fc2fSDavid du Colombier * or we'll deadlock waiting for ourselves to give up the dnvars.active. 6897dd7cddfSDavid du Colombier */ 6904f8f669cSDavid du Colombier if (recursive || dnvars.mutex || 6914f8f669cSDavid du Colombier (needrefresh == 0 && dnvars.active > 0)){ 6927dd7cddfSDavid du Colombier unlock(&dnvars); 6937dd7cddfSDavid du Colombier return; 6947dd7cddfSDavid du Colombier } 6957dd7cddfSDavid du Colombier 6967dd7cddfSDavid du Colombier /* wait till we're alone */ 6977dd7cddfSDavid du Colombier dnvars.mutex = 1; 6987dd7cddfSDavid du Colombier while(dnvars.active > 0){ 6997dd7cddfSDavid du Colombier unlock(&dnvars); 700d6d99297SDavid du Colombier sleep(100); /* tune; was 100 */ 7017dd7cddfSDavid du Colombier lock(&dnvars); 7027dd7cddfSDavid du Colombier } 7037dd7cddfSDavid du Colombier unlock(&dnvars); 7047dd7cddfSDavid du Colombier 7057dd7cddfSDavid du Colombier db2cache(needrefresh); 7067dd7cddfSDavid du Colombier dnageall(0); 7077dd7cddfSDavid du Colombier 7087dd7cddfSDavid du Colombier /* let others back in */ 7097dd7cddfSDavid du Colombier lastclean = now; 7107dd7cddfSDavid du Colombier needrefresh = 0; 7117dd7cddfSDavid du Colombier dnvars.mutex = 0; 7127dd7cddfSDavid du Colombier } 7137dd7cddfSDavid du Colombier 714d2fd7a44SDavid du Colombier int 715d2fd7a44SDavid du Colombier rrlistlen(RR *rp) 716d2fd7a44SDavid du Colombier { 717d2fd7a44SDavid du Colombier int n; 718d2fd7a44SDavid du Colombier 719d2fd7a44SDavid du Colombier n = 0; 720d2fd7a44SDavid du Colombier for(; rp; rp = rp->next) 721d2fd7a44SDavid du Colombier ++n; 722d2fd7a44SDavid du Colombier return n; 723d2fd7a44SDavid du Colombier } 724d2fd7a44SDavid du Colombier 7253e12c5d1SDavid du Colombier /* 7266dc4800dSDavid du Colombier * Attach a single resource record to a domain name (new->owner). 7273e12c5d1SDavid du Colombier * - Avoid duplicates with already present RR's 7283e12c5d1SDavid du Colombier * - Chain all RR's of the same type adjacent to one another 7293e12c5d1SDavid du Colombier * - chain authoritative RR's ahead of non-authoritative ones 7306dc4800dSDavid du Colombier * - remove any expired RR's 731225077b0SDavid du Colombier * If new is a stale duplicate, rrfree it. 7326dc4800dSDavid du Colombier * Must be called with dnlock held. 7333e12c5d1SDavid du Colombier */ 7343e12c5d1SDavid du Colombier static void 7353e12c5d1SDavid du Colombier rrattach1(RR *new, int auth) 7363e12c5d1SDavid du Colombier { 7373e12c5d1SDavid du Colombier RR **l; 7383e12c5d1SDavid du Colombier RR *rp; 7393e12c5d1SDavid du Colombier DN *dp; 7403e12c5d1SDavid du Colombier 7417dd7cddfSDavid du Colombier assert(new->magic == RRmagic && !new->cached); 7427dd7cddfSDavid du Colombier 7434f8f669cSDavid du Colombier // dnslog("rrattach1: %s", new->owner->name); 744e9b54818SDavid du Colombier if(!new->db) { 745e9b54818SDavid du Colombier /* 746e9b54818SDavid du Colombier * try not to let responses expire before we 747e9b54818SDavid du Colombier * can use them to complete this query, by extending 748e464c1a8SDavid du Colombier * past (or nearly past) expiration time. 749e9b54818SDavid du Colombier */ 750e464c1a8SDavid du Colombier new->expire = new->ttl > now + Min? new->ttl: now + 10*Min; 751e9b54818SDavid du Colombier } else 7527dd7cddfSDavid du Colombier new->expire = now + Year; 7533e12c5d1SDavid du Colombier dp = new->owner; 7547dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 7557dd7cddfSDavid du Colombier new->auth |= auth; 7563e12c5d1SDavid du Colombier new->next = 0; 7573e12c5d1SDavid du Colombier 7583e12c5d1SDavid du Colombier /* 7593ff48bf5SDavid du Colombier * find first rr of the right type 7603e12c5d1SDavid du Colombier */ 7613e12c5d1SDavid du Colombier l = &dp->rr; 7627dd7cddfSDavid du Colombier for(rp = *l; rp; rp = *l){ 7637dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 7643e12c5d1SDavid du Colombier if(rp->type == new->type) 7653e12c5d1SDavid du Colombier break; 7663e12c5d1SDavid du Colombier l = &rp->next; 7673e12c5d1SDavid du Colombier } 7683e12c5d1SDavid du Colombier 7693e12c5d1SDavid du Colombier /* 7707dd7cddfSDavid du Colombier * negative entries replace positive entries 7717dd7cddfSDavid du Colombier * positive entries replace negative entries 7727dd7cddfSDavid du Colombier * newer entries replace older entries with the same fields 773225077b0SDavid du Colombier * 774225077b0SDavid du Colombier * look farther ahead than just the next entry when looking 775225077b0SDavid du Colombier * for duplicates; RRs of a given type can have different rdata 776225077b0SDavid du Colombier * fields (e.g. multiple NS servers). 7773e12c5d1SDavid du Colombier */ 778225077b0SDavid du Colombier while ((rp = *l) != nil){ 7797dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 7807dd7cddfSDavid du Colombier if(rp->type != new->type) 7813e12c5d1SDavid du Colombier break; 7827dd7cddfSDavid du Colombier 7837dd7cddfSDavid du Colombier if(rp->db == new->db && rp->auth == new->auth){ 7847dd7cddfSDavid du Colombier /* negative drives out positive and vice versa */ 7857dd7cddfSDavid du Colombier if(rp->negative != new->negative) { 786225077b0SDavid du Colombier rrdelete(l, rp); 787225077b0SDavid du Colombier continue; /* *l == rp->next */ 7883e12c5d1SDavid du Colombier } 7897dd7cddfSDavid du Colombier /* all things equal, pick the newer one */ 790225077b0SDavid du Colombier else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){ 7917dd7cddfSDavid du Colombier /* new drives out old */ 792225077b0SDavid du Colombier if (new->ttl <= rp->ttl && 793225077b0SDavid du Colombier new->expire <= rp->expire) { 7943e12c5d1SDavid du Colombier rrfree(new); 7953e12c5d1SDavid du Colombier return; 7963e12c5d1SDavid du Colombier } 797225077b0SDavid du Colombier rrdelete(l, rp); 798225077b0SDavid du Colombier continue; /* *l == rp->next */ 7997dd7cddfSDavid du Colombier } 800225077b0SDavid du Colombier /* 801225077b0SDavid du Colombier * Hack for pointer records. This makes sure 8023ff48bf5SDavid du Colombier * the ordering in the list reflects the ordering 8033ff48bf5SDavid du Colombier * received or read from the database 8043ff48bf5SDavid du Colombier */ 805225077b0SDavid du Colombier else if(rp->type == Tptr && 806225077b0SDavid du Colombier !rp->negative && !new->negative && 807225077b0SDavid du Colombier rp->ptr->ordinal > new->ptr->ordinal) 8083ff48bf5SDavid du Colombier break; 8093ff48bf5SDavid du Colombier } 8103e12c5d1SDavid du Colombier l = &rp->next; 8113e12c5d1SDavid du Colombier } 8123e12c5d1SDavid du Colombier 813530fef66SDavid du Colombier if (rronlist(new, rp)) { 8144f927735SDavid du Colombier /* should not happen; duplicates were processed above */ 815530fef66SDavid du Colombier dnslog("adding duplicate %R to list of %R; aborting", new, rp); 8164f927735SDavid du Colombier abort(); 8174f927735SDavid du Colombier } 8183e12c5d1SDavid du Colombier /* 8193e12c5d1SDavid du Colombier * add to chain 8203e12c5d1SDavid du Colombier */ 8217dd7cddfSDavid du Colombier new->cached = 1; 822530fef66SDavid du Colombier new->next = rp; 8233e12c5d1SDavid du Colombier *l = new; 8243e12c5d1SDavid du Colombier } 8253e12c5d1SDavid du Colombier 8263e12c5d1SDavid du Colombier /* 8273e12c5d1SDavid du Colombier * Attach a list of resource records to a domain name. 828225077b0SDavid du Colombier * May rrfree any stale duplicate RRs; dismembers the list. 829225077b0SDavid du Colombier * Upon return, every RR in the list will have been rrfree-d 830225077b0SDavid du Colombier * or attached to its domain name. 8316dc4800dSDavid du Colombier * See rrattach1 for properties preserved. 8323e12c5d1SDavid du Colombier */ 8333e12c5d1SDavid du Colombier void 8343e12c5d1SDavid du Colombier rrattach(RR *rp, int auth) 8353e12c5d1SDavid du Colombier { 8363e12c5d1SDavid du Colombier RR *next; 837d2fd7a44SDavid du Colombier DN *dp; 8383e12c5d1SDavid du Colombier 839bd389b36SDavid du Colombier lock(&dnlock); 8403e12c5d1SDavid du Colombier for(; rp; rp = next){ 8413e12c5d1SDavid du Colombier next = rp->next; 8424f8f669cSDavid du Colombier rp->next = nil; 843d2fd7a44SDavid du Colombier dp = rp->owner; 8447dd7cddfSDavid du Colombier 8457dd7cddfSDavid du Colombier /* avoid any outside spoofing */ 8464f8f669cSDavid du Colombier // dnslog("rrattach: %s", rp->owner->name); 8474f8f669cSDavid du Colombier if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name)) 8487dd7cddfSDavid du Colombier rrfree(rp); 849d2fd7a44SDavid du Colombier else { 850530fef66SDavid du Colombier /* ameliorate the memory leak */ 851530fef66SDavid du Colombier if (0 && rrlistlen(dp->rr) > 50 && !dp->keep) { 852530fef66SDavid du Colombier dnslog("rrattach(%s): rr list too long; " 853530fef66SDavid du Colombier "freeing it", dp->name); 854530fef66SDavid du Colombier rrfreelist(dp->rr); 855530fef66SDavid du Colombier dp->rr = nil; 856530fef66SDavid du Colombier } else 857530fef66SDavid du Colombier USED(dp); 8583e12c5d1SDavid du Colombier rrattach1(rp, auth); 859d2fd7a44SDavid du Colombier } 8603e12c5d1SDavid du Colombier } 861bd389b36SDavid du Colombier unlock(&dnlock); 8623e12c5d1SDavid du Colombier } 8633e12c5d1SDavid du Colombier 864530fef66SDavid du Colombier /* should be called with dnlock held */ 8654f8f669cSDavid du Colombier RR** 8667dd7cddfSDavid du Colombier rrcopy(RR *rp, RR **last) 8677dd7cddfSDavid du Colombier { 8684f8f669cSDavid du Colombier Cert *cert; 8694f8f669cSDavid du Colombier Key *key; 8704f8f669cSDavid du Colombier Null *null; 8717dd7cddfSDavid du Colombier RR *nrp; 8727dd7cddfSDavid du Colombier SOA *soa; 8739a747e4fSDavid du Colombier Sig *sig; 87460845620SDavid du Colombier Txt *t, *nt, **l; 8757dd7cddfSDavid du Colombier 8767dd7cddfSDavid du Colombier nrp = rralloc(rp->type); 877a41547ffSDavid du Colombier setmalloctag(nrp, getcallerpc(&rp)); 8789a747e4fSDavid du Colombier switch(rp->type){ 87960845620SDavid du Colombier case Ttxt: 88060845620SDavid du Colombier *nrp = *rp; 88160845620SDavid du Colombier l = &nrp->txt; 88260845620SDavid du Colombier *l = nil; 88360845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next){ 88460845620SDavid du Colombier nt = emalloc(sizeof(*nt)); 88560845620SDavid du Colombier nt->p = estrdup(t->p); 88660845620SDavid du Colombier nt->next = nil; 88760845620SDavid du Colombier *l = nt; 88860845620SDavid du Colombier l = &nt->next; 88960845620SDavid du Colombier } 89060845620SDavid du Colombier break; 8919a747e4fSDavid du Colombier case Tsoa: 8927dd7cddfSDavid du Colombier soa = nrp->soa; 8937dd7cddfSDavid du Colombier *nrp = *rp; 8947dd7cddfSDavid du Colombier nrp->soa = soa; 8957dd7cddfSDavid du Colombier *nrp->soa = *rp->soa; 896dc5a79c1SDavid du Colombier nrp->soa->slaves = copyserverlist(rp->soa->slaves); 8979a747e4fSDavid du Colombier break; 8984f8f669cSDavid du Colombier case Tsrv: 8994f8f669cSDavid du Colombier *nrp = *rp; 900fd87a217SDavid du Colombier nrp->srv = emalloc(sizeof *nrp->srv); 9014f8f669cSDavid du Colombier *nrp->srv = *rp->srv; 9024f8f669cSDavid du Colombier break; 9039a747e4fSDavid du Colombier case Tkey: 9049a747e4fSDavid du Colombier key = nrp->key; 9059a747e4fSDavid du Colombier *nrp = *rp; 9069a747e4fSDavid du Colombier nrp->key = key; 9079a747e4fSDavid du Colombier *key = *rp->key; 9089a747e4fSDavid du Colombier key->data = emalloc(key->dlen); 9099a747e4fSDavid du Colombier memmove(key->data, rp->key->data, rp->key->dlen); 9109a747e4fSDavid du Colombier break; 9119a747e4fSDavid du Colombier case Tsig: 9129a747e4fSDavid du Colombier sig = nrp->sig; 9139a747e4fSDavid du Colombier *nrp = *rp; 9149a747e4fSDavid du Colombier nrp->sig = sig; 9159a747e4fSDavid du Colombier *sig = *rp->sig; 9169a747e4fSDavid du Colombier sig->data = emalloc(sig->dlen); 9179a747e4fSDavid du Colombier memmove(sig->data, rp->sig->data, rp->sig->dlen); 9189a747e4fSDavid du Colombier break; 9199a747e4fSDavid du Colombier case Tcert: 9209a747e4fSDavid du Colombier cert = nrp->cert; 9219a747e4fSDavid du Colombier *nrp = *rp; 9229a747e4fSDavid du Colombier nrp->cert = cert; 9239a747e4fSDavid du Colombier *cert = *rp->cert; 9249a747e4fSDavid du Colombier cert->data = emalloc(cert->dlen); 9259a747e4fSDavid du Colombier memmove(cert->data, rp->cert->data, rp->cert->dlen); 9269a747e4fSDavid du Colombier break; 9279a747e4fSDavid du Colombier case Tnull: 9289a747e4fSDavid du Colombier null = nrp->null; 9299a747e4fSDavid du Colombier *nrp = *rp; 9309a747e4fSDavid du Colombier nrp->null = null; 9319a747e4fSDavid du Colombier *null = *rp->null; 9329a747e4fSDavid du Colombier null->data = emalloc(null->dlen); 9339a747e4fSDavid du Colombier memmove(null->data, rp->null->data, rp->null->dlen); 9349a747e4fSDavid du Colombier break; 9359a747e4fSDavid du Colombier default: 9369a747e4fSDavid du Colombier *nrp = *rp; 9379a747e4fSDavid du Colombier break; 9387dd7cddfSDavid du Colombier } 9397dd7cddfSDavid du Colombier nrp->cached = 0; 9407dd7cddfSDavid du Colombier nrp->next = 0; 9417dd7cddfSDavid du Colombier *last = nrp; 9427dd7cddfSDavid du Colombier return &nrp->next; 9437dd7cddfSDavid du Colombier } 9447dd7cddfSDavid du Colombier 9453e12c5d1SDavid du Colombier /* 9463e12c5d1SDavid du Colombier * lookup a resource record of a particular type and 9477dd7cddfSDavid du Colombier * class attached to a domain name. Return copies. 9487dd7cddfSDavid du Colombier * 9497dd7cddfSDavid du Colombier * Priority ordering is: 9507dd7cddfSDavid du Colombier * db authoritative 9517dd7cddfSDavid du Colombier * not timed out network authoritative 9527dd7cddfSDavid du Colombier * not timed out network unauthoritative 9537dd7cddfSDavid du Colombier * unauthoritative db 9547dd7cddfSDavid du Colombier * 95580ee5cbfSDavid du Colombier * if flag NOneg is set, don't return negative cached entries. 9567dd7cddfSDavid du Colombier * return nothing instead. 9573e12c5d1SDavid du Colombier */ 9583e12c5d1SDavid du Colombier RR* 9597dd7cddfSDavid du Colombier rrlookup(DN *dp, int type, int flag) 9603e12c5d1SDavid du Colombier { 9617dd7cddfSDavid du Colombier RR *rp, *first, **last; 9623e12c5d1SDavid du Colombier 9637dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 9647dd7cddfSDavid du Colombier 9657dd7cddfSDavid du Colombier first = 0; 9667dd7cddfSDavid du Colombier last = &first; 9677dd7cddfSDavid du Colombier lock(&dnlock); 9687dd7cddfSDavid du Colombier 9697dd7cddfSDavid du Colombier /* try for an authoritative db entry */ 9703e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 9717dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 9727dd7cddfSDavid du Colombier if(rp->db) 9737dd7cddfSDavid du Colombier if(rp->auth) 974a41547ffSDavid du Colombier if(tsame(type, rp->type)) { 9754e5f5f32SDavid du Colombier last = rrcopy(rp, last); 976a41547ffSDavid du Colombier // setmalloctag(*last, getcallerpc(&dp)); 977a41547ffSDavid du Colombier } 9783e12c5d1SDavid du Colombier } 9797dd7cddfSDavid du Colombier if(first) 9807dd7cddfSDavid du Colombier goto out; 9817dd7cddfSDavid du Colombier 9824f8f669cSDavid du Colombier /* try for a living authoritative network entry */ 9837dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 9847dd7cddfSDavid du Colombier if(!rp->db) 9857dd7cddfSDavid du Colombier if(rp->auth) 9867dd7cddfSDavid du Colombier if(rp->ttl + 60 > now) 9877dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 9887dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative) 9897dd7cddfSDavid du Colombier goto out; 9907dd7cddfSDavid du Colombier last = rrcopy(rp, last); 9917dd7cddfSDavid du Colombier } 9927dd7cddfSDavid du Colombier } 9937dd7cddfSDavid du Colombier if(first) 9947dd7cddfSDavid du Colombier goto out; 9957dd7cddfSDavid du Colombier 9964f8f669cSDavid du Colombier /* try for a living unauthoritative network entry */ 9977dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 9987dd7cddfSDavid du Colombier if(!rp->db) 9997dd7cddfSDavid du Colombier if(rp->ttl + 60 > now) 10007dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 10017dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative) 10027dd7cddfSDavid du Colombier goto out; 10034e5f5f32SDavid du Colombier last = rrcopy(rp, last); 10047dd7cddfSDavid du Colombier } 10057dd7cddfSDavid du Colombier } 10067dd7cddfSDavid du Colombier if(first) 10077dd7cddfSDavid du Colombier goto out; 10087dd7cddfSDavid du Colombier 10097dd7cddfSDavid du Colombier /* try for an unauthoritative db entry */ 10107dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 10117dd7cddfSDavid du Colombier if(rp->db) 10127dd7cddfSDavid du Colombier if(tsame(type, rp->type)) 10137dd7cddfSDavid du Colombier last = rrcopy(rp, last); 10147dd7cddfSDavid du Colombier } 10157dd7cddfSDavid du Colombier if(first) 10167dd7cddfSDavid du Colombier goto out; 10177dd7cddfSDavid du Colombier 10187dd7cddfSDavid du Colombier /* otherwise, settle for anything we got (except for negative caches) */ 10194f8f669cSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 10207dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 10217dd7cddfSDavid du Colombier if(rp->negative) 10227dd7cddfSDavid du Colombier goto out; 10237dd7cddfSDavid du Colombier last = rrcopy(rp, last); 10247dd7cddfSDavid du Colombier } 10257dd7cddfSDavid du Colombier 10267dd7cddfSDavid du Colombier out: 10277dd7cddfSDavid du Colombier unlock(&dnlock); 10287dd7cddfSDavid du Colombier unique(first); 10294f8f669cSDavid du Colombier // dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first); 1030a41547ffSDavid du Colombier // if (first) 1031a41547ffSDavid du Colombier // setmalloctag(first, getcallerpc(&dp)); 10327dd7cddfSDavid du Colombier return first; 10333e12c5d1SDavid du Colombier } 10343e12c5d1SDavid du Colombier 10353e12c5d1SDavid du Colombier /* 10363e12c5d1SDavid du Colombier * convert an ascii RR type name to its integer representation 10373e12c5d1SDavid du Colombier */ 10383e12c5d1SDavid du Colombier int 10393e12c5d1SDavid du Colombier rrtype(char *atype) 10403e12c5d1SDavid du Colombier { 10413e12c5d1SDavid du Colombier int i; 10423e12c5d1SDavid du Colombier 1043219b2ee8SDavid du Colombier for(i = 0; i <= Tall; i++) 10443e12c5d1SDavid du Colombier if(rrtname[i] && strcmp(rrtname[i], atype) == 0) 10453e12c5d1SDavid du Colombier return i; 10467dd7cddfSDavid du Colombier 10474f8f669cSDavid du Colombier /* make any a synonym for all */ 10487dd7cddfSDavid du Colombier if(strcmp(atype, "any") == 0) 10497dd7cddfSDavid du Colombier return Tall; 1050*d9924332SDavid du Colombier else if(isascii(atype[0]) && isdigit(atype[0])) 10513e12c5d1SDavid du Colombier return atoi(atype); 1052*d9924332SDavid du Colombier else 1053*d9924332SDavid du Colombier return -1; 10543e12c5d1SDavid du Colombier } 10553e12c5d1SDavid du Colombier 10563e12c5d1SDavid du Colombier /* 10575d459b5aSDavid du Colombier * return 0 if not a supported rr type 10585d459b5aSDavid du Colombier */ 10595d459b5aSDavid du Colombier int 10605d459b5aSDavid du Colombier rrsupported(int type) 10615d459b5aSDavid du Colombier { 10625d459b5aSDavid du Colombier if(type < 0 || type >Tall) 10635d459b5aSDavid du Colombier return 0; 10644f8f669cSDavid du Colombier return rrtname[type] != nil; 10655d459b5aSDavid du Colombier } 10665d459b5aSDavid du Colombier 10675d459b5aSDavid du Colombier /* 1068219b2ee8SDavid du Colombier * compare 2 types 1069219b2ee8SDavid du Colombier */ 1070219b2ee8SDavid du Colombier int 1071219b2ee8SDavid du Colombier tsame(int t1, int t2) 1072219b2ee8SDavid du Colombier { 1073219b2ee8SDavid du Colombier return t1 == t2 || t1 == Tall; 1074219b2ee8SDavid du Colombier } 1075219b2ee8SDavid du Colombier 1076219b2ee8SDavid du Colombier /* 10777dd7cddfSDavid du Colombier * Add resource records to a list, duplicate them if they are cached 1078530fef66SDavid du Colombier * RR's since these are shared. should be called with dnlock held 1079530fef66SDavid du Colombier * to avoid racing down the start chain. 10803e12c5d1SDavid du Colombier */ 10813e12c5d1SDavid du Colombier RR* 10827dd7cddfSDavid du Colombier rrcat(RR **start, RR *rp) 10833e12c5d1SDavid du Colombier { 1084225077b0SDavid du Colombier RR *olp, *nlp; 10853e12c5d1SDavid du Colombier RR **last; 10863e12c5d1SDavid du Colombier 1087225077b0SDavid du Colombier /* check for duplicates */ 1088225077b0SDavid du Colombier for (olp = *start; 0 && olp; olp = olp->next) 1089225077b0SDavid du Colombier for (nlp = rp; nlp; nlp = nlp->next) 1090225077b0SDavid du Colombier if (rrsame(nlp, olp)) 1091225077b0SDavid du Colombier dnslog("rrcat: duplicate RR: %R", nlp); 1092225077b0SDavid du Colombier USED(olp); 1093225077b0SDavid du Colombier 10943e12c5d1SDavid du Colombier last = start; 10954f8f669cSDavid du Colombier while(*last != nil) 10963e12c5d1SDavid du Colombier last = &(*last)->next; 10973e12c5d1SDavid du Colombier 10987dd7cddfSDavid du Colombier *last = rp; 10997dd7cddfSDavid du Colombier return *start; 11003e12c5d1SDavid du Colombier } 11013e12c5d1SDavid du Colombier 11027dd7cddfSDavid du Colombier /* 11037dd7cddfSDavid du Colombier * remove negative cache rr's from an rr list 11047dd7cddfSDavid du Colombier */ 11057dd7cddfSDavid du Colombier RR* 11067dd7cddfSDavid du Colombier rrremneg(RR **l) 11077dd7cddfSDavid du Colombier { 11087dd7cddfSDavid du Colombier RR **nl, *rp; 11097dd7cddfSDavid du Colombier RR *first; 11107dd7cddfSDavid du Colombier 11117dd7cddfSDavid du Colombier first = nil; 11127dd7cddfSDavid du Colombier nl = &first; 11137dd7cddfSDavid du Colombier while(*l != nil){ 11147dd7cddfSDavid du Colombier rp = *l; 11157dd7cddfSDavid du Colombier if(rp->negative){ 11167dd7cddfSDavid du Colombier *l = rp->next; 11177dd7cddfSDavid du Colombier *nl = rp; 11187dd7cddfSDavid du Colombier nl = &rp->next; 11197dd7cddfSDavid du Colombier *nl = nil; 11207dd7cddfSDavid du Colombier } else 112180ee5cbfSDavid du Colombier l = &rp->next; 11227dd7cddfSDavid du Colombier } 11237dd7cddfSDavid du Colombier 11247dd7cddfSDavid du Colombier return first; 11257dd7cddfSDavid du Colombier } 11267dd7cddfSDavid du Colombier 11277dd7cddfSDavid du Colombier /* 11287dd7cddfSDavid du Colombier * remove rr's of a particular type from an rr list 11297dd7cddfSDavid du Colombier */ 11307dd7cddfSDavid du Colombier RR* 11317dd7cddfSDavid du Colombier rrremtype(RR **l, int type) 11327dd7cddfSDavid du Colombier { 11334f8f669cSDavid du Colombier RR *first, *rp; 11344f8f669cSDavid du Colombier RR **nl; 11357dd7cddfSDavid du Colombier 11367dd7cddfSDavid du Colombier first = nil; 11377dd7cddfSDavid du Colombier nl = &first; 11387dd7cddfSDavid du Colombier while(*l != nil){ 11397dd7cddfSDavid du Colombier rp = *l; 11407dd7cddfSDavid du Colombier if(rp->type == type){ 11417dd7cddfSDavid du Colombier *l = rp->next; 11427dd7cddfSDavid du Colombier *nl = rp; 11437dd7cddfSDavid du Colombier nl = &rp->next; 11447dd7cddfSDavid du Colombier *nl = nil; 11457dd7cddfSDavid du Colombier } else 11467dd7cddfSDavid du Colombier l = &(*l)->next; 11477dd7cddfSDavid du Colombier } 11487dd7cddfSDavid du Colombier 11497dd7cddfSDavid du Colombier return first; 11503e12c5d1SDavid du Colombier } 11513e12c5d1SDavid du Colombier 11524f8f669cSDavid du Colombier static char * 11534f8f669cSDavid du Colombier dnname(DN *dn) 11544f8f669cSDavid du Colombier { 11554f8f669cSDavid du Colombier return dn? dn->name: "<null>"; 11564f8f669cSDavid du Colombier } 11574f8f669cSDavid du Colombier 11583e12c5d1SDavid du Colombier /* 11593e12c5d1SDavid du Colombier * print conversion for rr records 11603e12c5d1SDavid du Colombier */ 11613e12c5d1SDavid du Colombier int 11629a747e4fSDavid du Colombier rrfmt(Fmt *f) 11633e12c5d1SDavid du Colombier { 11646b0d5c8bSDavid du Colombier int rv; 11654f8f669cSDavid du Colombier char *strp; 11666b0d5c8bSDavid du Colombier char buf[Domlen]; 11674f8f669cSDavid du Colombier Fmt fstr; 11684f8f669cSDavid du Colombier RR *rp; 1169dc5a79c1SDavid du Colombier Server *s; 11704f8f669cSDavid du Colombier SOA *soa; 11714f8f669cSDavid du Colombier Srv *srv; 117260845620SDavid du Colombier Txt *t; 11733e12c5d1SDavid du Colombier 11749a747e4fSDavid du Colombier fmtstrinit(&fstr); 11759a747e4fSDavid du Colombier 11769a747e4fSDavid du Colombier rp = va_arg(f->args, RR*); 11774f8f669cSDavid du Colombier if(rp == nil){ 11789a747e4fSDavid du Colombier fmtprint(&fstr, "<null>"); 1179219b2ee8SDavid du Colombier goto out; 1180219b2ee8SDavid du Colombier } 1181219b2ee8SDavid du Colombier 11824f8f669cSDavid du Colombier fmtprint(&fstr, "%s %s", dnname(rp->owner), 11839a747e4fSDavid du Colombier rrname(rp->type, buf, sizeof buf)); 11847dd7cddfSDavid du Colombier 11857dd7cddfSDavid du Colombier if(rp->negative){ 11869a747e4fSDavid du Colombier fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode); 11877dd7cddfSDavid du Colombier goto out; 11887dd7cddfSDavid du Colombier } 11893e12c5d1SDavid du Colombier 11903e12c5d1SDavid du Colombier switch(rp->type){ 11913e12c5d1SDavid du Colombier case Thinfo: 11924f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os)); 11933e12c5d1SDavid du Colombier break; 11943e12c5d1SDavid du Colombier case Tcname: 11953e12c5d1SDavid du Colombier case Tmb: 11963e12c5d1SDavid du Colombier case Tmd: 11973e12c5d1SDavid du Colombier case Tmf: 11983e12c5d1SDavid du Colombier case Tns: 11994f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->host)); 12003e12c5d1SDavid du Colombier break; 12013e12c5d1SDavid du Colombier case Tmg: 12023e12c5d1SDavid du Colombier case Tmr: 12034f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->mb)); 12043e12c5d1SDavid du Colombier break; 12053e12c5d1SDavid du Colombier case Tminfo: 12064f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb)); 12073e12c5d1SDavid du Colombier break; 12083e12c5d1SDavid du Colombier case Tmx: 12094f8f669cSDavid du Colombier fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host)); 12103e12c5d1SDavid du Colombier break; 12113e12c5d1SDavid du Colombier case Ta: 12125d459b5aSDavid du Colombier case Taaaa: 12134f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ip)); 12143e12c5d1SDavid du Colombier break; 12153e12c5d1SDavid du Colombier case Tptr: 12164f8f669cSDavid du Colombier // fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr), 12174f8f669cSDavid du Colombier // rp->ptr? rp->ptr->ordinal: "<null>"); 12184f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ptr)); 12193e12c5d1SDavid du Colombier break; 12203e12c5d1SDavid du Colombier case Tsoa: 12214f8f669cSDavid du Colombier soa = rp->soa; 12224f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", 12234f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb), 12244f8f669cSDavid du Colombier (soa? soa->serial: 0), 12254f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0), 12264f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0)); 12274f8f669cSDavid du Colombier if (soa) 12284f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next) 1229dc5a79c1SDavid du Colombier fmtprint(&fstr, " %s", s->name); 12303e12c5d1SDavid du Colombier break; 12314f8f669cSDavid du Colombier case Tsrv: 12324f8f669cSDavid du Colombier srv = rp->srv; 12334f8f669cSDavid du Colombier fmtprint(&fstr, "\t%ud %ud %ud %s", 12344f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0), 1235225077b0SDavid du Colombier rp->port, dnname(rp->host)); 12364f8f669cSDavid du Colombier break; 12379a747e4fSDavid du Colombier case Tnull: 12384f8f669cSDavid du Colombier if (rp->null == nil) 12394f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null>"); 12404f8f669cSDavid du Colombier else 12414f8f669cSDavid du Colombier fmtprint(&fstr, "\t%.*H", rp->null->dlen, 12424f8f669cSDavid du Colombier rp->null->data); 12439a747e4fSDavid du Colombier break; 12447dd7cddfSDavid du Colombier case Ttxt: 124560845620SDavid du Colombier fmtprint(&fstr, "\t"); 124660845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 124760845620SDavid du Colombier fmtprint(&fstr, "%s", t->p); 12487dd7cddfSDavid du Colombier break; 12497dd7cddfSDavid du Colombier case Trp: 12504f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp)); 12517dd7cddfSDavid du Colombier break; 12527dd7cddfSDavid du Colombier case Tkey: 12534f8f669cSDavid du Colombier if (rp->key == nil) 12544f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>"); 12554f8f669cSDavid du Colombier else 12564f8f669cSDavid du Colombier fmtprint(&fstr, "\t%d %d %d", rp->key->flags, 12574f8f669cSDavid du Colombier rp->key->proto, rp->key->alg); 12587dd7cddfSDavid du Colombier break; 12597dd7cddfSDavid du Colombier case Tsig: 12604f8f669cSDavid du Colombier if (rp->sig == nil) 12614f8f669cSDavid du Colombier fmtprint(&fstr, 12624f8f669cSDavid du Colombier "\t<null> <null> <null> <null> <null> <null> <null> <null>"); 12634f8f669cSDavid du Colombier else 12649a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s", 12654f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels, 12664f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep, 12674f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer)); 12687dd7cddfSDavid du Colombier break; 12697dd7cddfSDavid du Colombier case Tcert: 12704f8f669cSDavid du Colombier if (rp->cert == nil) 12714f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>"); 12724f8f669cSDavid du Colombier else 12739a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d", 12744f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg); 12753e12c5d1SDavid du Colombier break; 12763e12c5d1SDavid du Colombier } 1277219b2ee8SDavid du Colombier out: 12789a747e4fSDavid du Colombier strp = fmtstrflush(&fstr); 12799a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp); 12809a747e4fSDavid du Colombier free(strp); 12819a747e4fSDavid du Colombier return rv; 12823e12c5d1SDavid du Colombier } 12833e12c5d1SDavid du Colombier 12843e12c5d1SDavid du Colombier /* 12857dd7cddfSDavid du Colombier * print conversion for rr records in attribute value form 12867dd7cddfSDavid du Colombier */ 12877dd7cddfSDavid du Colombier int 12889a747e4fSDavid du Colombier rravfmt(Fmt *f) 12897dd7cddfSDavid du Colombier { 12904f8f669cSDavid du Colombier int rv, quote; 12919a747e4fSDavid du Colombier char *strp; 12929a747e4fSDavid du Colombier Fmt fstr; 12934f8f669cSDavid du Colombier RR *rp; 1294dc5a79c1SDavid du Colombier Server *s; 12954f8f669cSDavid du Colombier SOA *soa; 12964f8f669cSDavid du Colombier Srv *srv; 129760845620SDavid du Colombier Txt *t; 12987dd7cddfSDavid du Colombier 12999a747e4fSDavid du Colombier fmtstrinit(&fstr); 13009a747e4fSDavid du Colombier 13019a747e4fSDavid du Colombier rp = va_arg(f->args, RR*); 13024f8f669cSDavid du Colombier if(rp == nil){ 13039a747e4fSDavid du Colombier fmtprint(&fstr, "<null>"); 13047dd7cddfSDavid du Colombier goto out; 13057dd7cddfSDavid du Colombier } 13067dd7cddfSDavid du Colombier 13077dd7cddfSDavid du Colombier if(rp->type == Tptr) 13084f8f669cSDavid du Colombier fmtprint(&fstr, "ptr=%s", dnname(rp->owner)); 13097dd7cddfSDavid du Colombier else 13104f8f669cSDavid du Colombier fmtprint(&fstr, "dom=%s", dnname(rp->owner)); 13117dd7cddfSDavid du Colombier 13127dd7cddfSDavid du Colombier switch(rp->type){ 13137dd7cddfSDavid du Colombier case Thinfo: 13144f8f669cSDavid du Colombier fmtprint(&fstr, " cpu=%s os=%s", 13154f8f669cSDavid du Colombier dnname(rp->cpu), dnname(rp->os)); 13167dd7cddfSDavid du Colombier break; 13177dd7cddfSDavid du Colombier case Tcname: 13184f8f669cSDavid du Colombier fmtprint(&fstr, " cname=%s", dnname(rp->host)); 13197dd7cddfSDavid du Colombier break; 13207dd7cddfSDavid du Colombier case Tmb: 13217dd7cddfSDavid du Colombier case Tmd: 13227dd7cddfSDavid du Colombier case Tmf: 13234f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->host)); 13247dd7cddfSDavid du Colombier break; 13257dd7cddfSDavid du Colombier case Tns: 13264f8f669cSDavid du Colombier fmtprint(&fstr, " ns=%s", dnname(rp->host)); 13277dd7cddfSDavid du Colombier break; 13287dd7cddfSDavid du Colombier case Tmg: 13297dd7cddfSDavid du Colombier case Tmr: 13304f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->mb)); 13317dd7cddfSDavid du Colombier break; 13327dd7cddfSDavid du Colombier case Tminfo: 13334f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s mbox=%s", 13344f8f669cSDavid du Colombier dnname(rp->mb), dnname(rp->rmb)); 13357dd7cddfSDavid du Colombier break; 13367dd7cddfSDavid du Colombier case Tmx: 13374f8f669cSDavid du Colombier fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host)); 13387dd7cddfSDavid du Colombier break; 13397dd7cddfSDavid du Colombier case Ta: 13405d459b5aSDavid du Colombier case Taaaa: 13414f8f669cSDavid du Colombier fmtprint(&fstr, " ip=%s", dnname(rp->ip)); 13427dd7cddfSDavid du Colombier break; 13437dd7cddfSDavid du Colombier case Tptr: 13444f8f669cSDavid du Colombier fmtprint(&fstr, " dom=%s", dnname(rp->ptr)); 13457dd7cddfSDavid du Colombier break; 13467dd7cddfSDavid du Colombier case Tsoa: 13474f8f669cSDavid du Colombier soa = rp->soa; 13484f8f669cSDavid du Colombier fmtprint(&fstr, 13494f8f669cSDavid du Colombier " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud", 13504f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb), 13514f8f669cSDavid du Colombier (soa? soa->serial: 0), 13524f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0), 13534f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0)); 13544f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next) 1355dc5a79c1SDavid du Colombier fmtprint(&fstr, " dnsslave=%s", s->name); 13567dd7cddfSDavid du Colombier break; 13574f8f669cSDavid du Colombier case Tsrv: 13584f8f669cSDavid du Colombier srv = rp->srv; 13594f8f669cSDavid du Colombier fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s", 13604f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0), 1361225077b0SDavid du Colombier rp->port, dnname(rp->host)); 13624f8f669cSDavid du Colombier break; 13639a747e4fSDavid du Colombier case Tnull: 13644f8f669cSDavid du Colombier if (rp->null == nil) 13654f8f669cSDavid du Colombier fmtprint(&fstr, " null=<null>"); 13664f8f669cSDavid du Colombier else 13674f8f669cSDavid du Colombier fmtprint(&fstr, " null=%.*H", rp->null->dlen, 13684f8f669cSDavid du Colombier rp->null->data); 13699a747e4fSDavid du Colombier break; 13707dd7cddfSDavid du Colombier case Ttxt: 137160845620SDavid du Colombier fmtprint(&fstr, " txt="); 137260845620SDavid du Colombier quote = 0; 137360845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 137460845620SDavid du Colombier if(strchr(t->p, ' ')) 137560845620SDavid du Colombier quote = 1; 137660845620SDavid du Colombier if(quote) 137760845620SDavid du Colombier fmtprint(&fstr, "\""); 137860845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 137960845620SDavid du Colombier fmtprint(&fstr, "%s", t->p); 138060845620SDavid du Colombier if(quote) 138160845620SDavid du Colombier fmtprint(&fstr, "\""); 13827dd7cddfSDavid du Colombier break; 13837dd7cddfSDavid du Colombier case Trp: 13844f8f669cSDavid du Colombier fmtprint(&fstr, " rp=%s txt=%s", 13854f8f669cSDavid du Colombier dnname(rp->rmb), dnname(rp->rp)); 13867dd7cddfSDavid du Colombier break; 13877dd7cddfSDavid du Colombier case Tkey: 13884f8f669cSDavid du Colombier if (rp->key == nil) 13894f8f669cSDavid du Colombier fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>"); 13904f8f669cSDavid du Colombier else 13919a747e4fSDavid du Colombier fmtprint(&fstr, " flags=%d proto=%d alg=%d", 13927dd7cddfSDavid du Colombier rp->key->flags, rp->key->proto, rp->key->alg); 13937dd7cddfSDavid du Colombier break; 13947dd7cddfSDavid du Colombier case Tsig: 13954f8f669cSDavid du Colombier if (rp->sig == nil) 13964f8f669cSDavid du Colombier fmtprint(&fstr, 13974f8f669cSDavid du Colombier " type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>"); 13984f8f669cSDavid du Colombier else 13994f8f669cSDavid du Colombier fmtprint(&fstr, 14004f8f669cSDavid du Colombier " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s", 14014f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels, 14024f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep, 14034f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer)); 14047dd7cddfSDavid du Colombier break; 14057dd7cddfSDavid du Colombier case Tcert: 14064f8f669cSDavid du Colombier if (rp->cert == nil) 14074f8f669cSDavid du Colombier fmtprint(&fstr, " type=<null> tag=<null> alg=<null>"); 14084f8f669cSDavid du Colombier else 14099a747e4fSDavid du Colombier fmtprint(&fstr, " type=%d tag=%d alg=%d", 14104f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg); 14117dd7cddfSDavid du Colombier break; 14127dd7cddfSDavid du Colombier } 14137dd7cddfSDavid du Colombier out: 14149a747e4fSDavid du Colombier strp = fmtstrflush(&fstr); 14159a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp); 14169a747e4fSDavid du Colombier free(strp); 14179a747e4fSDavid du Colombier return rv; 14183e12c5d1SDavid du Colombier } 14197dd7cddfSDavid du Colombier 14207dd7cddfSDavid du Colombier void 14217dd7cddfSDavid du Colombier warning(char *fmt, ...) 14227dd7cddfSDavid du Colombier { 14234f8f669cSDavid du Colombier char dnserr[256]; 14247dd7cddfSDavid du Colombier va_list arg; 14257dd7cddfSDavid du Colombier 14267dd7cddfSDavid du Colombier va_start(arg, fmt); 14279a747e4fSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); 14287dd7cddfSDavid du Colombier va_end(arg); 14294f8f669cSDavid du Colombier syslog(1, logfile, dnserr); /* on console too */ 14304f8f669cSDavid du Colombier } 14314f8f669cSDavid du Colombier 14324f8f669cSDavid du Colombier void 14334f8f669cSDavid du Colombier dnslog(char *fmt, ...) 14344f8f669cSDavid du Colombier { 14354f8f669cSDavid du Colombier char dnserr[256]; 14364f8f669cSDavid du Colombier va_list arg; 14374f8f669cSDavid du Colombier 14384f8f669cSDavid du Colombier va_start(arg, fmt); 14394f8f669cSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); 14404f8f669cSDavid du Colombier va_end(arg); 14414f8f669cSDavid du Colombier syslog(0, logfile, dnserr); 14424f8f669cSDavid du Colombier } 14434f8f669cSDavid du Colombier 14444f8f669cSDavid du Colombier /* 14454f8f669cSDavid du Colombier * based on libthread's threadsetname, but drags in less library code. 14464f8f669cSDavid du Colombier * actually just sets the arguments displayed. 14474f8f669cSDavid du Colombier */ 14484f8f669cSDavid du Colombier void 14494f8f669cSDavid du Colombier procsetname(char *fmt, ...) 14504f8f669cSDavid du Colombier { 14514f8f669cSDavid du Colombier int fd; 14524f8f669cSDavid du Colombier char *cmdname; 14534f8f669cSDavid du Colombier char buf[128]; 14544f8f669cSDavid du Colombier va_list arg; 14554f8f669cSDavid du Colombier 14564f8f669cSDavid du Colombier va_start(arg, fmt); 14574f8f669cSDavid du Colombier cmdname = vsmprint(fmt, arg); 14584f8f669cSDavid du Colombier va_end(arg); 14594f8f669cSDavid du Colombier if (cmdname == nil) 14604f8f669cSDavid du Colombier return; 14614f8f669cSDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid()); 14624f8f669cSDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){ 14634f8f669cSDavid du Colombier write(fd, cmdname, strlen(cmdname)+1); 14644f8f669cSDavid du Colombier close(fd); 14654f8f669cSDavid du Colombier } 14664f8f669cSDavid du Colombier free(cmdname); 14677dd7cddfSDavid du Colombier } 14687dd7cddfSDavid du Colombier 14697dd7cddfSDavid du Colombier /* 14707dd7cddfSDavid du Colombier * create a slave process to handle a request to avoid one request blocking 14717dd7cddfSDavid du Colombier * another 14727dd7cddfSDavid du Colombier */ 14737dd7cddfSDavid du Colombier void 14747dd7cddfSDavid du Colombier slave(Request *req) 14757dd7cddfSDavid du Colombier { 1476a41547ffSDavid du Colombier int ppid, procs; 14777dd7cddfSDavid du Colombier 14787dd7cddfSDavid du Colombier if(req->isslave) 14797dd7cddfSDavid du Colombier return; /* we're already a slave process */ 14807dd7cddfSDavid du Colombier 1481b4b9fc2fSDavid du Colombier /* 1482b4b9fc2fSDavid du Colombier * These calls to putactivity cannot block. 1483b4b9fc2fSDavid du Colombier * After getactivity(), the current process is counted 1484b4b9fc2fSDavid du Colombier * twice in dnvars.active (one will pass to the child). 1485b4b9fc2fSDavid du Colombier * If putactivity tries to wait for dnvars.active == 0, 1486b4b9fc2fSDavid du Colombier * it will never happen. 1487b4b9fc2fSDavid du Colombier */ 1488b4b9fc2fSDavid du Colombier 14897dd7cddfSDavid du Colombier /* limit parallelism */ 1490a41547ffSDavid du Colombier procs = getactivity(req, 1); 1491a41547ffSDavid du Colombier if (procs > stats.slavehiwat) 1492a41547ffSDavid du Colombier stats.slavehiwat = procs; 1493a41547ffSDavid du Colombier if(procs > Maxactive){ 14944f8f669cSDavid du Colombier if(traceactivity) 14954f8f669cSDavid du Colombier dnslog("[%d] too much activity", getpid()); 1496b4b9fc2fSDavid du Colombier putactivity(1); 14977dd7cddfSDavid du Colombier return; 14987dd7cddfSDavid du Colombier } 14997dd7cddfSDavid du Colombier 1500c73252aeSDavid du Colombier /* 1501c73252aeSDavid du Colombier * parent returns to main loop, child does the work. 1502c73252aeSDavid du Colombier * don't change note group. 1503c73252aeSDavid du Colombier */ 1504b4b9fc2fSDavid du Colombier ppid = getpid(); 1505c73252aeSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){ 15067dd7cddfSDavid du Colombier case -1: 1507b4b9fc2fSDavid du Colombier putactivity(1); 15087dd7cddfSDavid du Colombier break; 15097dd7cddfSDavid du Colombier case 0: 15104f8f669cSDavid du Colombier procsetname("request slave of pid %d", ppid); 15114f8f669cSDavid du Colombier if(traceactivity) 1512a41547ffSDavid du Colombier dnslog("[%d] take activity from %d", getpid(), ppid); 15134f8f669cSDavid du Colombier req->isslave = 1; /* why not `= getpid()'? */ 15147dd7cddfSDavid du Colombier break; 15157dd7cddfSDavid du Colombier default: 15164f8f669cSDavid du Colombier /* 15174f8f669cSDavid du Colombier * this relies on rfork producing separate, initially-identical 15184f8f669cSDavid du Colombier * stacks, thus giving us two copies of `req', one in each 15194f8f669cSDavid du Colombier * process. 15204f8f669cSDavid du Colombier */ 15216aaebd7dSDavid du Colombier alarm(0); 15227dd7cddfSDavid du Colombier longjmp(req->mret, 1); 15237dd7cddfSDavid du Colombier } 15247dd7cddfSDavid du Colombier } 15257dd7cddfSDavid du Colombier 15267dd7cddfSDavid du Colombier /* 15277dd7cddfSDavid du Colombier * chasing down double free's 15287dd7cddfSDavid du Colombier */ 15297dd7cddfSDavid du Colombier void 15307dd7cddfSDavid du Colombier dncheck(void *p, int dolock) 15317dd7cddfSDavid du Colombier { 15327dd7cddfSDavid du Colombier int i; 15337dd7cddfSDavid du Colombier DN *dp; 15347dd7cddfSDavid du Colombier RR *rp; 15357dd7cddfSDavid du Colombier 15367dd7cddfSDavid du Colombier if(p != nil){ 15377dd7cddfSDavid du Colombier dp = p; 15387dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 15397dd7cddfSDavid du Colombier } 15407dd7cddfSDavid du Colombier 15417dd7cddfSDavid du Colombier if(!testing) 15427dd7cddfSDavid du Colombier return; 15437dd7cddfSDavid du Colombier 15447dd7cddfSDavid du Colombier if(dolock) 15457dd7cddfSDavid du Colombier lock(&dnlock); 15469a747e4fSDavid du Colombier poolcheck(mainmem); 15477dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 15487dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 15497dd7cddfSDavid du Colombier assert(dp != p); 15507dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 15517dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 15527dd7cddfSDavid du Colombier assert(rp->magic == RRmagic); 15537dd7cddfSDavid du Colombier assert(rp->cached); 15547dd7cddfSDavid du Colombier assert(rp->owner == dp); 1555225077b0SDavid du Colombier /* also check for duplicate rrs */ 15564f927735SDavid du Colombier if (dolock && rronlist(rp, rp->next)) { 15574f927735SDavid du Colombier dnslog("%R duplicates its next chain " 15584f927735SDavid du Colombier "(%R); aborting", rp, rp->next); 15594f927735SDavid du Colombier abort(); 15604f927735SDavid du Colombier } 15617dd7cddfSDavid du Colombier } 15627dd7cddfSDavid du Colombier } 15637dd7cddfSDavid du Colombier if(dolock) 15647dd7cddfSDavid du Colombier unlock(&dnlock); 15657dd7cddfSDavid du Colombier } 15667dd7cddfSDavid du Colombier 15677dd7cddfSDavid du Colombier static int 15687dd7cddfSDavid du Colombier rrequiv(RR *r1, RR *r2) 15697dd7cddfSDavid du Colombier { 15707dd7cddfSDavid du Colombier return r1->owner == r2->owner 15717dd7cddfSDavid du Colombier && r1->type == r2->type 15727dd7cddfSDavid du Colombier && r1->arg0 == r2->arg0 1573225077b0SDavid du Colombier && r1->arg1 == r2->arg1; 15747dd7cddfSDavid du Colombier } 15757dd7cddfSDavid du Colombier 15767dd7cddfSDavid du Colombier void 15777dd7cddfSDavid du Colombier unique(RR *rp) 15787dd7cddfSDavid du Colombier { 15797dd7cddfSDavid du Colombier RR **l, *nrp; 15807dd7cddfSDavid du Colombier 15817dd7cddfSDavid du Colombier for(; rp; rp = rp->next){ 15827dd7cddfSDavid du Colombier l = &rp->next; 15834f8f669cSDavid du Colombier for(nrp = *l; nrp; nrp = *l) 15847dd7cddfSDavid du Colombier if(rrequiv(rp, nrp)){ 15857dd7cddfSDavid du Colombier *l = nrp->next; 15867dd7cddfSDavid du Colombier rrfree(nrp); 15877dd7cddfSDavid du Colombier } else 15887dd7cddfSDavid du Colombier l = &nrp->next; 15897dd7cddfSDavid du Colombier } 15907dd7cddfSDavid du Colombier } 15917dd7cddfSDavid du Colombier 15927dd7cddfSDavid du Colombier /* 15937dd7cddfSDavid du Colombier * true if second domain is subsumed by the first 15947dd7cddfSDavid du Colombier */ 15957dd7cddfSDavid du Colombier int 15967dd7cddfSDavid du Colombier subsume(char *higher, char *lower) 15977dd7cddfSDavid du Colombier { 15987dd7cddfSDavid du Colombier int hn, ln; 15997dd7cddfSDavid du Colombier 16007dd7cddfSDavid du Colombier ln = strlen(lower); 16017dd7cddfSDavid du Colombier hn = strlen(higher); 16024f8f669cSDavid du Colombier if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 || 16034f8f669cSDavid du Colombier ln > hn && hn != 0 && lower[ln - hn - 1] != '.') 16047dd7cddfSDavid du Colombier return 0; 16057dd7cddfSDavid du Colombier return 1; 16067dd7cddfSDavid du Colombier } 16077dd7cddfSDavid du Colombier 16087dd7cddfSDavid du Colombier /* 16097dd7cddfSDavid du Colombier * randomize the order we return items to provide some 16105d459b5aSDavid du Colombier * load balancing for servers. 16115d459b5aSDavid du Colombier * 16125d459b5aSDavid du Colombier * only randomize the first class of entries 16137dd7cddfSDavid du Colombier */ 16147dd7cddfSDavid du Colombier RR* 16157dd7cddfSDavid du Colombier randomize(RR *rp) 16167dd7cddfSDavid du Colombier { 16175d459b5aSDavid du Colombier RR *first, *last, *x, *base; 16187dd7cddfSDavid du Colombier ulong n; 16197dd7cddfSDavid du Colombier 16207dd7cddfSDavid du Colombier if(rp == nil || rp->next == nil) 16217dd7cddfSDavid du Colombier return rp; 16227dd7cddfSDavid du Colombier 16233cbadd90SDavid du Colombier /* just randomize addresses, mx's and ns's */ 16247dd7cddfSDavid du Colombier for(x = rp; x; x = x->next) 1625adb31a62SDavid du Colombier if(x->type != Ta && x->type != Taaaa && 1626adb31a62SDavid du Colombier x->type != Tmx && x->type != Tns) 16277dd7cddfSDavid du Colombier return rp; 16287dd7cddfSDavid du Colombier 16295d459b5aSDavid du Colombier base = rp; 16305d459b5aSDavid du Colombier 16317dd7cddfSDavid du Colombier n = rand(); 16327dd7cddfSDavid du Colombier last = first = nil; 16337dd7cddfSDavid du Colombier while(rp != nil){ 16345d459b5aSDavid du Colombier /* stop randomizing if we've moved past our class */ 16355d459b5aSDavid du Colombier if(base->auth != rp->auth || base->db != rp->db){ 16365d459b5aSDavid du Colombier last->next = rp; 16375d459b5aSDavid du Colombier break; 16385d459b5aSDavid du Colombier } 16395d459b5aSDavid du Colombier 16407dd7cddfSDavid du Colombier /* unchain */ 16417dd7cddfSDavid du Colombier x = rp; 16427dd7cddfSDavid du Colombier rp = x->next; 16437dd7cddfSDavid du Colombier x->next = nil; 16447dd7cddfSDavid du Colombier 1645225077b0SDavid du Colombier if(n&1){ 16467dd7cddfSDavid du Colombier /* add to tail */ 16477dd7cddfSDavid du Colombier if(last == nil) 16487dd7cddfSDavid du Colombier first = x; 16497dd7cddfSDavid du Colombier else 16507dd7cddfSDavid du Colombier last->next = x; 16517dd7cddfSDavid du Colombier last = x; 16527dd7cddfSDavid du Colombier } else { 16537dd7cddfSDavid du Colombier /* add to head */ 16547dd7cddfSDavid du Colombier if(last == nil) 16557dd7cddfSDavid du Colombier last = x; 16567dd7cddfSDavid du Colombier x->next = first; 16577dd7cddfSDavid du Colombier first = x; 16587dd7cddfSDavid du Colombier } 16597dd7cddfSDavid du Colombier 16607dd7cddfSDavid du Colombier /* reroll the dice */ 16617dd7cddfSDavid du Colombier n >>= 1; 16627dd7cddfSDavid du Colombier } 16633cbadd90SDavid du Colombier 16647dd7cddfSDavid du Colombier return first; 16657dd7cddfSDavid du Colombier } 166659cc4ca5SDavid du Colombier 16679a747e4fSDavid du Colombier static int 16689a747e4fSDavid du Colombier sencodefmt(Fmt *f) 166959cc4ca5SDavid du Colombier { 16704f8f669cSDavid du Colombier int i, len, ilen, rv; 16714f8f669cSDavid du Colombier char *out, *buf; 16729a747e4fSDavid du Colombier uchar *b; 16734f8f669cSDavid du Colombier char obuf[64]; /* rsc optimization */ 167459cc4ca5SDavid du Colombier 16759a747e4fSDavid du Colombier if(!(f->flags&FmtPrec) || f->prec < 1) 16769a747e4fSDavid du Colombier goto error; 16779a747e4fSDavid du Colombier 16789a747e4fSDavid du Colombier b = va_arg(f->args, uchar*); 16799a747e4fSDavid du Colombier if(b == nil) 16809a747e4fSDavid du Colombier goto error; 16819a747e4fSDavid du Colombier 16829a747e4fSDavid du Colombier /* if it's a printable, go for it */ 16839a747e4fSDavid du Colombier len = f->prec; 16849a747e4fSDavid du Colombier for(i = 0; i < len; i++) 16859a747e4fSDavid du Colombier if(!isprint(b[i])) 16869a747e4fSDavid du Colombier break; 16879a747e4fSDavid du Colombier if(i == len){ 16889a747e4fSDavid du Colombier if(len >= sizeof obuf) 16899a747e4fSDavid du Colombier len = sizeof(obuf)-1; 16909a747e4fSDavid du Colombier memmove(obuf, b, len); 16919a747e4fSDavid du Colombier obuf[len] = 0; 16929a747e4fSDavid du Colombier fmtstrcpy(f, obuf); 16939a747e4fSDavid du Colombier return 0; 169459cc4ca5SDavid du Colombier } 169559cc4ca5SDavid du Colombier 16969a747e4fSDavid du Colombier ilen = f->prec; 16979a747e4fSDavid du Colombier f->prec = 0; 16989a747e4fSDavid du Colombier f->flags &= ~FmtPrec; 16999a747e4fSDavid du Colombier switch(f->r){ 17009a747e4fSDavid du Colombier case '<': 17019a747e4fSDavid du Colombier len = (8*ilen+4)/5 + 3; 17029a747e4fSDavid du Colombier break; 17039a747e4fSDavid du Colombier case '[': 17049a747e4fSDavid du Colombier len = (8*ilen+5)/6 + 4; 17059a747e4fSDavid du Colombier break; 17069a747e4fSDavid du Colombier case 'H': 17079a747e4fSDavid du Colombier len = 2*ilen + 1; 17089a747e4fSDavid du Colombier break; 17099a747e4fSDavid du Colombier default: 17109a747e4fSDavid du Colombier goto error; 17119a747e4fSDavid du Colombier } 171259cc4ca5SDavid du Colombier 17139a747e4fSDavid du Colombier if(len > sizeof(obuf)){ 17149a747e4fSDavid du Colombier buf = malloc(len); 17159a747e4fSDavid du Colombier if(buf == nil) 17169a747e4fSDavid du Colombier goto error; 17179a747e4fSDavid du Colombier } else 17189a747e4fSDavid du Colombier buf = obuf; 17199a747e4fSDavid du Colombier 17204f8f669cSDavid du Colombier /* convert */ 17219a747e4fSDavid du Colombier out = buf; 17229a747e4fSDavid du Colombier switch(f->r){ 17239a747e4fSDavid du Colombier case '<': 17249a747e4fSDavid du Colombier rv = enc32(out, len, b, ilen); 17259a747e4fSDavid du Colombier break; 17269a747e4fSDavid du Colombier case '[': 17279a747e4fSDavid du Colombier rv = enc64(out, len, b, ilen); 17289a747e4fSDavid du Colombier break; 17299a747e4fSDavid du Colombier case 'H': 17309a747e4fSDavid du Colombier rv = enc16(out, len, b, ilen); 17319a747e4fSDavid du Colombier break; 17329a747e4fSDavid du Colombier default: 17339a747e4fSDavid du Colombier rv = -1; 17349a747e4fSDavid du Colombier break; 17359a747e4fSDavid du Colombier } 17369a747e4fSDavid du Colombier if(rv < 0) 17379a747e4fSDavid du Colombier goto error; 17389a747e4fSDavid du Colombier 17399a747e4fSDavid du Colombier fmtstrcpy(f, buf); 17409a747e4fSDavid du Colombier if(buf != obuf) 17419a747e4fSDavid du Colombier free(buf); 17429a747e4fSDavid du Colombier return 0; 17439a747e4fSDavid du Colombier 17449a747e4fSDavid du Colombier error: 17459a747e4fSDavid du Colombier return fmtstrcpy(f, "<encodefmt>"); 17469a747e4fSDavid du Colombier } 17479a747e4fSDavid du Colombier 17489a747e4fSDavid du Colombier void* 17499a747e4fSDavid du Colombier emalloc(int size) 17509a747e4fSDavid du Colombier { 17519a747e4fSDavid du Colombier char *x; 17529a747e4fSDavid du Colombier 17539a747e4fSDavid du Colombier x = mallocz(size, 1); 17549a747e4fSDavid du Colombier if(x == nil) 17559a747e4fSDavid du Colombier abort(); 175634f77ae3SDavid du Colombier setmalloctag(x, getcallerpc(&size)); 17579a747e4fSDavid du Colombier return x; 17589a747e4fSDavid du Colombier } 17599a747e4fSDavid du Colombier 17609a747e4fSDavid du Colombier char* 17619a747e4fSDavid du Colombier estrdup(char *s) 17629a747e4fSDavid du Colombier { 17639a747e4fSDavid du Colombier int size; 17649a747e4fSDavid du Colombier char *p; 17659a747e4fSDavid du Colombier 17669a747e4fSDavid du Colombier size = strlen(s)+1; 17679a747e4fSDavid du Colombier p = mallocz(size, 0); 17689a747e4fSDavid du Colombier if(p == nil) 17699a747e4fSDavid du Colombier abort(); 17709a747e4fSDavid du Colombier memmove(p, s, size); 177134f77ae3SDavid du Colombier setmalloctag(p, getcallerpc(&s)); 17729a747e4fSDavid du Colombier return p; 177359cc4ca5SDavid du Colombier } 17743ff48bf5SDavid du Colombier 17753ff48bf5SDavid du Colombier /* 17763ff48bf5SDavid du Colombier * create a pointer record 17773ff48bf5SDavid du Colombier */ 17783ff48bf5SDavid du Colombier static RR* 17793ff48bf5SDavid du Colombier mkptr(DN *dp, char *ptr, ulong ttl) 17803ff48bf5SDavid du Colombier { 17813ff48bf5SDavid du Colombier DN *ipdp; 17823ff48bf5SDavid du Colombier RR *rp; 17833ff48bf5SDavid du Colombier 17843ff48bf5SDavid du Colombier ipdp = dnlookup(ptr, Cin, 1); 17853ff48bf5SDavid du Colombier 17863ff48bf5SDavid du Colombier rp = rralloc(Tptr); 17873ff48bf5SDavid du Colombier rp->ptr = dp; 17883ff48bf5SDavid du Colombier rp->owner = ipdp; 17893ff48bf5SDavid du Colombier rp->db = 1; 17903ff48bf5SDavid du Colombier if(ttl) 17913ff48bf5SDavid du Colombier rp->ttl = ttl; 17923ff48bf5SDavid du Colombier return rp; 17933ff48bf5SDavid du Colombier } 17943ff48bf5SDavid du Colombier 179553874d13SDavid du Colombier void bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes); 179653874d13SDavid du Colombier 17973ff48bf5SDavid du Colombier /* 17983ff48bf5SDavid du Colombier * look for all ip addresses in this network and make 17993ff48bf5SDavid du Colombier * pointer records for them. 18003ff48bf5SDavid du Colombier */ 18013ff48bf5SDavid du Colombier void 180253874d13SDavid du Colombier dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl) 18033ff48bf5SDavid du Colombier { 180453874d13SDavid du Colombier int i, j, len; 18054f8f669cSDavid du Colombier char *p, *e; 18064f8f669cSDavid du Colombier char ptr[Domlen]; 180753874d13SDavid du Colombier uchar *ipp; 18084f8f669cSDavid du Colombier uchar ip[IPaddrlen], nnet[IPaddrlen]; 180953874d13SDavid du Colombier uchar nibip[IPaddrlen*2]; 18103ff48bf5SDavid du Colombier DN *dp; 18113ff48bf5SDavid du Colombier RR *rp, *nrp, *first, **l; 18123ff48bf5SDavid du Colombier 18133ff48bf5SDavid du Colombier l = &first; 18143ff48bf5SDavid du Colombier first = nil; 18154f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++) 18164f8f669cSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 18173ff48bf5SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 181853874d13SDavid du Colombier if(rp->type != forwtype || rp->negative) 18193ff48bf5SDavid du Colombier continue; 18203ff48bf5SDavid du Colombier parseip(ip, rp->ip->name); 18213ff48bf5SDavid du Colombier maskip(ip, mask, nnet); 18223ff48bf5SDavid du Colombier if(ipcmp(net, nnet) != 0) 18233ff48bf5SDavid du Colombier continue; 182453874d13SDavid du Colombier 182553874d13SDavid du Colombier ipp = ip; 182653874d13SDavid du Colombier len = IPaddrlen; 182753874d13SDavid du Colombier if (forwtype == Taaaa) { 182853874d13SDavid du Colombier bytes2nibbles(nibip, ip, IPaddrlen); 182953874d13SDavid du Colombier ipp = nibip; 183053874d13SDavid du Colombier len = 2*IPaddrlen; 183153874d13SDavid du Colombier } 183253874d13SDavid du Colombier 18333ff48bf5SDavid du Colombier p = ptr; 18343ff48bf5SDavid du Colombier e = ptr+sizeof(ptr); 183553874d13SDavid du Colombier for(j = len - 1; j >= len - subdoms; j--) 183653874d13SDavid du Colombier p = seprint(p, e, (forwtype == Ta? 183753874d13SDavid du Colombier "%d.": "%x."), ipp[j]); 18383ff48bf5SDavid du Colombier seprint(p, e, "%s", dom); 183953874d13SDavid du Colombier 18403ff48bf5SDavid du Colombier nrp = mkptr(dp, ptr, ttl); 18413ff48bf5SDavid du Colombier *l = nrp; 18423ff48bf5SDavid du Colombier l = &nrp->next; 18433ff48bf5SDavid du Colombier } 18443ff48bf5SDavid du Colombier 18453ff48bf5SDavid du Colombier for(rp = first; rp != nil; rp = nrp){ 18463ff48bf5SDavid du Colombier nrp = rp->next; 18473ff48bf5SDavid du Colombier rp->next = nil; 18486dc4800dSDavid du Colombier rrattach(rp, Authoritative); 18493ff48bf5SDavid du Colombier } 18503ff48bf5SDavid du Colombier } 1851dc5a79c1SDavid du Colombier 1852dc5a79c1SDavid du Colombier void 1853dc5a79c1SDavid du Colombier addserver(Server **l, char *name) 1854dc5a79c1SDavid du Colombier { 1855dc5a79c1SDavid du Colombier Server *s; 1856dc5a79c1SDavid du Colombier 1857dc5a79c1SDavid du Colombier while(*l) 1858dc5a79c1SDavid du Colombier l = &(*l)->next; 1859dc5a79c1SDavid du Colombier s = malloc(sizeof(Server)+strlen(name)+1); 1860dc5a79c1SDavid du Colombier if(s == nil) 1861dc5a79c1SDavid du Colombier return; 1862dc5a79c1SDavid du Colombier s->name = (char*)(s+1); 1863dc5a79c1SDavid du Colombier strcpy(s->name, name); 1864dc5a79c1SDavid du Colombier s->next = nil; 1865dc5a79c1SDavid du Colombier *l = s; 1866dc5a79c1SDavid du Colombier } 1867dc5a79c1SDavid du Colombier 1868dc5a79c1SDavid du Colombier Server* 1869dc5a79c1SDavid du Colombier copyserverlist(Server *s) 1870dc5a79c1SDavid du Colombier { 1871dc5a79c1SDavid du Colombier Server *ns; 1872dc5a79c1SDavid du Colombier 1873dc5a79c1SDavid du Colombier for(ns = nil; s != nil; s = s->next) 1874dc5a79c1SDavid du Colombier addserver(&ns, s->name); 1875dc5a79c1SDavid du Colombier return ns; 1876dc5a79c1SDavid du Colombier } 1877b751ae26SDavid du Colombier 1878b751ae26SDavid du Colombier 1879b751ae26SDavid du Colombier /* from here down is copied to ip/snoopy/dns.c periodically to update it */ 1880b751ae26SDavid du Colombier 1881b751ae26SDavid du Colombier /* 1882b751ae26SDavid du Colombier * convert an integer RR type to it's ascii name 1883b751ae26SDavid du Colombier */ 1884b751ae26SDavid du Colombier char* 1885b751ae26SDavid du Colombier rrname(int type, char *buf, int len) 1886b751ae26SDavid du Colombier { 1887b751ae26SDavid du Colombier char *t; 1888b751ae26SDavid du Colombier 1889b751ae26SDavid du Colombier t = nil; 1890b751ae26SDavid du Colombier if(type >= 0 && type <= Tall) 1891b751ae26SDavid du Colombier t = rrtname[type]; 1892b751ae26SDavid du Colombier if(t==nil){ 1893b751ae26SDavid du Colombier snprint(buf, len, "%d", type); 1894b751ae26SDavid du Colombier t = buf; 1895b751ae26SDavid du Colombier } 1896b751ae26SDavid du Colombier return t; 1897b751ae26SDavid du Colombier } 1898b751ae26SDavid du Colombier 1899b751ae26SDavid du Colombier /* 1900b751ae26SDavid du Colombier * free a list of resource records and any related structs 1901b751ae26SDavid du Colombier */ 1902b751ae26SDavid du Colombier void 1903b751ae26SDavid du Colombier rrfreelist(RR *rp) 1904b751ae26SDavid du Colombier { 1905b751ae26SDavid du Colombier RR *next; 1906b751ae26SDavid du Colombier 1907b751ae26SDavid du Colombier for(; rp; rp = next){ 1908b751ae26SDavid du Colombier next = rp->next; 1909b751ae26SDavid du Colombier rrfree(rp); 1910b751ae26SDavid du Colombier } 1911b751ae26SDavid du Colombier } 1912b751ae26SDavid du Colombier 1913b751ae26SDavid du Colombier void 1914b751ae26SDavid du Colombier freeserverlist(Server *s) 1915b751ae26SDavid du Colombier { 1916b751ae26SDavid du Colombier Server *next; 1917b751ae26SDavid du Colombier 1918b751ae26SDavid du Colombier for(; s != nil; s = next){ 1919b751ae26SDavid du Colombier next = s->next; 1920b751ae26SDavid du Colombier free(s); 1921b751ae26SDavid du Colombier } 1922b751ae26SDavid du Colombier } 1923b751ae26SDavid du Colombier 1924b751ae26SDavid du Colombier /* 1925b751ae26SDavid du Colombier * allocate a resource record of a given type 1926b751ae26SDavid du Colombier */ 1927b751ae26SDavid du Colombier RR* 1928b751ae26SDavid du Colombier rralloc(int type) 1929b751ae26SDavid du Colombier { 1930b751ae26SDavid du Colombier RR *rp; 1931b751ae26SDavid du Colombier 1932b751ae26SDavid du Colombier rp = emalloc(sizeof(*rp)); 1933b751ae26SDavid du Colombier rp->magic = RRmagic; 1934b751ae26SDavid du Colombier rp->pc = getcallerpc(&type); 1935b751ae26SDavid du Colombier rp->type = type; 1936fd87a217SDavid du Colombier if (rp->type != type) 1937fd87a217SDavid du Colombier dnslog("rralloc: bogus type %d", type); 1938b751ae26SDavid du Colombier setmalloctag(rp, rp->pc); 1939b751ae26SDavid du Colombier switch(type){ 1940b751ae26SDavid du Colombier case Tsoa: 1941b751ae26SDavid du Colombier rp->soa = emalloc(sizeof(*rp->soa)); 1942b751ae26SDavid du Colombier rp->soa->slaves = nil; 1943b751ae26SDavid du Colombier setmalloctag(rp->soa, rp->pc); 1944b751ae26SDavid du Colombier break; 1945b751ae26SDavid du Colombier case Tsrv: 1946b751ae26SDavid du Colombier rp->srv = emalloc(sizeof(*rp->srv)); 1947b751ae26SDavid du Colombier setmalloctag(rp->srv, rp->pc); 1948b751ae26SDavid du Colombier break; 1949b751ae26SDavid du Colombier case Tkey: 1950b751ae26SDavid du Colombier rp->key = emalloc(sizeof(*rp->key)); 1951b751ae26SDavid du Colombier setmalloctag(rp->key, rp->pc); 1952b751ae26SDavid du Colombier break; 1953b751ae26SDavid du Colombier case Tcert: 1954b751ae26SDavid du Colombier rp->cert = emalloc(sizeof(*rp->cert)); 1955b751ae26SDavid du Colombier setmalloctag(rp->cert, rp->pc); 1956b751ae26SDavid du Colombier break; 1957b751ae26SDavid du Colombier case Tsig: 1958b751ae26SDavid du Colombier rp->sig = emalloc(sizeof(*rp->sig)); 1959b751ae26SDavid du Colombier setmalloctag(rp->sig, rp->pc); 1960b751ae26SDavid du Colombier break; 1961b751ae26SDavid du Colombier case Tnull: 1962b751ae26SDavid du Colombier rp->null = emalloc(sizeof(*rp->null)); 1963b751ae26SDavid du Colombier setmalloctag(rp->null, rp->pc); 1964b751ae26SDavid du Colombier break; 1965b751ae26SDavid du Colombier } 1966b751ae26SDavid du Colombier rp->ttl = 0; 1967b751ae26SDavid du Colombier rp->expire = 0; 1968b751ae26SDavid du Colombier rp->next = 0; 1969b751ae26SDavid du Colombier return rp; 1970b751ae26SDavid du Colombier } 1971b751ae26SDavid du Colombier 1972b751ae26SDavid du Colombier /* 1973b751ae26SDavid du Colombier * free a resource record and any related structs 1974b751ae26SDavid du Colombier */ 1975b751ae26SDavid du Colombier void 1976b751ae26SDavid du Colombier rrfree(RR *rp) 1977b751ae26SDavid du Colombier { 1978b751ae26SDavid du Colombier DN *dp; 1979b751ae26SDavid du Colombier RR *nrp; 1980b751ae26SDavid du Colombier Txt *t; 1981b751ae26SDavid du Colombier 1982530fef66SDavid du Colombier assert(rp->magic == RRmagic); 1983b751ae26SDavid du Colombier assert(!rp->cached); 1984b751ae26SDavid du Colombier 1985b751ae26SDavid du Colombier dp = rp->owner; 1986b751ae26SDavid du Colombier if(dp){ 1987b751ae26SDavid du Colombier assert(dp->magic == DNmagic); 1988b751ae26SDavid du Colombier for(nrp = dp->rr; nrp; nrp = nrp->next) 1989b751ae26SDavid du Colombier assert(nrp != rp); /* "rrfree of live rr" */ 1990b751ae26SDavid du Colombier } 1991b751ae26SDavid du Colombier 1992b751ae26SDavid du Colombier switch(rp->type){ 1993b751ae26SDavid du Colombier case Tsoa: 1994b751ae26SDavid du Colombier freeserverlist(rp->soa->slaves); 1995b751ae26SDavid du Colombier memset(rp->soa, 0, sizeof *rp->soa); /* cause trouble */ 1996b751ae26SDavid du Colombier free(rp->soa); 1997b751ae26SDavid du Colombier break; 1998b751ae26SDavid du Colombier case Tsrv: 1999b751ae26SDavid du Colombier memset(rp->srv, 0, sizeof *rp->srv); /* cause trouble */ 2000b751ae26SDavid du Colombier free(rp->srv); 2001b751ae26SDavid du Colombier break; 2002b751ae26SDavid du Colombier case Tkey: 2003b751ae26SDavid du Colombier free(rp->key->data); 2004b751ae26SDavid du Colombier memset(rp->key, 0, sizeof *rp->key); /* cause trouble */ 2005b751ae26SDavid du Colombier free(rp->key); 2006b751ae26SDavid du Colombier break; 2007b751ae26SDavid du Colombier case Tcert: 2008b751ae26SDavid du Colombier free(rp->cert->data); 2009b751ae26SDavid du Colombier memset(rp->cert, 0, sizeof *rp->cert); /* cause trouble */ 2010b751ae26SDavid du Colombier free(rp->cert); 2011b751ae26SDavid du Colombier break; 2012b751ae26SDavid du Colombier case Tsig: 2013b751ae26SDavid du Colombier free(rp->sig->data); 2014b751ae26SDavid du Colombier memset(rp->sig, 0, sizeof *rp->sig); /* cause trouble */ 2015b751ae26SDavid du Colombier free(rp->sig); 2016b751ae26SDavid du Colombier break; 2017b751ae26SDavid du Colombier case Tnull: 2018b751ae26SDavid du Colombier free(rp->null->data); 2019b751ae26SDavid du Colombier memset(rp->null, 0, sizeof *rp->null); /* cause trouble */ 2020b751ae26SDavid du Colombier free(rp->null); 2021b751ae26SDavid du Colombier break; 2022b751ae26SDavid du Colombier case Ttxt: 2023b751ae26SDavid du Colombier while(rp->txt != nil){ 2024b751ae26SDavid du Colombier t = rp->txt; 2025b751ae26SDavid du Colombier rp->txt = t->next; 2026b751ae26SDavid du Colombier free(t->p); 2027b751ae26SDavid du Colombier memset(t, 0, sizeof *t); /* cause trouble */ 2028b751ae26SDavid du Colombier free(t); 2029b751ae26SDavid du Colombier } 2030b751ae26SDavid du Colombier break; 2031b751ae26SDavid du Colombier } 2032b751ae26SDavid du Colombier 2033b751ae26SDavid du Colombier rp->magic = ~rp->magic; 2034b751ae26SDavid du Colombier memset(rp, 0, sizeof *rp); /* cause trouble */ 2035b751ae26SDavid du Colombier free(rp); 2036b751ae26SDavid du Colombier } 2037