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 { 17*1a8a6b0dSDavid du Colombier Deftarget = 1<<30, /* effectively disable aging */ 18*1a8a6b0dSDavid du Colombier Minage = 1<<30, 19*1a8a6b0dSDavid du Colombier Defagefreq = 1<<30, /* age names this often (seconds) */ 20*1a8a6b0dSDavid du Colombier 21*1a8a6b0dSDavid du Colombier /* these settings will trigger frequent aging */ 22*1a8a6b0dSDavid du Colombier // Deftarget = 4000, 23*1a8a6b0dSDavid du Colombier // Minage = 5*60, 24*1a8a6b0dSDavid du Colombier // Defagefreq = 15*60, /* age names this often (seconds) */ 2581730632SDavid du Colombier }; 2681730632SDavid du Colombier 273e12c5d1SDavid du Colombier /* 283e12c5d1SDavid du Colombier * Hash table for domain names. The hash is based only on the 293e12c5d1SDavid du Colombier * first element of the domain name. 303e12c5d1SDavid du Colombier */ 317dd7cddfSDavid du Colombier DN *ht[HTLEN]; 323e12c5d1SDavid du Colombier 334f8f669cSDavid du Colombier static struct { 347dd7cddfSDavid du Colombier Lock; 357dd7cddfSDavid du Colombier ulong names; /* names allocated */ 367dd7cddfSDavid du Colombier ulong oldest; /* longest we'll leave a name around */ 377dd7cddfSDavid du Colombier int active; 387dd7cddfSDavid du Colombier int mutex; 394f8f669cSDavid du Colombier ushort id; /* same size as in packet */ 407dd7cddfSDavid du Colombier } dnvars; 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier /* names of RR types */ 433e12c5d1SDavid du Colombier char *rrtname[] = 443e12c5d1SDavid du Colombier { 453e12c5d1SDavid du Colombier [Ta] "ip", 463e12c5d1SDavid du Colombier [Tns] "ns", 473e12c5d1SDavid du Colombier [Tmd] "md", 483e12c5d1SDavid du Colombier [Tmf] "mf", 493e12c5d1SDavid du Colombier [Tcname] "cname", 503e12c5d1SDavid du Colombier [Tsoa] "soa", 513e12c5d1SDavid du Colombier [Tmb] "mb", 523e12c5d1SDavid du Colombier [Tmg] "mg", 533e12c5d1SDavid du Colombier [Tmr] "mr", 543e12c5d1SDavid du Colombier [Tnull] "null", 553e12c5d1SDavid du Colombier [Twks] "wks", 563e12c5d1SDavid du Colombier [Tptr] "ptr", 573e12c5d1SDavid du Colombier [Thinfo] "hinfo", 583e12c5d1SDavid du Colombier [Tminfo] "minfo", 593e12c5d1SDavid du Colombier [Tmx] "mx", 603e12c5d1SDavid du Colombier [Ttxt] "txt", 617dd7cddfSDavid du Colombier [Trp] "rp", 62ab3dc52fSDavid du Colombier [Tafsdb] "afsdb", 63ab3dc52fSDavid du Colombier [Tx25] "x.25", 64ab3dc52fSDavid du Colombier [Tisdn] "isdn", 65ab3dc52fSDavid du Colombier [Trt] "rt", 66ab3dc52fSDavid du Colombier [Tnsap] "nsap", 67ab3dc52fSDavid du Colombier [Tnsapptr] "nsap-ptr", 687dd7cddfSDavid du Colombier [Tsig] "sig", 69ab3dc52fSDavid du Colombier [Tkey] "key", 70ab3dc52fSDavid du Colombier [Tpx] "px", 71ab3dc52fSDavid du Colombier [Tgpos] "gpos", 725d459b5aSDavid du Colombier [Taaaa] "ipv6", 73ab3dc52fSDavid du Colombier [Tloc] "loc", 74ab3dc52fSDavid du Colombier [Tnxt] "nxt", 75ab3dc52fSDavid du Colombier [Teid] "eid", 76ab3dc52fSDavid du Colombier [Tnimloc] "nimrod", 77ab3dc52fSDavid du Colombier [Tsrv] "srv", 78ab3dc52fSDavid du Colombier [Tatma] "atma", 79ab3dc52fSDavid du Colombier [Tnaptr] "naptr", 80ab3dc52fSDavid du Colombier [Tkx] "kx", 81ab3dc52fSDavid du Colombier [Tcert] "cert", 82ab3dc52fSDavid du Colombier [Ta6] "a6", 83ab3dc52fSDavid du Colombier [Tdname] "dname", 84ab3dc52fSDavid du Colombier [Tsink] "sink", 85ab3dc52fSDavid du Colombier [Topt] "opt", 86ab3dc52fSDavid du Colombier [Tapl] "apl", 87ab3dc52fSDavid du Colombier [Tds] "ds", 88ab3dc52fSDavid du Colombier [Tsshfp] "sshfp", 89ab3dc52fSDavid du Colombier [Tipseckey] "ipseckey", 90ab3dc52fSDavid du Colombier [Trrsig] "rrsig", 91ab3dc52fSDavid du Colombier [Tnsec] "nsec", 92ab3dc52fSDavid du Colombier [Tdnskey] "dnskey", 93ab3dc52fSDavid du Colombier [Tspf] "spf", 94ab3dc52fSDavid du Colombier [Tuinfo] "uinfo", 95ab3dc52fSDavid du Colombier [Tuid] "uid", 96ab3dc52fSDavid du Colombier [Tgid] "gid", 97ab3dc52fSDavid du Colombier [Tunspec] "unspec", 98ab3dc52fSDavid du Colombier [Ttkey] "tkey", 99ab3dc52fSDavid du Colombier [Ttsig] "tsig", 1007dd7cddfSDavid du Colombier [Tixfr] "ixfr", 1017dd7cddfSDavid du Colombier [Taxfr] "axfr", 102ab3dc52fSDavid du Colombier [Tmailb] "mailb", 103ab3dc52fSDavid du Colombier [Tmaila] "maila", 104219b2ee8SDavid du Colombier [Tall] "all", 1053e12c5d1SDavid du Colombier 0, 1063e12c5d1SDavid du Colombier }; 1073e12c5d1SDavid du Colombier 1083e12c5d1SDavid du Colombier /* names of response codes */ 109271b8d73SDavid du Colombier char *rname[Rmask+1] = 1103e12c5d1SDavid du Colombier { 1113e12c5d1SDavid du Colombier [Rok] "ok", 1123e12c5d1SDavid du Colombier [Rformat] "format error", 1133e12c5d1SDavid du Colombier [Rserver] "server failure", 1143e12c5d1SDavid du Colombier [Rname] "bad name", 1153e12c5d1SDavid du Colombier [Runimplimented] "unimplemented", 1163e12c5d1SDavid du Colombier [Rrefused] "we don't like you", 117ab3dc52fSDavid du Colombier [Ryxdomain] "name should not exist", 118ab3dc52fSDavid du Colombier [Ryxrrset] "rr set should not exist", 119ab3dc52fSDavid du Colombier [Rnxrrset] "rr set should exist", 120ab3dc52fSDavid du Colombier [Rnotauth] "not authorative", 121ab3dc52fSDavid du Colombier [Rnotzone] "not in zone", 122ab3dc52fSDavid du Colombier [Rbadvers] "bad opt version", 123ab3dc52fSDavid du Colombier /* [Rbadsig] "bad signature", */ 124ab3dc52fSDavid du Colombier [Rbadkey] "bad key", 125ab3dc52fSDavid du Colombier [Rbadtime] "bad signature time", 126ab3dc52fSDavid du Colombier [Rbadmode] "bad mode", 127ab3dc52fSDavid du Colombier [Rbadname] "duplicate key name", 128ab3dc52fSDavid du Colombier [Rbadalg] "bad algorithm", 1293e12c5d1SDavid du Colombier }; 1304f8f669cSDavid du Colombier unsigned nrname = nelem(rname); 1313e12c5d1SDavid du Colombier 1323e12c5d1SDavid du Colombier /* names of op codes */ 1333e12c5d1SDavid du Colombier char *opname[] = 1343e12c5d1SDavid du Colombier { 1353e12c5d1SDavid du Colombier [Oquery] "query", 136ab3dc52fSDavid du Colombier [Oinverse] "inverse query (retired)", 1373e12c5d1SDavid du Colombier [Ostatus] "status", 138ab3dc52fSDavid du Colombier [Oupdate] "update", 1393e12c5d1SDavid du Colombier }; 1403e12c5d1SDavid du Colombier 14121abd8f2SDavid du Colombier ulong target = Deftarget; 142bd389b36SDavid du Colombier Lock dnlock; 1433e12c5d1SDavid du Colombier 144f46c709fSDavid du Colombier static ulong agefreq = Defagefreq; 145f46c709fSDavid du Colombier 146225077b0SDavid du Colombier static int rrequiv(RR *r1, RR *r2); 1479a747e4fSDavid du Colombier static int sencodefmt(Fmt*); 14859cc4ca5SDavid du Colombier 149254fe3d3SDavid du Colombier static void 150254fe3d3SDavid du Colombier ding(void*, char *msg) 151254fe3d3SDavid du Colombier { 152254fe3d3SDavid du Colombier if(strstr(msg, "alarm") != nil) { 153254fe3d3SDavid du Colombier stats.alarms++; 154254fe3d3SDavid du Colombier noted(NCONT); /* resume with system call error */ 155254fe3d3SDavid du Colombier } else 156254fe3d3SDavid du Colombier noted(NDFLT); /* die */ 157254fe3d3SDavid du Colombier } 158254fe3d3SDavid du Colombier 1593e12c5d1SDavid du Colombier void 1603e12c5d1SDavid du Colombier dninit(void) 1613e12c5d1SDavid du Colombier { 1629a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 1639a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 1649a747e4fSDavid du Colombier fmtinstall('V', eipfmt); 1659a747e4fSDavid du Colombier fmtinstall('R', rrfmt); 1669a747e4fSDavid du Colombier fmtinstall('Q', rravfmt); 1679a747e4fSDavid du Colombier fmtinstall('H', sencodefmt); 1687dd7cddfSDavid du Colombier 1697dd7cddfSDavid du Colombier dnvars.oldest = maxage; 1707dd7cddfSDavid du Colombier dnvars.names = 0; 1714f8f669cSDavid du Colombier dnvars.id = truerand(); /* don't start with same id every time */ 172254fe3d3SDavid du Colombier 173254fe3d3SDavid du Colombier notify(ding); 1743e12c5d1SDavid du Colombier } 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier /* 1773e12c5d1SDavid du Colombier * hash for a domain name 1783e12c5d1SDavid du Colombier */ 1793e12c5d1SDavid du Colombier static ulong 1803e12c5d1SDavid du Colombier dnhash(char *name) 1813e12c5d1SDavid du Colombier { 1823e12c5d1SDavid du Colombier ulong hash; 1833e12c5d1SDavid du Colombier uchar *val = (uchar*)name; 1843e12c5d1SDavid du Colombier 1857dd7cddfSDavid du Colombier for(hash = 0; *val; val++) 1864f8f669cSDavid du Colombier hash = hash*13 + tolower(*val)-'a'; 1873e12c5d1SDavid du Colombier return hash % HTLEN; 1883e12c5d1SDavid du Colombier } 1893e12c5d1SDavid du Colombier 1903e12c5d1SDavid du Colombier /* 1913e12c5d1SDavid du Colombier * lookup a symbol. if enter is not zero and the name is 1923e12c5d1SDavid du Colombier * not found, create it. 1933e12c5d1SDavid du Colombier */ 1943e12c5d1SDavid du Colombier DN* 1953e12c5d1SDavid du Colombier dnlookup(char *name, int class, int enter) 1963e12c5d1SDavid du Colombier { 1973e12c5d1SDavid du Colombier DN **l; 1983e12c5d1SDavid du Colombier DN *dp; 1993e12c5d1SDavid du Colombier 2003ff48bf5SDavid du Colombier l = &ht[dnhash(name)]; 201bd389b36SDavid du Colombier lock(&dnlock); 2023e12c5d1SDavid du Colombier for(dp = *l; dp; dp = dp->next) { 2037dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 2043ff48bf5SDavid du Colombier if(dp->class == class && cistrcmp(dp->name, name) == 0){ 2057dd7cddfSDavid du Colombier dp->referenced = now; 206bd389b36SDavid du Colombier unlock(&dnlock); 2073e12c5d1SDavid du Colombier return dp; 2083e12c5d1SDavid du Colombier } 2093e12c5d1SDavid du Colombier l = &dp->next; 2103e12c5d1SDavid du Colombier } 2114f8f669cSDavid du Colombier 2124f8f669cSDavid du Colombier if(!enter){ 213bd389b36SDavid du Colombier unlock(&dnlock); 2143e12c5d1SDavid du Colombier return 0; 2153e12c5d1SDavid du Colombier } 2167dd7cddfSDavid du Colombier dnvars.names++; 2179a747e4fSDavid du Colombier dp = emalloc(sizeof(*dp)); 2187dd7cddfSDavid du Colombier dp->magic = DNmagic; 2199a747e4fSDavid du Colombier dp->name = estrdup(name); 2204f8f669cSDavid du Colombier assert(dp->name != nil); 2213e12c5d1SDavid du Colombier dp->class = class; 2223e12c5d1SDavid du Colombier dp->rr = 0; 2237dd7cddfSDavid du Colombier dp->referenced = now; 224530fef66SDavid du Colombier /* add new DN to tail of the hash list. *l points to last next ptr. */ 225530fef66SDavid du Colombier dp->next = nil; 2263e12c5d1SDavid du Colombier *l = dp; 227bd389b36SDavid du Colombier unlock(&dnlock); 2287dd7cddfSDavid du Colombier 2293e12c5d1SDavid du Colombier return dp; 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier 232225077b0SDavid du Colombier static int 233225077b0SDavid du Colombier rrsame(RR *rr1, RR *rr2) 234225077b0SDavid du Colombier { 235225077b0SDavid du Colombier return rr1 == rr2 || rr2 && rrequiv(rr1, rr2) && 236225077b0SDavid du Colombier rr1->db == rr2->db && rr1->auth == rr2->auth; 237225077b0SDavid du Colombier } 238225077b0SDavid du Colombier 239225077b0SDavid du Colombier static int 240225077b0SDavid du Colombier rronlist(RR *rp, RR *lp) 241225077b0SDavid du Colombier { 242225077b0SDavid du Colombier for(; lp; lp = lp->next) 2434f927735SDavid du Colombier if (rrsame(lp, rp)) 244225077b0SDavid du Colombier return 1; 245225077b0SDavid du Colombier return 0; 246225077b0SDavid du Colombier } 247225077b0SDavid du Colombier 2483e12c5d1SDavid du Colombier /* 2494f927735SDavid du Colombier * dump the stats 250219b2ee8SDavid du Colombier */ 251219b2ee8SDavid du Colombier void 2524f927735SDavid du Colombier dnstats(char *file) 253219b2ee8SDavid du Colombier { 254219b2ee8SDavid du Colombier int i, fd; 255219b2ee8SDavid du Colombier 25621abd8f2SDavid du Colombier fd = create(file, OWRITE, 0666); 257219b2ee8SDavid du Colombier if(fd < 0) 258219b2ee8SDavid du Colombier return; 259a41547ffSDavid du Colombier 260a41547ffSDavid du Colombier qlock(&stats); 2614f927735SDavid du Colombier fprint(fd, "# system %s\n", sysname()); 262f46c709fSDavid du Colombier fprint(fd, "# slave procs high-water mark\t%lud\n", stats.slavehiwat); 263f46c709fSDavid du Colombier fprint(fd, "# queries received by 9p\t%lud\n", stats.qrecvd9p); 264f46c709fSDavid du Colombier fprint(fd, "# queries received by udp\t%lud\n", stats.qrecvdudp); 265f46c709fSDavid du Colombier fprint(fd, "# queries answered from memory\t%lud\n", stats.answinmem); 266f46c709fSDavid du Colombier fprint(fd, "# queries sent by udp\t%lud\n", stats.qsent); 267a41547ffSDavid du Colombier for (i = 0; i < nelem(stats.under10ths); i++) 268a41547ffSDavid du Colombier if (stats.under10ths[i] || i == nelem(stats.under10ths) - 1) 269f46c709fSDavid du Colombier fprint(fd, "# responses arriving within %.1f s.\t%lud\n", 270a41547ffSDavid du Colombier (double)(i+1)/10, stats.under10ths[i]); 271f46c709fSDavid du Colombier fprint(fd, "\n# queries sent & timed-out\t%lud\n", stats.tmout); 272f46c709fSDavid du Colombier fprint(fd, "# cname queries timed-out\t%lud\n", stats.tmoutcname); 273f46c709fSDavid du Colombier fprint(fd, "# ipv6 queries timed-out\t%lud\n", stats.tmoutv6); 274f46c709fSDavid du Colombier fprint(fd, "\n# negative answers received\t%lud\n", stats.negans); 2750319257bSDavid du Colombier fprint(fd, "# negative answers w Rserver set\t%lud\n", stats.negserver); 2760319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation\t%lud\n", 2770319257bSDavid du Colombier stats.negbaddeleg); 2780319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation & no answers\t%lud\n", 2790319257bSDavid du Colombier stats.negbdnoans); 2800319257bSDavid du Colombier fprint(fd, "# negative answers w no Rname set\t%lud\n", stats.negnorname); 281f46c709fSDavid du Colombier fprint(fd, "# negative answers cached\t%lud\n", stats.negcached); 282a41547ffSDavid du Colombier qunlock(&stats); 283a41547ffSDavid du Colombier 284219b2ee8SDavid du Colombier lock(&dnlock); 2856d8e4566SDavid du Colombier fprint(fd, "\n# domain names %lud target %lud\n", dnvars.names, target); 2864f927735SDavid du Colombier unlock(&dnlock); 2874f927735SDavid du Colombier close(fd); 2884f927735SDavid du Colombier } 2894f927735SDavid du Colombier 2904f927735SDavid du Colombier /* 2914f927735SDavid du Colombier * dump the cache 2924f927735SDavid du Colombier */ 2934f927735SDavid du Colombier void 2944f927735SDavid du Colombier dndump(char *file) 2954f927735SDavid du Colombier { 2964f927735SDavid du Colombier int i, fd; 2974f927735SDavid du Colombier DN *dp; 2984f927735SDavid du Colombier RR *rp; 2994f927735SDavid du Colombier 3004f927735SDavid du Colombier fd = create(file, OWRITE, 0666); 3014f927735SDavid du Colombier if(fd < 0) 3024f927735SDavid du Colombier return; 3034f927735SDavid du Colombier 3044f927735SDavid du Colombier lock(&dnlock); 3054f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++) 306219b2ee8SDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 307219b2ee8SDavid du Colombier fprint(fd, "%s\n", dp->name); 308225077b0SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) { 3096d8e4566SDavid du Colombier fprint(fd, "\t%R %c%c %lud/%lud\n", 3104f8f669cSDavid du Colombier rp, rp->auth? 'A': 'U', 3117dd7cddfSDavid du Colombier rp->db? 'D': 'N', rp->expire, rp->ttl); 312225077b0SDavid du Colombier if (rronlist(rp, rp->next)) 313225077b0SDavid du Colombier fprint(fd, "*** duplicate:\n"); 314225077b0SDavid du Colombier } 315219b2ee8SDavid du Colombier } 316219b2ee8SDavid du Colombier unlock(&dnlock); 317219b2ee8SDavid du Colombier close(fd); 318219b2ee8SDavid du Colombier } 319219b2ee8SDavid du Colombier 320219b2ee8SDavid du Colombier /* 3217dd7cddfSDavid du Colombier * purge all records 3227dd7cddfSDavid du Colombier */ 3237dd7cddfSDavid du Colombier void 3247dd7cddfSDavid du Colombier dnpurge(void) 3257dd7cddfSDavid du Colombier { 3267dd7cddfSDavid du Colombier DN *dp; 327a4285193SDavid du Colombier RR *rp, *srp; 3287dd7cddfSDavid du Colombier int i; 3297dd7cddfSDavid du Colombier 3307dd7cddfSDavid du Colombier lock(&dnlock); 3317dd7cddfSDavid du Colombier 3327dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 3337dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 334a4285193SDavid du Colombier srp = rp = dp->rr; 3357dd7cddfSDavid du Colombier dp->rr = nil; 3367dd7cddfSDavid du Colombier for(; rp != nil; rp = rp->next) 3377dd7cddfSDavid du Colombier rp->cached = 0; 338a4285193SDavid du Colombier rrfreelist(srp); 3397dd7cddfSDavid du Colombier } 3407dd7cddfSDavid du Colombier 3417dd7cddfSDavid du Colombier unlock(&dnlock); 3427dd7cddfSDavid du Colombier } 3437dd7cddfSDavid du Colombier 344d2fd7a44SDavid du Colombier /* 345d2fd7a44SDavid du Colombier * delete rp from *l, free rp. 346d2fd7a44SDavid du Colombier * call with dnlock held. 347d2fd7a44SDavid du Colombier */ 348225077b0SDavid du Colombier static void 349225077b0SDavid du Colombier rrdelete(RR **l, RR *rp) 350225077b0SDavid du Colombier { 351225077b0SDavid du Colombier *l = rp->next; 352225077b0SDavid du Colombier rp->cached = 0; /* avoid blowing an assertion in rrfree */ 353225077b0SDavid du Colombier rrfree(rp); 354225077b0SDavid du Colombier } 355225077b0SDavid du Colombier 3567dd7cddfSDavid du Colombier /* 357d2fd7a44SDavid du Colombier * check the age of resource records, free any that have timed out. 358d2fd7a44SDavid du Colombier * call with dnlock held. 3593e12c5d1SDavid du Colombier */ 3603e12c5d1SDavid du Colombier void 3613e12c5d1SDavid du Colombier dnage(DN *dp) 3623e12c5d1SDavid du Colombier { 3633e12c5d1SDavid du Colombier RR **l; 3643e12c5d1SDavid du Colombier RR *rp, *next; 3657dd7cddfSDavid du Colombier ulong diff; 3663e12c5d1SDavid du Colombier 3677dd7cddfSDavid du Colombier diff = now - dp->referenced; 3686dc4800dSDavid du Colombier if(diff < Reserved || dp->keep) 3697dd7cddfSDavid du Colombier return; 3707dd7cddfSDavid du Colombier 3713e12c5d1SDavid du Colombier l = &dp->rr; 3723e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = next){ 3737dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 3743e12c5d1SDavid du Colombier next = rp->next; 375225077b0SDavid du Colombier if(!rp->db && (rp->expire < now || diff > dnvars.oldest)) 376225077b0SDavid du Colombier rrdelete(l, rp); 377225077b0SDavid du Colombier else 3783e12c5d1SDavid du Colombier l = &rp->next; 3793e12c5d1SDavid du Colombier } 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier 3826dc4800dSDavid du Colombier #define MARK(dp) { if (dp) (dp)->keep = 1; } 383a41547ffSDavid du Colombier 384410ea80bSDavid du Colombier /* mark a domain name and those in its RRs as never to be aged */ 385a41547ffSDavid du Colombier void 386410ea80bSDavid du Colombier dnagenever(DN *dp, int dolock) 387a41547ffSDavid du Colombier { 388a41547ffSDavid du Colombier RR *rp; 389a41547ffSDavid du Colombier 390410ea80bSDavid du Colombier if (dolock) 391a41547ffSDavid du Colombier lock(&dnlock); 392a41547ffSDavid du Colombier 393410ea80bSDavid du Colombier /* mark all referenced domain names */ 394410ea80bSDavid du Colombier MARK(dp); 395a41547ffSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 396a41547ffSDavid du Colombier MARK(rp->owner); 397410ea80bSDavid du Colombier if(rp->negative){ 398410ea80bSDavid du Colombier MARK(rp->negsoaowner); 399410ea80bSDavid du Colombier continue; 400410ea80bSDavid du Colombier } 401a41547ffSDavid du Colombier switch(rp->type){ 402410ea80bSDavid du Colombier case Thinfo: 403410ea80bSDavid du Colombier MARK(rp->cpu); 404410ea80bSDavid du Colombier MARK(rp->os); 405410ea80bSDavid du Colombier break; 406410ea80bSDavid du Colombier case Ttxt: 407410ea80bSDavid du Colombier break; 408410ea80bSDavid du Colombier case Tcname: 409410ea80bSDavid du Colombier case Tmb: 410410ea80bSDavid du Colombier case Tmd: 411410ea80bSDavid du Colombier case Tmf: 412a41547ffSDavid du Colombier case Tns: 413410ea80bSDavid du Colombier case Tmx: 414410ea80bSDavid du Colombier case Tsrv: 415a41547ffSDavid du Colombier MARK(rp->host); 416a41547ffSDavid du Colombier break; 417410ea80bSDavid du Colombier case Tmg: 418410ea80bSDavid du Colombier case Tmr: 419410ea80bSDavid du Colombier MARK(rp->mb); 420410ea80bSDavid du Colombier break; 421410ea80bSDavid du Colombier case Tminfo: 422410ea80bSDavid du Colombier MARK(rp->rmb); 423410ea80bSDavid du Colombier MARK(rp->mb); 424410ea80bSDavid du Colombier break; 425410ea80bSDavid du Colombier case Trp: 426410ea80bSDavid du Colombier MARK(rp->rmb); 427410ea80bSDavid du Colombier MARK(rp->rp); 428410ea80bSDavid du Colombier break; 429410ea80bSDavid du Colombier case Ta: 430410ea80bSDavid du Colombier case Taaaa: 431410ea80bSDavid du Colombier MARK(rp->ip); 432410ea80bSDavid du Colombier break; 433410ea80bSDavid du Colombier case Tptr: 434410ea80bSDavid du Colombier MARK(rp->ptr); 435410ea80bSDavid du Colombier break; 436410ea80bSDavid du Colombier case Tsoa: 437410ea80bSDavid du Colombier MARK(rp->host); 438410ea80bSDavid du Colombier MARK(rp->rmb); 439410ea80bSDavid du Colombier break; 440a41547ffSDavid du Colombier } 441a41547ffSDavid du Colombier } 442410ea80bSDavid du Colombier 443410ea80bSDavid du Colombier if (dolock) 444410ea80bSDavid du Colombier unlock(&dnlock); 4456dc4800dSDavid du Colombier } 446a41547ffSDavid du Colombier 447410ea80bSDavid du Colombier /* mark all current domain names as never to be aged */ 448410ea80bSDavid du Colombier void 449410ea80bSDavid du Colombier dnageallnever(void) 450410ea80bSDavid du Colombier { 451410ea80bSDavid du Colombier int i; 452410ea80bSDavid du Colombier DN *dp; 453410ea80bSDavid du Colombier 454410ea80bSDavid du Colombier lock(&dnlock); 455410ea80bSDavid du Colombier 456410ea80bSDavid du Colombier /* mark all referenced domain names */ 457410ea80bSDavid du Colombier for(i = 0; i < HTLEN; i++) 458410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 459410ea80bSDavid du Colombier dnagenever(dp, 0); 460410ea80bSDavid du Colombier 461a41547ffSDavid du Colombier unlock(&dnlock); 462a41547ffSDavid du Colombier 463a41547ffSDavid du Colombier dnslog("%ld initial domain names; target is %ld", dnvars.names, target); 464a41547ffSDavid du Colombier if(dnvars.names >= target) 465a41547ffSDavid du Colombier dnslog("more initial domain names (%ld) than target (%ld)", 466a41547ffSDavid du Colombier dnvars.names, target); 467a41547ffSDavid du Colombier } 468a41547ffSDavid du Colombier 4696dc4800dSDavid du Colombier #define REF(dp) { if (dp) (dp)->refs++; } 4706dc4800dSDavid du Colombier 4717dd7cddfSDavid du Colombier /* 4727dd7cddfSDavid du Colombier * periodicly sweep for old records and remove unreferenced domain names 4737dd7cddfSDavid du Colombier * 4747dd7cddfSDavid du Colombier * only called when all other threads are locked out 4757dd7cddfSDavid du Colombier */ 4767dd7cddfSDavid du Colombier void 4777dd7cddfSDavid du Colombier dnageall(int doit) 4787dd7cddfSDavid du Colombier { 4797dd7cddfSDavid du Colombier DN *dp, **l; 480225077b0SDavid du Colombier int i; 4817dd7cddfSDavid du Colombier RR *rp; 4827dd7cddfSDavid du Colombier static ulong nextage; 4837dd7cddfSDavid du Colombier 4844f8f669cSDavid du Colombier if(dnvars.names < target || (now < nextage && !doit)){ 4857dd7cddfSDavid du Colombier dnvars.oldest = maxage; 4867dd7cddfSDavid du Colombier return; 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier 4894f8f669cSDavid du Colombier if(dnvars.names >= target) { 4903cbadd90SDavid du Colombier dnslog("more names (%lud) than target (%lud)", dnvars.names, 4913cbadd90SDavid du Colombier target); 4927dd7cddfSDavid du Colombier dnvars.oldest /= 2; 49381730632SDavid du Colombier if (dnvars.oldest < Minage) 49481730632SDavid du Colombier dnvars.oldest = Minage; /* don't be silly */ 4954f8f669cSDavid du Colombier } 496f46c709fSDavid du Colombier if (agefreq > dnvars.oldest / 2) 497f46c709fSDavid du Colombier nextage = now + dnvars.oldest / 2; 498f46c709fSDavid du Colombier else 499f46c709fSDavid du Colombier nextage = now + agefreq; 5007dd7cddfSDavid du Colombier 5017dd7cddfSDavid du Colombier lock(&dnlock); 5027dd7cddfSDavid du Colombier 5037dd7cddfSDavid du Colombier /* time out all old entries (and set refs to 0) */ 5047dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 5057dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 5067dd7cddfSDavid du Colombier dp->refs = 0; 5077dd7cddfSDavid du Colombier dnage(dp); 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier 5107dd7cddfSDavid du Colombier /* mark all referenced domain names */ 5117dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 5127dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 5137dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 5147dd7cddfSDavid du Colombier REF(rp->owner); 5157dd7cddfSDavid du Colombier if(rp->negative){ 5167dd7cddfSDavid du Colombier REF(rp->negsoaowner); 5177dd7cddfSDavid du Colombier continue; 5187dd7cddfSDavid du Colombier } 5197dd7cddfSDavid du Colombier switch(rp->type){ 5207dd7cddfSDavid du Colombier case Thinfo: 5217dd7cddfSDavid du Colombier REF(rp->cpu); 5227dd7cddfSDavid du Colombier REF(rp->os); 5237dd7cddfSDavid du Colombier break; 5247dd7cddfSDavid du Colombier case Ttxt: 5257dd7cddfSDavid du Colombier break; 5267dd7cddfSDavid du Colombier case Tcname: 5277dd7cddfSDavid du Colombier case Tmb: 5287dd7cddfSDavid du Colombier case Tmd: 5297dd7cddfSDavid du Colombier case Tmf: 5307dd7cddfSDavid du Colombier case Tns: 5314f8f669cSDavid du Colombier case Tmx: 532225077b0SDavid du Colombier case Tsrv: 5337dd7cddfSDavid du Colombier REF(rp->host); 5347dd7cddfSDavid du Colombier break; 5357dd7cddfSDavid du Colombier case Tmg: 5367dd7cddfSDavid du Colombier case Tmr: 5377dd7cddfSDavid du Colombier REF(rp->mb); 5387dd7cddfSDavid du Colombier break; 5397dd7cddfSDavid du Colombier case Tminfo: 5407dd7cddfSDavid du Colombier REF(rp->rmb); 5417dd7cddfSDavid du Colombier REF(rp->mb); 5427dd7cddfSDavid du Colombier break; 5437dd7cddfSDavid du Colombier case Trp: 5447dd7cddfSDavid du Colombier REF(rp->rmb); 54560845620SDavid du Colombier REF(rp->rp); 5467dd7cddfSDavid du Colombier break; 5477dd7cddfSDavid du Colombier case Ta: 5485d459b5aSDavid du Colombier case Taaaa: 5497dd7cddfSDavid du Colombier REF(rp->ip); 5507dd7cddfSDavid du Colombier break; 5517dd7cddfSDavid du Colombier case Tptr: 5527dd7cddfSDavid du Colombier REF(rp->ptr); 5537dd7cddfSDavid du Colombier break; 5547dd7cddfSDavid du Colombier case Tsoa: 5557dd7cddfSDavid du Colombier REF(rp->host); 5567dd7cddfSDavid du Colombier REF(rp->rmb); 5577dd7cddfSDavid du Colombier break; 5587dd7cddfSDavid du Colombier } 5597dd7cddfSDavid du Colombier } 5607dd7cddfSDavid du Colombier 5617dd7cddfSDavid du Colombier /* sweep and remove unreferenced domain names */ 5627dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++){ 5637dd7cddfSDavid du Colombier l = &ht[i]; 5647dd7cddfSDavid du Colombier for(dp = *l; dp; dp = *l){ 565a41547ffSDavid du Colombier if(dp->rr == 0 && dp->refs == 0 && !dp->keep){ 56634f77ae3SDavid du Colombier assert(dp->magic == DNmagic); 5677dd7cddfSDavid du Colombier *l = dp->next; 5684f8f669cSDavid du Colombier 5697dd7cddfSDavid du Colombier if(dp->name) 5707dd7cddfSDavid du Colombier free(dp->name); 57134f77ae3SDavid du Colombier dp->magic = ~dp->magic; 5727dd7cddfSDavid du Colombier dnvars.names--; 5734f8f669cSDavid du Colombier memset(dp, 0, sizeof *dp); /* cause trouble */ 5747dd7cddfSDavid du Colombier free(dp); 5754f8f669cSDavid du Colombier 5767dd7cddfSDavid du Colombier continue; 5777dd7cddfSDavid du Colombier } 5787dd7cddfSDavid du Colombier l = &dp->next; 5797dd7cddfSDavid du Colombier } 5807dd7cddfSDavid du Colombier } 5817dd7cddfSDavid du Colombier 5827dd7cddfSDavid du Colombier unlock(&dnlock); 5837dd7cddfSDavid du Colombier } 5847dd7cddfSDavid du Colombier 5857dd7cddfSDavid du Colombier /* 5867dd7cddfSDavid du Colombier * timeout all database records (used when rereading db) 5877dd7cddfSDavid du Colombier */ 5887dd7cddfSDavid du Colombier void 5897dd7cddfSDavid du Colombier dnagedb(void) 5907dd7cddfSDavid du Colombier { 5917dd7cddfSDavid du Colombier DN *dp; 5927dd7cddfSDavid du Colombier int i; 5937dd7cddfSDavid du Colombier RR *rp; 5947dd7cddfSDavid du Colombier 5957dd7cddfSDavid du Colombier lock(&dnlock); 5967dd7cddfSDavid du Colombier 5977dd7cddfSDavid du Colombier /* time out all database entries */ 5987dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 599410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) { 600410ea80bSDavid du Colombier dp->keep = 0; 6017dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 6027dd7cddfSDavid du Colombier if(rp->db) 6037dd7cddfSDavid du Colombier rp->expire = 0; 604410ea80bSDavid du Colombier } 6057dd7cddfSDavid du Colombier 6067dd7cddfSDavid du Colombier unlock(&dnlock); 6077dd7cddfSDavid du Colombier } 6087dd7cddfSDavid du Colombier 6097dd7cddfSDavid du Colombier /* 6104f8f669cSDavid du Colombier * mark all local db records about my area as authoritative, 6114f8f669cSDavid du Colombier * time out any others 6127dd7cddfSDavid du Colombier */ 6137dd7cddfSDavid du Colombier void 6147dd7cddfSDavid du Colombier dnauthdb(void) 6157dd7cddfSDavid du Colombier { 6166b0d5c8bSDavid du Colombier int i; 6174f8f669cSDavid du Colombier ulong minttl; 6186b0d5c8bSDavid du Colombier Area *area; 6194f8f669cSDavid du Colombier DN *dp; 6207dd7cddfSDavid du Colombier RR *rp; 6217dd7cddfSDavid du Colombier 6227dd7cddfSDavid du Colombier lock(&dnlock); 6237dd7cddfSDavid du Colombier 6247dd7cddfSDavid du Colombier /* time out all database entries */ 6257dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 6267dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 6277dd7cddfSDavid du Colombier area = inmyarea(dp->name); 6287dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 6297dd7cddfSDavid du Colombier if(rp->db){ 6307dd7cddfSDavid du Colombier if(area){ 6314f8f669cSDavid du Colombier minttl = area->soarr->soa->minttl; 6324f8f669cSDavid du Colombier if(rp->ttl < minttl) 6334f8f669cSDavid du Colombier rp->ttl = minttl; 6347dd7cddfSDavid du Colombier rp->auth = 1; 6357dd7cddfSDavid du Colombier } 6367dd7cddfSDavid du Colombier if(rp->expire == 0){ 6377dd7cddfSDavid du Colombier rp->db = 0; 6387dd7cddfSDavid du Colombier dp->referenced = now-Reserved-1; 6397dd7cddfSDavid du Colombier } 6407dd7cddfSDavid du Colombier } 6417dd7cddfSDavid du Colombier } 6427dd7cddfSDavid du Colombier 6437dd7cddfSDavid du Colombier unlock(&dnlock); 6447dd7cddfSDavid du Colombier } 6457dd7cddfSDavid du Colombier 6467dd7cddfSDavid du Colombier /* 6477dd7cddfSDavid du Colombier * keep track of other processes to know if we can 6487dd7cddfSDavid du Colombier * garbage collect. block while garbage collecting. 6497dd7cddfSDavid du Colombier */ 6507dd7cddfSDavid du Colombier int 651b4b9fc2fSDavid du Colombier getactivity(Request *req, int recursive) 6527dd7cddfSDavid du Colombier { 6537dd7cddfSDavid du Colombier int rv; 6547dd7cddfSDavid du Colombier 6554f8f669cSDavid du Colombier if(traceactivity) 6564f8f669cSDavid du Colombier dnslog("get: %d active by pid %d from %p", 6574f8f669cSDavid du Colombier dnvars.active, getpid(), getcallerpc(&req)); 6587dd7cddfSDavid du Colombier lock(&dnvars); 659b4b9fc2fSDavid du Colombier /* 660b4b9fc2fSDavid du Colombier * can't block here if we're already holding one 661b4b9fc2fSDavid du Colombier * of the dnvars.active (recursive). will deadlock. 662b4b9fc2fSDavid du Colombier */ 663b4b9fc2fSDavid du Colombier while(!recursive && dnvars.mutex){ 6647dd7cddfSDavid du Colombier unlock(&dnvars); 665d6d99297SDavid du Colombier sleep(100); /* tune; was 200 */ 6667dd7cddfSDavid du Colombier lock(&dnvars); 6677dd7cddfSDavid du Colombier } 6687dd7cddfSDavid du Colombier rv = ++dnvars.active; 6694f8f669cSDavid du Colombier now = time(nil); 670a41547ffSDavid du Colombier nowns = nsec(); 6717dd7cddfSDavid du Colombier req->id = ++dnvars.id; 6727dd7cddfSDavid du Colombier unlock(&dnvars); 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier return rv; 6757dd7cddfSDavid du Colombier } 6767dd7cddfSDavid du Colombier void 677b4b9fc2fSDavid du Colombier putactivity(int recursive) 6787dd7cddfSDavid du Colombier { 6797dd7cddfSDavid du Colombier static ulong lastclean; 6807dd7cddfSDavid du Colombier 6814f8f669cSDavid du Colombier if(traceactivity) 6824f8f669cSDavid du Colombier dnslog("put: %d active by pid %d", 6834f8f669cSDavid du Colombier dnvars.active, getpid()); 6847dd7cddfSDavid du Colombier lock(&dnvars); 6857dd7cddfSDavid du Colombier dnvars.active--; 6864f8f669cSDavid du Colombier assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */ 6877dd7cddfSDavid du Colombier 6887dd7cddfSDavid du Colombier /* 6897dd7cddfSDavid du Colombier * clean out old entries and check for new db periodicly 690b4b9fc2fSDavid du Colombier * can't block here if being called to let go a "recursive" lock 691b4b9fc2fSDavid du Colombier * or we'll deadlock waiting for ourselves to give up the dnvars.active. 6927dd7cddfSDavid du Colombier */ 6934f8f669cSDavid du Colombier if (recursive || dnvars.mutex || 6944f8f669cSDavid du Colombier (needrefresh == 0 && dnvars.active > 0)){ 6957dd7cddfSDavid du Colombier unlock(&dnvars); 6967dd7cddfSDavid du Colombier return; 6977dd7cddfSDavid du Colombier } 6987dd7cddfSDavid du Colombier 6997dd7cddfSDavid du Colombier /* wait till we're alone */ 7007dd7cddfSDavid du Colombier dnvars.mutex = 1; 7017dd7cddfSDavid du Colombier while(dnvars.active > 0){ 7027dd7cddfSDavid du Colombier unlock(&dnvars); 703d6d99297SDavid du Colombier sleep(100); /* tune; was 100 */ 7047dd7cddfSDavid du Colombier lock(&dnvars); 7057dd7cddfSDavid du Colombier } 7067dd7cddfSDavid du Colombier unlock(&dnvars); 7077dd7cddfSDavid du Colombier 7087dd7cddfSDavid du Colombier db2cache(needrefresh); 7097dd7cddfSDavid du Colombier dnageall(0); 7107dd7cddfSDavid du Colombier 7117dd7cddfSDavid du Colombier /* let others back in */ 7127dd7cddfSDavid du Colombier lastclean = now; 7137dd7cddfSDavid du Colombier needrefresh = 0; 7147dd7cddfSDavid du Colombier dnvars.mutex = 0; 7157dd7cddfSDavid du Colombier } 7167dd7cddfSDavid du Colombier 717d2fd7a44SDavid du Colombier int 718d2fd7a44SDavid du Colombier rrlistlen(RR *rp) 719d2fd7a44SDavid du Colombier { 720d2fd7a44SDavid du Colombier int n; 721d2fd7a44SDavid du Colombier 722d2fd7a44SDavid du Colombier n = 0; 723d2fd7a44SDavid du Colombier for(; rp; rp = rp->next) 724d2fd7a44SDavid du Colombier ++n; 725d2fd7a44SDavid du Colombier return n; 726d2fd7a44SDavid du Colombier } 727d2fd7a44SDavid du Colombier 7283e12c5d1SDavid du Colombier /* 7296dc4800dSDavid du Colombier * Attach a single resource record to a domain name (new->owner). 7303e12c5d1SDavid du Colombier * - Avoid duplicates with already present RR's 7313e12c5d1SDavid du Colombier * - Chain all RR's of the same type adjacent to one another 7323e12c5d1SDavid du Colombier * - chain authoritative RR's ahead of non-authoritative ones 7336dc4800dSDavid du Colombier * - remove any expired RR's 734225077b0SDavid du Colombier * If new is a stale duplicate, rrfree it. 7356dc4800dSDavid du Colombier * Must be called with dnlock held. 7363e12c5d1SDavid du Colombier */ 7373e12c5d1SDavid du Colombier static void 7383e12c5d1SDavid du Colombier rrattach1(RR *new, int auth) 7393e12c5d1SDavid du Colombier { 7403e12c5d1SDavid du Colombier RR **l; 7413e12c5d1SDavid du Colombier RR *rp; 7423e12c5d1SDavid du Colombier DN *dp; 7433e12c5d1SDavid du Colombier 7447dd7cddfSDavid du Colombier assert(new->magic == RRmagic && !new->cached); 7457dd7cddfSDavid du Colombier 7464f8f669cSDavid du Colombier // dnslog("rrattach1: %s", new->owner->name); 747e9b54818SDavid du Colombier if(!new->db) { 748e9b54818SDavid du Colombier /* 749e9b54818SDavid du Colombier * try not to let responses expire before we 750e9b54818SDavid du Colombier * can use them to complete this query, by extending 751e464c1a8SDavid du Colombier * past (or nearly past) expiration time. 752e9b54818SDavid du Colombier */ 753e464c1a8SDavid du Colombier new->expire = new->ttl > now + Min? new->ttl: now + 10*Min; 754e9b54818SDavid du Colombier } else 7557dd7cddfSDavid du Colombier new->expire = now + Year; 7563e12c5d1SDavid du Colombier dp = new->owner; 7577dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 7587dd7cddfSDavid du Colombier new->auth |= auth; 7593e12c5d1SDavid du Colombier new->next = 0; 7603e12c5d1SDavid du Colombier 7613e12c5d1SDavid du Colombier /* 7623ff48bf5SDavid du Colombier * find first rr of the right type 7633e12c5d1SDavid du Colombier */ 7643e12c5d1SDavid du Colombier l = &dp->rr; 7657dd7cddfSDavid du Colombier for(rp = *l; rp; rp = *l){ 7667dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 7673e12c5d1SDavid du Colombier if(rp->type == new->type) 7683e12c5d1SDavid du Colombier break; 7693e12c5d1SDavid du Colombier l = &rp->next; 7703e12c5d1SDavid du Colombier } 7713e12c5d1SDavid du Colombier 7723e12c5d1SDavid du Colombier /* 7737dd7cddfSDavid du Colombier * negative entries replace positive entries 7747dd7cddfSDavid du Colombier * positive entries replace negative entries 7757dd7cddfSDavid du Colombier * newer entries replace older entries with the same fields 776225077b0SDavid du Colombier * 777225077b0SDavid du Colombier * look farther ahead than just the next entry when looking 778225077b0SDavid du Colombier * for duplicates; RRs of a given type can have different rdata 779225077b0SDavid du Colombier * fields (e.g. multiple NS servers). 7803e12c5d1SDavid du Colombier */ 781225077b0SDavid du Colombier while ((rp = *l) != nil){ 7827dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 7837dd7cddfSDavid du Colombier if(rp->type != new->type) 7843e12c5d1SDavid du Colombier break; 7857dd7cddfSDavid du Colombier 7867dd7cddfSDavid du Colombier if(rp->db == new->db && rp->auth == new->auth){ 7877dd7cddfSDavid du Colombier /* negative drives out positive and vice versa */ 7887dd7cddfSDavid du Colombier if(rp->negative != new->negative) { 789225077b0SDavid du Colombier rrdelete(l, rp); 790225077b0SDavid du Colombier continue; /* *l == rp->next */ 7913e12c5d1SDavid du Colombier } 7927dd7cddfSDavid du Colombier /* all things equal, pick the newer one */ 793225077b0SDavid du Colombier else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){ 7947dd7cddfSDavid du Colombier /* new drives out old */ 795225077b0SDavid du Colombier if (new->ttl <= rp->ttl && 796225077b0SDavid du Colombier new->expire <= rp->expire) { 7973e12c5d1SDavid du Colombier rrfree(new); 7983e12c5d1SDavid du Colombier return; 7993e12c5d1SDavid du Colombier } 800225077b0SDavid du Colombier rrdelete(l, rp); 801225077b0SDavid du Colombier continue; /* *l == rp->next */ 8027dd7cddfSDavid du Colombier } 803225077b0SDavid du Colombier /* 804225077b0SDavid du Colombier * Hack for pointer records. This makes sure 8053ff48bf5SDavid du Colombier * the ordering in the list reflects the ordering 8063ff48bf5SDavid du Colombier * received or read from the database 8073ff48bf5SDavid du Colombier */ 808225077b0SDavid du Colombier else if(rp->type == Tptr && 809225077b0SDavid du Colombier !rp->negative && !new->negative && 810225077b0SDavid du Colombier rp->ptr->ordinal > new->ptr->ordinal) 8113ff48bf5SDavid du Colombier break; 8123ff48bf5SDavid du Colombier } 8133e12c5d1SDavid du Colombier l = &rp->next; 8143e12c5d1SDavid du Colombier } 8153e12c5d1SDavid du Colombier 816530fef66SDavid du Colombier if (rronlist(new, rp)) { 8174f927735SDavid du Colombier /* should not happen; duplicates were processed above */ 818530fef66SDavid du Colombier dnslog("adding duplicate %R to list of %R; aborting", new, rp); 8194f927735SDavid du Colombier abort(); 8204f927735SDavid du Colombier } 8213e12c5d1SDavid du Colombier /* 8223e12c5d1SDavid du Colombier * add to chain 8233e12c5d1SDavid du Colombier */ 8247dd7cddfSDavid du Colombier new->cached = 1; 825530fef66SDavid du Colombier new->next = rp; 8263e12c5d1SDavid du Colombier *l = new; 8273e12c5d1SDavid du Colombier } 8283e12c5d1SDavid du Colombier 8293e12c5d1SDavid du Colombier /* 8303e12c5d1SDavid du Colombier * Attach a list of resource records to a domain name. 831225077b0SDavid du Colombier * May rrfree any stale duplicate RRs; dismembers the list. 832225077b0SDavid du Colombier * Upon return, every RR in the list will have been rrfree-d 833225077b0SDavid du Colombier * or attached to its domain name. 8346dc4800dSDavid du Colombier * See rrattach1 for properties preserved. 8353e12c5d1SDavid du Colombier */ 8363e12c5d1SDavid du Colombier void 8373e12c5d1SDavid du Colombier rrattach(RR *rp, int auth) 8383e12c5d1SDavid du Colombier { 8393e12c5d1SDavid du Colombier RR *next; 840d2fd7a44SDavid du Colombier DN *dp; 8413e12c5d1SDavid du Colombier 842bd389b36SDavid du Colombier lock(&dnlock); 8433e12c5d1SDavid du Colombier for(; rp; rp = next){ 8443e12c5d1SDavid du Colombier next = rp->next; 8454f8f669cSDavid du Colombier rp->next = nil; 846d2fd7a44SDavid du Colombier dp = rp->owner; 8477dd7cddfSDavid du Colombier 8487dd7cddfSDavid du Colombier /* avoid any outside spoofing */ 8494f8f669cSDavid du Colombier // dnslog("rrattach: %s", rp->owner->name); 8504f8f669cSDavid du Colombier if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name)) 8517dd7cddfSDavid du Colombier rrfree(rp); 852d2fd7a44SDavid du Colombier else { 853530fef66SDavid du Colombier /* ameliorate the memory leak */ 854530fef66SDavid du Colombier if (0 && rrlistlen(dp->rr) > 50 && !dp->keep) { 855530fef66SDavid du Colombier dnslog("rrattach(%s): rr list too long; " 856530fef66SDavid du Colombier "freeing it", dp->name); 857530fef66SDavid du Colombier rrfreelist(dp->rr); 858530fef66SDavid du Colombier dp->rr = nil; 859530fef66SDavid du Colombier } else 860530fef66SDavid du Colombier USED(dp); 8613e12c5d1SDavid du Colombier rrattach1(rp, auth); 862d2fd7a44SDavid du Colombier } 8633e12c5d1SDavid du Colombier } 864bd389b36SDavid du Colombier unlock(&dnlock); 8653e12c5d1SDavid du Colombier } 8663e12c5d1SDavid du Colombier 867530fef66SDavid du Colombier /* should be called with dnlock held */ 8684f8f669cSDavid du Colombier RR** 8697dd7cddfSDavid du Colombier rrcopy(RR *rp, RR **last) 8707dd7cddfSDavid du Colombier { 8714f8f669cSDavid du Colombier Cert *cert; 8724f8f669cSDavid du Colombier Key *key; 8734f8f669cSDavid du Colombier Null *null; 8747dd7cddfSDavid du Colombier RR *nrp; 8757dd7cddfSDavid du Colombier SOA *soa; 8769a747e4fSDavid du Colombier Sig *sig; 87760845620SDavid du Colombier Txt *t, *nt, **l; 8787dd7cddfSDavid du Colombier 8797dd7cddfSDavid du Colombier nrp = rralloc(rp->type); 880a41547ffSDavid du Colombier setmalloctag(nrp, getcallerpc(&rp)); 8819a747e4fSDavid du Colombier switch(rp->type){ 88260845620SDavid du Colombier case Ttxt: 88360845620SDavid du Colombier *nrp = *rp; 88460845620SDavid du Colombier l = &nrp->txt; 88560845620SDavid du Colombier *l = nil; 88660845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next){ 88760845620SDavid du Colombier nt = emalloc(sizeof(*nt)); 88860845620SDavid du Colombier nt->p = estrdup(t->p); 88960845620SDavid du Colombier nt->next = nil; 89060845620SDavid du Colombier *l = nt; 89160845620SDavid du Colombier l = &nt->next; 89260845620SDavid du Colombier } 89360845620SDavid du Colombier break; 8949a747e4fSDavid du Colombier case Tsoa: 8957dd7cddfSDavid du Colombier soa = nrp->soa; 8967dd7cddfSDavid du Colombier *nrp = *rp; 8977dd7cddfSDavid du Colombier nrp->soa = soa; 8987dd7cddfSDavid du Colombier *nrp->soa = *rp->soa; 899dc5a79c1SDavid du Colombier nrp->soa->slaves = copyserverlist(rp->soa->slaves); 9009a747e4fSDavid du Colombier break; 9014f8f669cSDavid du Colombier case Tsrv: 9024f8f669cSDavid du Colombier *nrp = *rp; 903fd87a217SDavid du Colombier nrp->srv = emalloc(sizeof *nrp->srv); 9044f8f669cSDavid du Colombier *nrp->srv = *rp->srv; 9054f8f669cSDavid du Colombier break; 9069a747e4fSDavid du Colombier case Tkey: 9079a747e4fSDavid du Colombier key = nrp->key; 9089a747e4fSDavid du Colombier *nrp = *rp; 9099a747e4fSDavid du Colombier nrp->key = key; 9109a747e4fSDavid du Colombier *key = *rp->key; 9119a747e4fSDavid du Colombier key->data = emalloc(key->dlen); 9129a747e4fSDavid du Colombier memmove(key->data, rp->key->data, rp->key->dlen); 9139a747e4fSDavid du Colombier break; 9149a747e4fSDavid du Colombier case Tsig: 9159a747e4fSDavid du Colombier sig = nrp->sig; 9169a747e4fSDavid du Colombier *nrp = *rp; 9179a747e4fSDavid du Colombier nrp->sig = sig; 9189a747e4fSDavid du Colombier *sig = *rp->sig; 9199a747e4fSDavid du Colombier sig->data = emalloc(sig->dlen); 9209a747e4fSDavid du Colombier memmove(sig->data, rp->sig->data, rp->sig->dlen); 9219a747e4fSDavid du Colombier break; 9229a747e4fSDavid du Colombier case Tcert: 9239a747e4fSDavid du Colombier cert = nrp->cert; 9249a747e4fSDavid du Colombier *nrp = *rp; 9259a747e4fSDavid du Colombier nrp->cert = cert; 9269a747e4fSDavid du Colombier *cert = *rp->cert; 9279a747e4fSDavid du Colombier cert->data = emalloc(cert->dlen); 9289a747e4fSDavid du Colombier memmove(cert->data, rp->cert->data, rp->cert->dlen); 9299a747e4fSDavid du Colombier break; 9309a747e4fSDavid du Colombier case Tnull: 9319a747e4fSDavid du Colombier null = nrp->null; 9329a747e4fSDavid du Colombier *nrp = *rp; 9339a747e4fSDavid du Colombier nrp->null = null; 9349a747e4fSDavid du Colombier *null = *rp->null; 9359a747e4fSDavid du Colombier null->data = emalloc(null->dlen); 9369a747e4fSDavid du Colombier memmove(null->data, rp->null->data, rp->null->dlen); 9379a747e4fSDavid du Colombier break; 9389a747e4fSDavid du Colombier default: 9399a747e4fSDavid du Colombier *nrp = *rp; 9409a747e4fSDavid du Colombier break; 9417dd7cddfSDavid du Colombier } 9427dd7cddfSDavid du Colombier nrp->cached = 0; 9437dd7cddfSDavid du Colombier nrp->next = 0; 9447dd7cddfSDavid du Colombier *last = nrp; 9457dd7cddfSDavid du Colombier return &nrp->next; 9467dd7cddfSDavid du Colombier } 9477dd7cddfSDavid du Colombier 9483e12c5d1SDavid du Colombier /* 9493e12c5d1SDavid du Colombier * lookup a resource record of a particular type and 9507dd7cddfSDavid du Colombier * class attached to a domain name. Return copies. 9517dd7cddfSDavid du Colombier * 9527dd7cddfSDavid du Colombier * Priority ordering is: 9537dd7cddfSDavid du Colombier * db authoritative 9547dd7cddfSDavid du Colombier * not timed out network authoritative 9557dd7cddfSDavid du Colombier * not timed out network unauthoritative 9567dd7cddfSDavid du Colombier * unauthoritative db 9577dd7cddfSDavid du Colombier * 95880ee5cbfSDavid du Colombier * if flag NOneg is set, don't return negative cached entries. 9597dd7cddfSDavid du Colombier * return nothing instead. 9603e12c5d1SDavid du Colombier */ 9613e12c5d1SDavid du Colombier RR* 9627dd7cddfSDavid du Colombier rrlookup(DN *dp, int type, int flag) 9633e12c5d1SDavid du Colombier { 9647dd7cddfSDavid du Colombier RR *rp, *first, **last; 9653e12c5d1SDavid du Colombier 9667dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 9677dd7cddfSDavid du Colombier 9687dd7cddfSDavid du Colombier first = 0; 9697dd7cddfSDavid du Colombier last = &first; 9707dd7cddfSDavid du Colombier lock(&dnlock); 9717dd7cddfSDavid du Colombier 9727dd7cddfSDavid du Colombier /* try for an authoritative db entry */ 9733e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 9747dd7cddfSDavid du Colombier assert(rp->magic == RRmagic && rp->cached); 9757dd7cddfSDavid du Colombier if(rp->db) 9767dd7cddfSDavid du Colombier if(rp->auth) 977a41547ffSDavid du Colombier if(tsame(type, rp->type)) { 9784e5f5f32SDavid du Colombier last = rrcopy(rp, last); 979a41547ffSDavid du Colombier // setmalloctag(*last, getcallerpc(&dp)); 980a41547ffSDavid du Colombier } 9813e12c5d1SDavid du Colombier } 9827dd7cddfSDavid du Colombier if(first) 9837dd7cddfSDavid du Colombier goto out; 9847dd7cddfSDavid du Colombier 9854f8f669cSDavid du Colombier /* try for a living authoritative network entry */ 9867dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 9877dd7cddfSDavid du Colombier if(!rp->db) 9887dd7cddfSDavid du Colombier if(rp->auth) 9897dd7cddfSDavid du Colombier if(rp->ttl + 60 > now) 9907dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 9917dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative) 9927dd7cddfSDavid du Colombier goto out; 9937dd7cddfSDavid du Colombier last = rrcopy(rp, last); 9947dd7cddfSDavid du Colombier } 9957dd7cddfSDavid du Colombier } 9967dd7cddfSDavid du Colombier if(first) 9977dd7cddfSDavid du Colombier goto out; 9987dd7cddfSDavid du Colombier 9994f8f669cSDavid du Colombier /* try for a living unauthoritative network entry */ 10007dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 10017dd7cddfSDavid du Colombier if(!rp->db) 10027dd7cddfSDavid du Colombier if(rp->ttl + 60 > now) 10037dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 10047dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative) 10057dd7cddfSDavid du Colombier goto out; 10064e5f5f32SDavid du Colombier last = rrcopy(rp, last); 10077dd7cddfSDavid du Colombier } 10087dd7cddfSDavid du Colombier } 10097dd7cddfSDavid du Colombier if(first) 10107dd7cddfSDavid du Colombier goto out; 10117dd7cddfSDavid du Colombier 10127dd7cddfSDavid du Colombier /* try for an unauthoritative db entry */ 10137dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 10147dd7cddfSDavid du Colombier if(rp->db) 10157dd7cddfSDavid du Colombier if(tsame(type, rp->type)) 10167dd7cddfSDavid du Colombier last = rrcopy(rp, last); 10177dd7cddfSDavid du Colombier } 10187dd7cddfSDavid du Colombier if(first) 10197dd7cddfSDavid du Colombier goto out; 10207dd7cddfSDavid du Colombier 10217dd7cddfSDavid du Colombier /* otherwise, settle for anything we got (except for negative caches) */ 10224f8f669cSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) 10237dd7cddfSDavid du Colombier if(tsame(type, rp->type)){ 10247dd7cddfSDavid du Colombier if(rp->negative) 10257dd7cddfSDavid du Colombier goto out; 10267dd7cddfSDavid du Colombier last = rrcopy(rp, last); 10277dd7cddfSDavid du Colombier } 10287dd7cddfSDavid du Colombier 10297dd7cddfSDavid du Colombier out: 10307dd7cddfSDavid du Colombier unlock(&dnlock); 10317dd7cddfSDavid du Colombier unique(first); 10324f8f669cSDavid du Colombier // dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first); 1033a41547ffSDavid du Colombier // if (first) 1034a41547ffSDavid du Colombier // setmalloctag(first, getcallerpc(&dp)); 10357dd7cddfSDavid du Colombier return first; 10363e12c5d1SDavid du Colombier } 10373e12c5d1SDavid du Colombier 10383e12c5d1SDavid du Colombier /* 10393e12c5d1SDavid du Colombier * convert an ascii RR type name to its integer representation 10403e12c5d1SDavid du Colombier */ 10413e12c5d1SDavid du Colombier int 10423e12c5d1SDavid du Colombier rrtype(char *atype) 10433e12c5d1SDavid du Colombier { 10443e12c5d1SDavid du Colombier int i; 10453e12c5d1SDavid du Colombier 1046219b2ee8SDavid du Colombier for(i = 0; i <= Tall; i++) 10473e12c5d1SDavid du Colombier if(rrtname[i] && strcmp(rrtname[i], atype) == 0) 10483e12c5d1SDavid du Colombier return i; 10497dd7cddfSDavid du Colombier 10504f8f669cSDavid du Colombier /* make any a synonym for all */ 10517dd7cddfSDavid du Colombier if(strcmp(atype, "any") == 0) 10527dd7cddfSDavid du Colombier return Tall; 1053d9924332SDavid du Colombier else if(isascii(atype[0]) && isdigit(atype[0])) 10543e12c5d1SDavid du Colombier return atoi(atype); 1055d9924332SDavid du Colombier else 1056d9924332SDavid du Colombier return -1; 10573e12c5d1SDavid du Colombier } 10583e12c5d1SDavid du Colombier 10593e12c5d1SDavid du Colombier /* 10605d459b5aSDavid du Colombier * return 0 if not a supported rr type 10615d459b5aSDavid du Colombier */ 10625d459b5aSDavid du Colombier int 10635d459b5aSDavid du Colombier rrsupported(int type) 10645d459b5aSDavid du Colombier { 10655d459b5aSDavid du Colombier if(type < 0 || type >Tall) 10665d459b5aSDavid du Colombier return 0; 10674f8f669cSDavid du Colombier return rrtname[type] != nil; 10685d459b5aSDavid du Colombier } 10695d459b5aSDavid du Colombier 10705d459b5aSDavid du Colombier /* 1071219b2ee8SDavid du Colombier * compare 2 types 1072219b2ee8SDavid du Colombier */ 1073219b2ee8SDavid du Colombier int 1074219b2ee8SDavid du Colombier tsame(int t1, int t2) 1075219b2ee8SDavid du Colombier { 1076219b2ee8SDavid du Colombier return t1 == t2 || t1 == Tall; 1077219b2ee8SDavid du Colombier } 1078219b2ee8SDavid du Colombier 1079219b2ee8SDavid du Colombier /* 10807dd7cddfSDavid du Colombier * Add resource records to a list, duplicate them if they are cached 1081530fef66SDavid du Colombier * RR's since these are shared. should be called with dnlock held 1082530fef66SDavid du Colombier * to avoid racing down the start chain. 10833e12c5d1SDavid du Colombier */ 10843e12c5d1SDavid du Colombier RR* 10857dd7cddfSDavid du Colombier rrcat(RR **start, RR *rp) 10863e12c5d1SDavid du Colombier { 1087225077b0SDavid du Colombier RR *olp, *nlp; 10883e12c5d1SDavid du Colombier RR **last; 10893e12c5d1SDavid du Colombier 1090225077b0SDavid du Colombier /* check for duplicates */ 1091225077b0SDavid du Colombier for (olp = *start; 0 && olp; olp = olp->next) 1092225077b0SDavid du Colombier for (nlp = rp; nlp; nlp = nlp->next) 1093225077b0SDavid du Colombier if (rrsame(nlp, olp)) 1094225077b0SDavid du Colombier dnslog("rrcat: duplicate RR: %R", nlp); 1095225077b0SDavid du Colombier USED(olp); 1096225077b0SDavid du Colombier 10973e12c5d1SDavid du Colombier last = start; 10984f8f669cSDavid du Colombier while(*last != nil) 10993e12c5d1SDavid du Colombier last = &(*last)->next; 11003e12c5d1SDavid du Colombier 11017dd7cddfSDavid du Colombier *last = rp; 11027dd7cddfSDavid du Colombier return *start; 11033e12c5d1SDavid du Colombier } 11043e12c5d1SDavid du Colombier 11057dd7cddfSDavid du Colombier /* 11067dd7cddfSDavid du Colombier * remove negative cache rr's from an rr list 11077dd7cddfSDavid du Colombier */ 11087dd7cddfSDavid du Colombier RR* 11097dd7cddfSDavid du Colombier rrremneg(RR **l) 11107dd7cddfSDavid du Colombier { 11117dd7cddfSDavid du Colombier RR **nl, *rp; 11127dd7cddfSDavid du Colombier RR *first; 11137dd7cddfSDavid du Colombier 11147dd7cddfSDavid du Colombier first = nil; 11157dd7cddfSDavid du Colombier nl = &first; 11167dd7cddfSDavid du Colombier while(*l != nil){ 11177dd7cddfSDavid du Colombier rp = *l; 11187dd7cddfSDavid du Colombier if(rp->negative){ 11197dd7cddfSDavid du Colombier *l = rp->next; 11207dd7cddfSDavid du Colombier *nl = rp; 11217dd7cddfSDavid du Colombier nl = &rp->next; 11227dd7cddfSDavid du Colombier *nl = nil; 11237dd7cddfSDavid du Colombier } else 112480ee5cbfSDavid du Colombier l = &rp->next; 11257dd7cddfSDavid du Colombier } 11267dd7cddfSDavid du Colombier 11277dd7cddfSDavid du Colombier return first; 11287dd7cddfSDavid du Colombier } 11297dd7cddfSDavid du Colombier 11307dd7cddfSDavid du Colombier /* 11317dd7cddfSDavid du Colombier * remove rr's of a particular type from an rr list 11327dd7cddfSDavid du Colombier */ 11337dd7cddfSDavid du Colombier RR* 11347dd7cddfSDavid du Colombier rrremtype(RR **l, int type) 11357dd7cddfSDavid du Colombier { 11364f8f669cSDavid du Colombier RR *first, *rp; 11374f8f669cSDavid du Colombier RR **nl; 11387dd7cddfSDavid du Colombier 11397dd7cddfSDavid du Colombier first = nil; 11407dd7cddfSDavid du Colombier nl = &first; 11417dd7cddfSDavid du Colombier while(*l != nil){ 11427dd7cddfSDavid du Colombier rp = *l; 11437dd7cddfSDavid du Colombier if(rp->type == type){ 11447dd7cddfSDavid du Colombier *l = rp->next; 11457dd7cddfSDavid du Colombier *nl = rp; 11467dd7cddfSDavid du Colombier nl = &rp->next; 11477dd7cddfSDavid du Colombier *nl = nil; 11487dd7cddfSDavid du Colombier } else 11497dd7cddfSDavid du Colombier l = &(*l)->next; 11507dd7cddfSDavid du Colombier } 11517dd7cddfSDavid du Colombier 11527dd7cddfSDavid du Colombier return first; 11533e12c5d1SDavid du Colombier } 11543e12c5d1SDavid du Colombier 11554f8f669cSDavid du Colombier static char * 11564f8f669cSDavid du Colombier dnname(DN *dn) 11574f8f669cSDavid du Colombier { 11584f8f669cSDavid du Colombier return dn? dn->name: "<null>"; 11594f8f669cSDavid du Colombier } 11604f8f669cSDavid du Colombier 11613e12c5d1SDavid du Colombier /* 11623e12c5d1SDavid du Colombier * print conversion for rr records 11633e12c5d1SDavid du Colombier */ 11643e12c5d1SDavid du Colombier int 11659a747e4fSDavid du Colombier rrfmt(Fmt *f) 11663e12c5d1SDavid du Colombier { 11676b0d5c8bSDavid du Colombier int rv; 11684f8f669cSDavid du Colombier char *strp; 11696b0d5c8bSDavid du Colombier char buf[Domlen]; 11704f8f669cSDavid du Colombier Fmt fstr; 11714f8f669cSDavid du Colombier RR *rp; 1172dc5a79c1SDavid du Colombier Server *s; 11734f8f669cSDavid du Colombier SOA *soa; 11744f8f669cSDavid du Colombier Srv *srv; 117560845620SDavid du Colombier Txt *t; 11763e12c5d1SDavid du Colombier 11779a747e4fSDavid du Colombier fmtstrinit(&fstr); 11789a747e4fSDavid du Colombier 11799a747e4fSDavid du Colombier rp = va_arg(f->args, RR*); 11804f8f669cSDavid du Colombier if(rp == nil){ 11819a747e4fSDavid du Colombier fmtprint(&fstr, "<null>"); 1182219b2ee8SDavid du Colombier goto out; 1183219b2ee8SDavid du Colombier } 1184219b2ee8SDavid du Colombier 11854f8f669cSDavid du Colombier fmtprint(&fstr, "%s %s", dnname(rp->owner), 11869a747e4fSDavid du Colombier rrname(rp->type, buf, sizeof buf)); 11877dd7cddfSDavid du Colombier 11887dd7cddfSDavid du Colombier if(rp->negative){ 11899a747e4fSDavid du Colombier fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode); 11907dd7cddfSDavid du Colombier goto out; 11917dd7cddfSDavid du Colombier } 11923e12c5d1SDavid du Colombier 11933e12c5d1SDavid du Colombier switch(rp->type){ 11943e12c5d1SDavid du Colombier case Thinfo: 11954f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os)); 11963e12c5d1SDavid du Colombier break; 11973e12c5d1SDavid du Colombier case Tcname: 11983e12c5d1SDavid du Colombier case Tmb: 11993e12c5d1SDavid du Colombier case Tmd: 12003e12c5d1SDavid du Colombier case Tmf: 12013e12c5d1SDavid du Colombier case Tns: 12024f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->host)); 12033e12c5d1SDavid du Colombier break; 12043e12c5d1SDavid du Colombier case Tmg: 12053e12c5d1SDavid du Colombier case Tmr: 12064f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->mb)); 12073e12c5d1SDavid du Colombier break; 12083e12c5d1SDavid du Colombier case Tminfo: 12094f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb)); 12103e12c5d1SDavid du Colombier break; 12113e12c5d1SDavid du Colombier case Tmx: 12124f8f669cSDavid du Colombier fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host)); 12133e12c5d1SDavid du Colombier break; 12143e12c5d1SDavid du Colombier case Ta: 12155d459b5aSDavid du Colombier case Taaaa: 12164f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ip)); 12173e12c5d1SDavid du Colombier break; 12183e12c5d1SDavid du Colombier case Tptr: 12194f8f669cSDavid du Colombier // fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr), 12204f8f669cSDavid du Colombier // rp->ptr? rp->ptr->ordinal: "<null>"); 12214f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ptr)); 12223e12c5d1SDavid du Colombier break; 12233e12c5d1SDavid du Colombier case Tsoa: 12244f8f669cSDavid du Colombier soa = rp->soa; 12254f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", 12264f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb), 12274f8f669cSDavid du Colombier (soa? soa->serial: 0), 12284f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0), 12294f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0)); 12304f8f669cSDavid du Colombier if (soa) 12314f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next) 1232dc5a79c1SDavid du Colombier fmtprint(&fstr, " %s", s->name); 12333e12c5d1SDavid du Colombier break; 12344f8f669cSDavid du Colombier case Tsrv: 12354f8f669cSDavid du Colombier srv = rp->srv; 12364f8f669cSDavid du Colombier fmtprint(&fstr, "\t%ud %ud %ud %s", 12374f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0), 1238225077b0SDavid du Colombier rp->port, dnname(rp->host)); 12394f8f669cSDavid du Colombier break; 12409a747e4fSDavid du Colombier case Tnull: 12414f8f669cSDavid du Colombier if (rp->null == nil) 12424f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null>"); 12434f8f669cSDavid du Colombier else 12444f8f669cSDavid du Colombier fmtprint(&fstr, "\t%.*H", rp->null->dlen, 12454f8f669cSDavid du Colombier rp->null->data); 12469a747e4fSDavid du Colombier break; 12477dd7cddfSDavid du Colombier case Ttxt: 124860845620SDavid du Colombier fmtprint(&fstr, "\t"); 124960845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 125060845620SDavid du Colombier fmtprint(&fstr, "%s", t->p); 12517dd7cddfSDavid du Colombier break; 12527dd7cddfSDavid du Colombier case Trp: 12534f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp)); 12547dd7cddfSDavid du Colombier break; 12557dd7cddfSDavid du Colombier case Tkey: 12564f8f669cSDavid du Colombier if (rp->key == nil) 12574f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>"); 12584f8f669cSDavid du Colombier else 12594f8f669cSDavid du Colombier fmtprint(&fstr, "\t%d %d %d", rp->key->flags, 12604f8f669cSDavid du Colombier rp->key->proto, rp->key->alg); 12617dd7cddfSDavid du Colombier break; 12627dd7cddfSDavid du Colombier case Tsig: 12634f8f669cSDavid du Colombier if (rp->sig == nil) 12644f8f669cSDavid du Colombier fmtprint(&fstr, 12654f8f669cSDavid du Colombier "\t<null> <null> <null> <null> <null> <null> <null> <null>"); 12664f8f669cSDavid du Colombier else 12679a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s", 12684f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels, 12694f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep, 12704f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer)); 12717dd7cddfSDavid du Colombier break; 12727dd7cddfSDavid du Colombier case Tcert: 12734f8f669cSDavid du Colombier if (rp->cert == nil) 12744f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>"); 12754f8f669cSDavid du Colombier else 12769a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d", 12774f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg); 12783e12c5d1SDavid du Colombier break; 12793e12c5d1SDavid du Colombier } 1280219b2ee8SDavid du Colombier out: 12819a747e4fSDavid du Colombier strp = fmtstrflush(&fstr); 12829a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp); 12839a747e4fSDavid du Colombier free(strp); 12849a747e4fSDavid du Colombier return rv; 12853e12c5d1SDavid du Colombier } 12863e12c5d1SDavid du Colombier 12873e12c5d1SDavid du Colombier /* 12887dd7cddfSDavid du Colombier * print conversion for rr records in attribute value form 12897dd7cddfSDavid du Colombier */ 12907dd7cddfSDavid du Colombier int 12919a747e4fSDavid du Colombier rravfmt(Fmt *f) 12927dd7cddfSDavid du Colombier { 12934f8f669cSDavid du Colombier int rv, quote; 12949a747e4fSDavid du Colombier char *strp; 12959a747e4fSDavid du Colombier Fmt fstr; 12964f8f669cSDavid du Colombier RR *rp; 1297dc5a79c1SDavid du Colombier Server *s; 12984f8f669cSDavid du Colombier SOA *soa; 12994f8f669cSDavid du Colombier Srv *srv; 130060845620SDavid du Colombier Txt *t; 13017dd7cddfSDavid du Colombier 13029a747e4fSDavid du Colombier fmtstrinit(&fstr); 13039a747e4fSDavid du Colombier 13049a747e4fSDavid du Colombier rp = va_arg(f->args, RR*); 13054f8f669cSDavid du Colombier if(rp == nil){ 13069a747e4fSDavid du Colombier fmtprint(&fstr, "<null>"); 13077dd7cddfSDavid du Colombier goto out; 13087dd7cddfSDavid du Colombier } 13097dd7cddfSDavid du Colombier 13107dd7cddfSDavid du Colombier if(rp->type == Tptr) 13114f8f669cSDavid du Colombier fmtprint(&fstr, "ptr=%s", dnname(rp->owner)); 13127dd7cddfSDavid du Colombier else 13134f8f669cSDavid du Colombier fmtprint(&fstr, "dom=%s", dnname(rp->owner)); 13147dd7cddfSDavid du Colombier 13157dd7cddfSDavid du Colombier switch(rp->type){ 13167dd7cddfSDavid du Colombier case Thinfo: 13174f8f669cSDavid du Colombier fmtprint(&fstr, " cpu=%s os=%s", 13184f8f669cSDavid du Colombier dnname(rp->cpu), dnname(rp->os)); 13197dd7cddfSDavid du Colombier break; 13207dd7cddfSDavid du Colombier case Tcname: 13214f8f669cSDavid du Colombier fmtprint(&fstr, " cname=%s", dnname(rp->host)); 13227dd7cddfSDavid du Colombier break; 13237dd7cddfSDavid du Colombier case Tmb: 13247dd7cddfSDavid du Colombier case Tmd: 13257dd7cddfSDavid du Colombier case Tmf: 13264f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->host)); 13277dd7cddfSDavid du Colombier break; 13287dd7cddfSDavid du Colombier case Tns: 13294f8f669cSDavid du Colombier fmtprint(&fstr, " ns=%s", dnname(rp->host)); 13307dd7cddfSDavid du Colombier break; 13317dd7cddfSDavid du Colombier case Tmg: 13327dd7cddfSDavid du Colombier case Tmr: 13334f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->mb)); 13347dd7cddfSDavid du Colombier break; 13357dd7cddfSDavid du Colombier case Tminfo: 13364f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s mbox=%s", 13374f8f669cSDavid du Colombier dnname(rp->mb), dnname(rp->rmb)); 13387dd7cddfSDavid du Colombier break; 13397dd7cddfSDavid du Colombier case Tmx: 13404f8f669cSDavid du Colombier fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host)); 13417dd7cddfSDavid du Colombier break; 13427dd7cddfSDavid du Colombier case Ta: 13435d459b5aSDavid du Colombier case Taaaa: 13444f8f669cSDavid du Colombier fmtprint(&fstr, " ip=%s", dnname(rp->ip)); 13457dd7cddfSDavid du Colombier break; 13467dd7cddfSDavid du Colombier case Tptr: 13474f8f669cSDavid du Colombier fmtprint(&fstr, " dom=%s", dnname(rp->ptr)); 13487dd7cddfSDavid du Colombier break; 13497dd7cddfSDavid du Colombier case Tsoa: 13504f8f669cSDavid du Colombier soa = rp->soa; 13514f8f669cSDavid du Colombier fmtprint(&fstr, 13524f8f669cSDavid du Colombier " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud", 13534f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb), 13544f8f669cSDavid du Colombier (soa? soa->serial: 0), 13554f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0), 13564f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0)); 13574f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next) 1358dc5a79c1SDavid du Colombier fmtprint(&fstr, " dnsslave=%s", s->name); 13597dd7cddfSDavid du Colombier break; 13604f8f669cSDavid du Colombier case Tsrv: 13614f8f669cSDavid du Colombier srv = rp->srv; 13624f8f669cSDavid du Colombier fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s", 13634f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0), 1364225077b0SDavid du Colombier rp->port, dnname(rp->host)); 13654f8f669cSDavid du Colombier break; 13669a747e4fSDavid du Colombier case Tnull: 13674f8f669cSDavid du Colombier if (rp->null == nil) 13684f8f669cSDavid du Colombier fmtprint(&fstr, " null=<null>"); 13694f8f669cSDavid du Colombier else 13704f8f669cSDavid du Colombier fmtprint(&fstr, " null=%.*H", rp->null->dlen, 13714f8f669cSDavid du Colombier rp->null->data); 13729a747e4fSDavid du Colombier break; 13737dd7cddfSDavid du Colombier case Ttxt: 137460845620SDavid du Colombier fmtprint(&fstr, " txt="); 137560845620SDavid du Colombier quote = 0; 137660845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 137760845620SDavid du Colombier if(strchr(t->p, ' ')) 137860845620SDavid du Colombier quote = 1; 137960845620SDavid du Colombier if(quote) 138060845620SDavid du Colombier fmtprint(&fstr, "\""); 138160845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next) 138260845620SDavid du Colombier fmtprint(&fstr, "%s", t->p); 138360845620SDavid du Colombier if(quote) 138460845620SDavid du Colombier fmtprint(&fstr, "\""); 13857dd7cddfSDavid du Colombier break; 13867dd7cddfSDavid du Colombier case Trp: 13874f8f669cSDavid du Colombier fmtprint(&fstr, " rp=%s txt=%s", 13884f8f669cSDavid du Colombier dnname(rp->rmb), dnname(rp->rp)); 13897dd7cddfSDavid du Colombier break; 13907dd7cddfSDavid du Colombier case Tkey: 13914f8f669cSDavid du Colombier if (rp->key == nil) 13924f8f669cSDavid du Colombier fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>"); 13934f8f669cSDavid du Colombier else 13949a747e4fSDavid du Colombier fmtprint(&fstr, " flags=%d proto=%d alg=%d", 13957dd7cddfSDavid du Colombier rp->key->flags, rp->key->proto, rp->key->alg); 13967dd7cddfSDavid du Colombier break; 13977dd7cddfSDavid du Colombier case Tsig: 13984f8f669cSDavid du Colombier if (rp->sig == nil) 13994f8f669cSDavid du Colombier fmtprint(&fstr, 14004f8f669cSDavid du Colombier " type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>"); 14014f8f669cSDavid du Colombier else 14024f8f669cSDavid du Colombier fmtprint(&fstr, 14034f8f669cSDavid du Colombier " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s", 14044f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels, 14054f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep, 14064f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer)); 14077dd7cddfSDavid du Colombier break; 14087dd7cddfSDavid du Colombier case Tcert: 14094f8f669cSDavid du Colombier if (rp->cert == nil) 14104f8f669cSDavid du Colombier fmtprint(&fstr, " type=<null> tag=<null> alg=<null>"); 14114f8f669cSDavid du Colombier else 14129a747e4fSDavid du Colombier fmtprint(&fstr, " type=%d tag=%d alg=%d", 14134f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg); 14147dd7cddfSDavid du Colombier break; 14157dd7cddfSDavid du Colombier } 14167dd7cddfSDavid du Colombier out: 14179a747e4fSDavid du Colombier strp = fmtstrflush(&fstr); 14189a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp); 14199a747e4fSDavid du Colombier free(strp); 14209a747e4fSDavid du Colombier return rv; 14213e12c5d1SDavid du Colombier } 14227dd7cddfSDavid du Colombier 14237dd7cddfSDavid du Colombier void 14247dd7cddfSDavid du Colombier warning(char *fmt, ...) 14257dd7cddfSDavid du Colombier { 14264f8f669cSDavid du Colombier char dnserr[256]; 14277dd7cddfSDavid du Colombier va_list arg; 14287dd7cddfSDavid du Colombier 14297dd7cddfSDavid du Colombier va_start(arg, fmt); 14309a747e4fSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); 14317dd7cddfSDavid du Colombier va_end(arg); 14324f8f669cSDavid du Colombier syslog(1, logfile, dnserr); /* on console too */ 14334f8f669cSDavid du Colombier } 14344f8f669cSDavid du Colombier 14354f8f669cSDavid du Colombier void 14364f8f669cSDavid du Colombier dnslog(char *fmt, ...) 14374f8f669cSDavid du Colombier { 14384f8f669cSDavid du Colombier char dnserr[256]; 14394f8f669cSDavid du Colombier va_list arg; 14404f8f669cSDavid du Colombier 14414f8f669cSDavid du Colombier va_start(arg, fmt); 14424f8f669cSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); 14434f8f669cSDavid du Colombier va_end(arg); 14444f8f669cSDavid du Colombier syslog(0, logfile, dnserr); 14454f8f669cSDavid du Colombier } 14464f8f669cSDavid du Colombier 14474f8f669cSDavid du Colombier /* 14484f8f669cSDavid du Colombier * based on libthread's threadsetname, but drags in less library code. 14494f8f669cSDavid du Colombier * actually just sets the arguments displayed. 14504f8f669cSDavid du Colombier */ 14514f8f669cSDavid du Colombier void 14524f8f669cSDavid du Colombier procsetname(char *fmt, ...) 14534f8f669cSDavid du Colombier { 14544f8f669cSDavid du Colombier int fd; 14554f8f669cSDavid du Colombier char *cmdname; 14564f8f669cSDavid du Colombier char buf[128]; 14574f8f669cSDavid du Colombier va_list arg; 14584f8f669cSDavid du Colombier 14594f8f669cSDavid du Colombier va_start(arg, fmt); 14604f8f669cSDavid du Colombier cmdname = vsmprint(fmt, arg); 14614f8f669cSDavid du Colombier va_end(arg); 14624f8f669cSDavid du Colombier if (cmdname == nil) 14634f8f669cSDavid du Colombier return; 14644f8f669cSDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid()); 14654f8f669cSDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){ 14664f8f669cSDavid du Colombier write(fd, cmdname, strlen(cmdname)+1); 14674f8f669cSDavid du Colombier close(fd); 14684f8f669cSDavid du Colombier } 14694f8f669cSDavid du Colombier free(cmdname); 14707dd7cddfSDavid du Colombier } 14717dd7cddfSDavid du Colombier 14727dd7cddfSDavid du Colombier /* 14737dd7cddfSDavid du Colombier * create a slave process to handle a request to avoid one request blocking 14747dd7cddfSDavid du Colombier * another 14757dd7cddfSDavid du Colombier */ 14767dd7cddfSDavid du Colombier void 14777dd7cddfSDavid du Colombier slave(Request *req) 14787dd7cddfSDavid du Colombier { 1479a41547ffSDavid du Colombier int ppid, procs; 14807dd7cddfSDavid du Colombier 14817dd7cddfSDavid du Colombier if(req->isslave) 14827dd7cddfSDavid du Colombier return; /* we're already a slave process */ 14837dd7cddfSDavid du Colombier 1484b4b9fc2fSDavid du Colombier /* 1485b4b9fc2fSDavid du Colombier * These calls to putactivity cannot block. 1486b4b9fc2fSDavid du Colombier * After getactivity(), the current process is counted 1487b4b9fc2fSDavid du Colombier * twice in dnvars.active (one will pass to the child). 1488b4b9fc2fSDavid du Colombier * If putactivity tries to wait for dnvars.active == 0, 1489b4b9fc2fSDavid du Colombier * it will never happen. 1490b4b9fc2fSDavid du Colombier */ 1491b4b9fc2fSDavid du Colombier 14927dd7cddfSDavid du Colombier /* limit parallelism */ 1493a41547ffSDavid du Colombier procs = getactivity(req, 1); 1494a41547ffSDavid du Colombier if (procs > stats.slavehiwat) 1495a41547ffSDavid du Colombier stats.slavehiwat = procs; 1496a41547ffSDavid du Colombier if(procs > Maxactive){ 14974f8f669cSDavid du Colombier if(traceactivity) 14984f8f669cSDavid du Colombier dnslog("[%d] too much activity", getpid()); 1499b4b9fc2fSDavid du Colombier putactivity(1); 15007dd7cddfSDavid du Colombier return; 15017dd7cddfSDavid du Colombier } 15027dd7cddfSDavid du Colombier 1503c73252aeSDavid du Colombier /* 1504c73252aeSDavid du Colombier * parent returns to main loop, child does the work. 1505c73252aeSDavid du Colombier * don't change note group. 1506c73252aeSDavid du Colombier */ 1507b4b9fc2fSDavid du Colombier ppid = getpid(); 1508c73252aeSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){ 15097dd7cddfSDavid du Colombier case -1: 1510b4b9fc2fSDavid du Colombier putactivity(1); 15117dd7cddfSDavid du Colombier break; 15127dd7cddfSDavid du Colombier case 0: 15134f8f669cSDavid du Colombier procsetname("request slave of pid %d", ppid); 15144f8f669cSDavid du Colombier if(traceactivity) 1515a41547ffSDavid du Colombier dnslog("[%d] take activity from %d", getpid(), ppid); 15164f8f669cSDavid du Colombier req->isslave = 1; /* why not `= getpid()'? */ 15177dd7cddfSDavid du Colombier break; 15187dd7cddfSDavid du Colombier default: 15194f8f669cSDavid du Colombier /* 15204f8f669cSDavid du Colombier * this relies on rfork producing separate, initially-identical 15214f8f669cSDavid du Colombier * stacks, thus giving us two copies of `req', one in each 15224f8f669cSDavid du Colombier * process. 15234f8f669cSDavid du Colombier */ 15246aaebd7dSDavid du Colombier alarm(0); 15257dd7cddfSDavid du Colombier longjmp(req->mret, 1); 15267dd7cddfSDavid du Colombier } 15277dd7cddfSDavid du Colombier } 15287dd7cddfSDavid du Colombier 15297dd7cddfSDavid du Colombier /* 15307dd7cddfSDavid du Colombier * chasing down double free's 15317dd7cddfSDavid du Colombier */ 15327dd7cddfSDavid du Colombier void 15337dd7cddfSDavid du Colombier dncheck(void *p, int dolock) 15347dd7cddfSDavid du Colombier { 15357dd7cddfSDavid du Colombier int i; 15367dd7cddfSDavid du Colombier DN *dp; 15377dd7cddfSDavid du Colombier RR *rp; 15387dd7cddfSDavid du Colombier 15397dd7cddfSDavid du Colombier if(p != nil){ 15407dd7cddfSDavid du Colombier dp = p; 15417dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 15427dd7cddfSDavid du Colombier } 15437dd7cddfSDavid du Colombier 15447dd7cddfSDavid du Colombier if(!testing) 15457dd7cddfSDavid du Colombier return; 15467dd7cddfSDavid du Colombier 15477dd7cddfSDavid du Colombier if(dolock) 15487dd7cddfSDavid du Colombier lock(&dnlock); 15499a747e4fSDavid du Colombier poolcheck(mainmem); 15507dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++) 15517dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){ 15527dd7cddfSDavid du Colombier assert(dp != p); 15537dd7cddfSDavid du Colombier assert(dp->magic == DNmagic); 15547dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 15557dd7cddfSDavid du Colombier assert(rp->magic == RRmagic); 15567dd7cddfSDavid du Colombier assert(rp->cached); 15577dd7cddfSDavid du Colombier assert(rp->owner == dp); 1558225077b0SDavid du Colombier /* also check for duplicate rrs */ 15594f927735SDavid du Colombier if (dolock && rronlist(rp, rp->next)) { 15604f927735SDavid du Colombier dnslog("%R duplicates its next chain " 15614f927735SDavid du Colombier "(%R); aborting", rp, rp->next); 15624f927735SDavid du Colombier abort(); 15634f927735SDavid du Colombier } 15647dd7cddfSDavid du Colombier } 15657dd7cddfSDavid du Colombier } 15667dd7cddfSDavid du Colombier if(dolock) 15677dd7cddfSDavid du Colombier unlock(&dnlock); 15687dd7cddfSDavid du Colombier } 15697dd7cddfSDavid du Colombier 15707dd7cddfSDavid du Colombier static int 15717dd7cddfSDavid du Colombier rrequiv(RR *r1, RR *r2) 15727dd7cddfSDavid du Colombier { 15737dd7cddfSDavid du Colombier return r1->owner == r2->owner 15747dd7cddfSDavid du Colombier && r1->type == r2->type 15757dd7cddfSDavid du Colombier && r1->arg0 == r2->arg0 1576225077b0SDavid du Colombier && r1->arg1 == r2->arg1; 15777dd7cddfSDavid du Colombier } 15787dd7cddfSDavid du Colombier 15797dd7cddfSDavid du Colombier void 15807dd7cddfSDavid du Colombier unique(RR *rp) 15817dd7cddfSDavid du Colombier { 15827dd7cddfSDavid du Colombier RR **l, *nrp; 15837dd7cddfSDavid du Colombier 15847dd7cddfSDavid du Colombier for(; rp; rp = rp->next){ 15857dd7cddfSDavid du Colombier l = &rp->next; 15864f8f669cSDavid du Colombier for(nrp = *l; nrp; nrp = *l) 15877dd7cddfSDavid du Colombier if(rrequiv(rp, nrp)){ 15887dd7cddfSDavid du Colombier *l = nrp->next; 15897dd7cddfSDavid du Colombier rrfree(nrp); 15907dd7cddfSDavid du Colombier } else 15917dd7cddfSDavid du Colombier l = &nrp->next; 15927dd7cddfSDavid du Colombier } 15937dd7cddfSDavid du Colombier } 15947dd7cddfSDavid du Colombier 15957dd7cddfSDavid du Colombier /* 15967dd7cddfSDavid du Colombier * true if second domain is subsumed by the first 15977dd7cddfSDavid du Colombier */ 15987dd7cddfSDavid du Colombier int 15997dd7cddfSDavid du Colombier subsume(char *higher, char *lower) 16007dd7cddfSDavid du Colombier { 16017dd7cddfSDavid du Colombier int hn, ln; 16027dd7cddfSDavid du Colombier 16037dd7cddfSDavid du Colombier ln = strlen(lower); 16047dd7cddfSDavid du Colombier hn = strlen(higher); 16054f8f669cSDavid du Colombier if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 || 16064f8f669cSDavid du Colombier ln > hn && hn != 0 && lower[ln - hn - 1] != '.') 16077dd7cddfSDavid du Colombier return 0; 16087dd7cddfSDavid du Colombier return 1; 16097dd7cddfSDavid du Colombier } 16107dd7cddfSDavid du Colombier 16117dd7cddfSDavid du Colombier /* 16127dd7cddfSDavid du Colombier * randomize the order we return items to provide some 16135d459b5aSDavid du Colombier * load balancing for servers. 16145d459b5aSDavid du Colombier * 16155d459b5aSDavid du Colombier * only randomize the first class of entries 16167dd7cddfSDavid du Colombier */ 16177dd7cddfSDavid du Colombier RR* 16187dd7cddfSDavid du Colombier randomize(RR *rp) 16197dd7cddfSDavid du Colombier { 16205d459b5aSDavid du Colombier RR *first, *last, *x, *base; 16217dd7cddfSDavid du Colombier ulong n; 16227dd7cddfSDavid du Colombier 16237dd7cddfSDavid du Colombier if(rp == nil || rp->next == nil) 16247dd7cddfSDavid du Colombier return rp; 16257dd7cddfSDavid du Colombier 16263cbadd90SDavid du Colombier /* just randomize addresses, mx's and ns's */ 16277dd7cddfSDavid du Colombier for(x = rp; x; x = x->next) 1628adb31a62SDavid du Colombier if(x->type != Ta && x->type != Taaaa && 1629adb31a62SDavid du Colombier x->type != Tmx && x->type != Tns) 16307dd7cddfSDavid du Colombier return rp; 16317dd7cddfSDavid du Colombier 16325d459b5aSDavid du Colombier base = rp; 16335d459b5aSDavid du Colombier 16347dd7cddfSDavid du Colombier n = rand(); 16357dd7cddfSDavid du Colombier last = first = nil; 16367dd7cddfSDavid du Colombier while(rp != nil){ 16375d459b5aSDavid du Colombier /* stop randomizing if we've moved past our class */ 16385d459b5aSDavid du Colombier if(base->auth != rp->auth || base->db != rp->db){ 16395d459b5aSDavid du Colombier last->next = rp; 16405d459b5aSDavid du Colombier break; 16415d459b5aSDavid du Colombier } 16425d459b5aSDavid du Colombier 16437dd7cddfSDavid du Colombier /* unchain */ 16447dd7cddfSDavid du Colombier x = rp; 16457dd7cddfSDavid du Colombier rp = x->next; 16467dd7cddfSDavid du Colombier x->next = nil; 16477dd7cddfSDavid du Colombier 1648225077b0SDavid du Colombier if(n&1){ 16497dd7cddfSDavid du Colombier /* add to tail */ 16507dd7cddfSDavid du Colombier if(last == nil) 16517dd7cddfSDavid du Colombier first = x; 16527dd7cddfSDavid du Colombier else 16537dd7cddfSDavid du Colombier last->next = x; 16547dd7cddfSDavid du Colombier last = x; 16557dd7cddfSDavid du Colombier } else { 16567dd7cddfSDavid du Colombier /* add to head */ 16577dd7cddfSDavid du Colombier if(last == nil) 16587dd7cddfSDavid du Colombier last = x; 16597dd7cddfSDavid du Colombier x->next = first; 16607dd7cddfSDavid du Colombier first = x; 16617dd7cddfSDavid du Colombier } 16627dd7cddfSDavid du Colombier 16637dd7cddfSDavid du Colombier /* reroll the dice */ 16647dd7cddfSDavid du Colombier n >>= 1; 16657dd7cddfSDavid du Colombier } 16663cbadd90SDavid du Colombier 16677dd7cddfSDavid du Colombier return first; 16687dd7cddfSDavid du Colombier } 166959cc4ca5SDavid du Colombier 16709a747e4fSDavid du Colombier static int 16719a747e4fSDavid du Colombier sencodefmt(Fmt *f) 167259cc4ca5SDavid du Colombier { 16734f8f669cSDavid du Colombier int i, len, ilen, rv; 16744f8f669cSDavid du Colombier char *out, *buf; 16759a747e4fSDavid du Colombier uchar *b; 16764f8f669cSDavid du Colombier char obuf[64]; /* rsc optimization */ 167759cc4ca5SDavid du Colombier 16789a747e4fSDavid du Colombier if(!(f->flags&FmtPrec) || f->prec < 1) 16799a747e4fSDavid du Colombier goto error; 16809a747e4fSDavid du Colombier 16819a747e4fSDavid du Colombier b = va_arg(f->args, uchar*); 16829a747e4fSDavid du Colombier if(b == nil) 16839a747e4fSDavid du Colombier goto error; 16849a747e4fSDavid du Colombier 16859a747e4fSDavid du Colombier /* if it's a printable, go for it */ 16869a747e4fSDavid du Colombier len = f->prec; 16879a747e4fSDavid du Colombier for(i = 0; i < len; i++) 16889a747e4fSDavid du Colombier if(!isprint(b[i])) 16899a747e4fSDavid du Colombier break; 16909a747e4fSDavid du Colombier if(i == len){ 16919a747e4fSDavid du Colombier if(len >= sizeof obuf) 16929a747e4fSDavid du Colombier len = sizeof(obuf)-1; 16939a747e4fSDavid du Colombier memmove(obuf, b, len); 16949a747e4fSDavid du Colombier obuf[len] = 0; 16959a747e4fSDavid du Colombier fmtstrcpy(f, obuf); 16969a747e4fSDavid du Colombier return 0; 169759cc4ca5SDavid du Colombier } 169859cc4ca5SDavid du Colombier 16999a747e4fSDavid du Colombier ilen = f->prec; 17009a747e4fSDavid du Colombier f->prec = 0; 17019a747e4fSDavid du Colombier f->flags &= ~FmtPrec; 17029a747e4fSDavid du Colombier switch(f->r){ 17039a747e4fSDavid du Colombier case '<': 17049a747e4fSDavid du Colombier len = (8*ilen+4)/5 + 3; 17059a747e4fSDavid du Colombier break; 17069a747e4fSDavid du Colombier case '[': 17079a747e4fSDavid du Colombier len = (8*ilen+5)/6 + 4; 17089a747e4fSDavid du Colombier break; 17099a747e4fSDavid du Colombier case 'H': 17109a747e4fSDavid du Colombier len = 2*ilen + 1; 17119a747e4fSDavid du Colombier break; 17129a747e4fSDavid du Colombier default: 17139a747e4fSDavid du Colombier goto error; 17149a747e4fSDavid du Colombier } 171559cc4ca5SDavid du Colombier 17169a747e4fSDavid du Colombier if(len > sizeof(obuf)){ 17179a747e4fSDavid du Colombier buf = malloc(len); 17189a747e4fSDavid du Colombier if(buf == nil) 17199a747e4fSDavid du Colombier goto error; 17209a747e4fSDavid du Colombier } else 17219a747e4fSDavid du Colombier buf = obuf; 17229a747e4fSDavid du Colombier 17234f8f669cSDavid du Colombier /* convert */ 17249a747e4fSDavid du Colombier out = buf; 17259a747e4fSDavid du Colombier switch(f->r){ 17269a747e4fSDavid du Colombier case '<': 17279a747e4fSDavid du Colombier rv = enc32(out, len, b, ilen); 17289a747e4fSDavid du Colombier break; 17299a747e4fSDavid du Colombier case '[': 17309a747e4fSDavid du Colombier rv = enc64(out, len, b, ilen); 17319a747e4fSDavid du Colombier break; 17329a747e4fSDavid du Colombier case 'H': 17339a747e4fSDavid du Colombier rv = enc16(out, len, b, ilen); 17349a747e4fSDavid du Colombier break; 17359a747e4fSDavid du Colombier default: 17369a747e4fSDavid du Colombier rv = -1; 17379a747e4fSDavid du Colombier break; 17389a747e4fSDavid du Colombier } 17399a747e4fSDavid du Colombier if(rv < 0) 17409a747e4fSDavid du Colombier goto error; 17419a747e4fSDavid du Colombier 17429a747e4fSDavid du Colombier fmtstrcpy(f, buf); 17439a747e4fSDavid du Colombier if(buf != obuf) 17449a747e4fSDavid du Colombier free(buf); 17459a747e4fSDavid du Colombier return 0; 17469a747e4fSDavid du Colombier 17479a747e4fSDavid du Colombier error: 17489a747e4fSDavid du Colombier return fmtstrcpy(f, "<encodefmt>"); 17499a747e4fSDavid du Colombier } 17509a747e4fSDavid du Colombier 17519a747e4fSDavid du Colombier void* 17529a747e4fSDavid du Colombier emalloc(int size) 17539a747e4fSDavid du Colombier { 17549a747e4fSDavid du Colombier char *x; 17559a747e4fSDavid du Colombier 17569a747e4fSDavid du Colombier x = mallocz(size, 1); 17579a747e4fSDavid du Colombier if(x == nil) 17589a747e4fSDavid du Colombier abort(); 175934f77ae3SDavid du Colombier setmalloctag(x, getcallerpc(&size)); 17609a747e4fSDavid du Colombier return x; 17619a747e4fSDavid du Colombier } 17629a747e4fSDavid du Colombier 17639a747e4fSDavid du Colombier char* 17649a747e4fSDavid du Colombier estrdup(char *s) 17659a747e4fSDavid du Colombier { 17669a747e4fSDavid du Colombier int size; 17679a747e4fSDavid du Colombier char *p; 17689a747e4fSDavid du Colombier 17699a747e4fSDavid du Colombier size = strlen(s)+1; 17709a747e4fSDavid du Colombier p = mallocz(size, 0); 17719a747e4fSDavid du Colombier if(p == nil) 17729a747e4fSDavid du Colombier abort(); 17739a747e4fSDavid du Colombier memmove(p, s, size); 177434f77ae3SDavid du Colombier setmalloctag(p, getcallerpc(&s)); 17759a747e4fSDavid du Colombier return p; 177659cc4ca5SDavid du Colombier } 17773ff48bf5SDavid du Colombier 17783ff48bf5SDavid du Colombier /* 17793ff48bf5SDavid du Colombier * create a pointer record 17803ff48bf5SDavid du Colombier */ 17813ff48bf5SDavid du Colombier static RR* 17823ff48bf5SDavid du Colombier mkptr(DN *dp, char *ptr, ulong ttl) 17833ff48bf5SDavid du Colombier { 17843ff48bf5SDavid du Colombier DN *ipdp; 17853ff48bf5SDavid du Colombier RR *rp; 17863ff48bf5SDavid du Colombier 17873ff48bf5SDavid du Colombier ipdp = dnlookup(ptr, Cin, 1); 17883ff48bf5SDavid du Colombier 17893ff48bf5SDavid du Colombier rp = rralloc(Tptr); 17903ff48bf5SDavid du Colombier rp->ptr = dp; 17913ff48bf5SDavid du Colombier rp->owner = ipdp; 17923ff48bf5SDavid du Colombier rp->db = 1; 17933ff48bf5SDavid du Colombier if(ttl) 17943ff48bf5SDavid du Colombier rp->ttl = ttl; 17953ff48bf5SDavid du Colombier return rp; 17963ff48bf5SDavid du Colombier } 17973ff48bf5SDavid du Colombier 179853874d13SDavid du Colombier void bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes); 179953874d13SDavid du Colombier 18003ff48bf5SDavid du Colombier /* 18013ff48bf5SDavid du Colombier * look for all ip addresses in this network and make 18023ff48bf5SDavid du Colombier * pointer records for them. 18033ff48bf5SDavid du Colombier */ 18043ff48bf5SDavid du Colombier void 180553874d13SDavid du Colombier dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl) 18063ff48bf5SDavid du Colombier { 180753874d13SDavid du Colombier int i, j, len; 18084f8f669cSDavid du Colombier char *p, *e; 18094f8f669cSDavid du Colombier char ptr[Domlen]; 181053874d13SDavid du Colombier uchar *ipp; 18114f8f669cSDavid du Colombier uchar ip[IPaddrlen], nnet[IPaddrlen]; 181253874d13SDavid du Colombier uchar nibip[IPaddrlen*2]; 18133ff48bf5SDavid du Colombier DN *dp; 18143ff48bf5SDavid du Colombier RR *rp, *nrp, *first, **l; 18153ff48bf5SDavid du Colombier 18163ff48bf5SDavid du Colombier l = &first; 18173ff48bf5SDavid du Colombier first = nil; 18184f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++) 18194f8f669cSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) 18203ff48bf5SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){ 182153874d13SDavid du Colombier if(rp->type != forwtype || rp->negative) 18223ff48bf5SDavid du Colombier continue; 18233ff48bf5SDavid du Colombier parseip(ip, rp->ip->name); 18243ff48bf5SDavid du Colombier maskip(ip, mask, nnet); 18253ff48bf5SDavid du Colombier if(ipcmp(net, nnet) != 0) 18263ff48bf5SDavid du Colombier continue; 182753874d13SDavid du Colombier 182853874d13SDavid du Colombier ipp = ip; 182953874d13SDavid du Colombier len = IPaddrlen; 183053874d13SDavid du Colombier if (forwtype == Taaaa) { 183153874d13SDavid du Colombier bytes2nibbles(nibip, ip, IPaddrlen); 183253874d13SDavid du Colombier ipp = nibip; 183353874d13SDavid du Colombier len = 2*IPaddrlen; 183453874d13SDavid du Colombier } 183553874d13SDavid du Colombier 18363ff48bf5SDavid du Colombier p = ptr; 18373ff48bf5SDavid du Colombier e = ptr+sizeof(ptr); 183853874d13SDavid du Colombier for(j = len - 1; j >= len - subdoms; j--) 183953874d13SDavid du Colombier p = seprint(p, e, (forwtype == Ta? 184053874d13SDavid du Colombier "%d.": "%x."), ipp[j]); 18413ff48bf5SDavid du Colombier seprint(p, e, "%s", dom); 184253874d13SDavid du Colombier 18433ff48bf5SDavid du Colombier nrp = mkptr(dp, ptr, ttl); 18443ff48bf5SDavid du Colombier *l = nrp; 18453ff48bf5SDavid du Colombier l = &nrp->next; 18463ff48bf5SDavid du Colombier } 18473ff48bf5SDavid du Colombier 18483ff48bf5SDavid du Colombier for(rp = first; rp != nil; rp = nrp){ 18493ff48bf5SDavid du Colombier nrp = rp->next; 18503ff48bf5SDavid du Colombier rp->next = nil; 18516dc4800dSDavid du Colombier rrattach(rp, Authoritative); 18523ff48bf5SDavid du Colombier } 18533ff48bf5SDavid du Colombier } 1854dc5a79c1SDavid du Colombier 1855dc5a79c1SDavid du Colombier void 1856dc5a79c1SDavid du Colombier addserver(Server **l, char *name) 1857dc5a79c1SDavid du Colombier { 1858dc5a79c1SDavid du Colombier Server *s; 1859dc5a79c1SDavid du Colombier 1860dc5a79c1SDavid du Colombier while(*l) 1861dc5a79c1SDavid du Colombier l = &(*l)->next; 1862dc5a79c1SDavid du Colombier s = malloc(sizeof(Server)+strlen(name)+1); 1863dc5a79c1SDavid du Colombier if(s == nil) 1864dc5a79c1SDavid du Colombier return; 1865dc5a79c1SDavid du Colombier s->name = (char*)(s+1); 1866dc5a79c1SDavid du Colombier strcpy(s->name, name); 1867dc5a79c1SDavid du Colombier s->next = nil; 1868dc5a79c1SDavid du Colombier *l = s; 1869dc5a79c1SDavid du Colombier } 1870dc5a79c1SDavid du Colombier 1871dc5a79c1SDavid du Colombier Server* 1872dc5a79c1SDavid du Colombier copyserverlist(Server *s) 1873dc5a79c1SDavid du Colombier { 1874dc5a79c1SDavid du Colombier Server *ns; 1875dc5a79c1SDavid du Colombier 1876dc5a79c1SDavid du Colombier for(ns = nil; s != nil; s = s->next) 1877dc5a79c1SDavid du Colombier addserver(&ns, s->name); 1878dc5a79c1SDavid du Colombier return ns; 1879dc5a79c1SDavid du Colombier } 1880b751ae26SDavid du Colombier 1881b751ae26SDavid du Colombier 1882b751ae26SDavid du Colombier /* from here down is copied to ip/snoopy/dns.c periodically to update it */ 1883b751ae26SDavid du Colombier 1884b751ae26SDavid du Colombier /* 1885b751ae26SDavid du Colombier * convert an integer RR type to it's ascii name 1886b751ae26SDavid du Colombier */ 1887b751ae26SDavid du Colombier char* 1888b751ae26SDavid du Colombier rrname(int type, char *buf, int len) 1889b751ae26SDavid du Colombier { 1890b751ae26SDavid du Colombier char *t; 1891b751ae26SDavid du Colombier 1892b751ae26SDavid du Colombier t = nil; 1893b751ae26SDavid du Colombier if(type >= 0 && type <= Tall) 1894b751ae26SDavid du Colombier t = rrtname[type]; 1895b751ae26SDavid du Colombier if(t==nil){ 1896b751ae26SDavid du Colombier snprint(buf, len, "%d", type); 1897b751ae26SDavid du Colombier t = buf; 1898b751ae26SDavid du Colombier } 1899b751ae26SDavid du Colombier return t; 1900b751ae26SDavid du Colombier } 1901b751ae26SDavid du Colombier 1902b751ae26SDavid du Colombier /* 1903b751ae26SDavid du Colombier * free a list of resource records and any related structs 1904b751ae26SDavid du Colombier */ 1905b751ae26SDavid du Colombier void 1906b751ae26SDavid du Colombier rrfreelist(RR *rp) 1907b751ae26SDavid du Colombier { 1908b751ae26SDavid du Colombier RR *next; 1909b751ae26SDavid du Colombier 1910b751ae26SDavid du Colombier for(; rp; rp = next){ 1911b751ae26SDavid du Colombier next = rp->next; 1912b751ae26SDavid du Colombier rrfree(rp); 1913b751ae26SDavid du Colombier } 1914b751ae26SDavid du Colombier } 1915b751ae26SDavid du Colombier 1916b751ae26SDavid du Colombier void 1917b751ae26SDavid du Colombier freeserverlist(Server *s) 1918b751ae26SDavid du Colombier { 1919b751ae26SDavid du Colombier Server *next; 1920b751ae26SDavid du Colombier 1921b751ae26SDavid du Colombier for(; s != nil; s = next){ 1922b751ae26SDavid du Colombier next = s->next; 1923b751ae26SDavid du Colombier free(s); 1924b751ae26SDavid du Colombier } 1925b751ae26SDavid du Colombier } 1926b751ae26SDavid du Colombier 1927b751ae26SDavid du Colombier /* 1928b751ae26SDavid du Colombier * allocate a resource record of a given type 1929b751ae26SDavid du Colombier */ 1930b751ae26SDavid du Colombier RR* 1931b751ae26SDavid du Colombier rralloc(int type) 1932b751ae26SDavid du Colombier { 1933b751ae26SDavid du Colombier RR *rp; 1934b751ae26SDavid du Colombier 1935b751ae26SDavid du Colombier rp = emalloc(sizeof(*rp)); 1936b751ae26SDavid du Colombier rp->magic = RRmagic; 1937b751ae26SDavid du Colombier rp->pc = getcallerpc(&type); 1938b751ae26SDavid du Colombier rp->type = type; 1939fd87a217SDavid du Colombier if (rp->type != type) 1940fd87a217SDavid du Colombier dnslog("rralloc: bogus type %d", type); 1941b751ae26SDavid du Colombier setmalloctag(rp, rp->pc); 1942b751ae26SDavid du Colombier switch(type){ 1943b751ae26SDavid du Colombier case Tsoa: 1944b751ae26SDavid du Colombier rp->soa = emalloc(sizeof(*rp->soa)); 1945b751ae26SDavid du Colombier rp->soa->slaves = nil; 1946b751ae26SDavid du Colombier setmalloctag(rp->soa, rp->pc); 1947b751ae26SDavid du Colombier break; 1948b751ae26SDavid du Colombier case Tsrv: 1949b751ae26SDavid du Colombier rp->srv = emalloc(sizeof(*rp->srv)); 1950b751ae26SDavid du Colombier setmalloctag(rp->srv, rp->pc); 1951b751ae26SDavid du Colombier break; 1952b751ae26SDavid du Colombier case Tkey: 1953b751ae26SDavid du Colombier rp->key = emalloc(sizeof(*rp->key)); 1954b751ae26SDavid du Colombier setmalloctag(rp->key, rp->pc); 1955b751ae26SDavid du Colombier break; 1956b751ae26SDavid du Colombier case Tcert: 1957b751ae26SDavid du Colombier rp->cert = emalloc(sizeof(*rp->cert)); 1958b751ae26SDavid du Colombier setmalloctag(rp->cert, rp->pc); 1959b751ae26SDavid du Colombier break; 1960b751ae26SDavid du Colombier case Tsig: 1961b751ae26SDavid du Colombier rp->sig = emalloc(sizeof(*rp->sig)); 1962b751ae26SDavid du Colombier setmalloctag(rp->sig, rp->pc); 1963b751ae26SDavid du Colombier break; 1964b751ae26SDavid du Colombier case Tnull: 1965b751ae26SDavid du Colombier rp->null = emalloc(sizeof(*rp->null)); 1966b751ae26SDavid du Colombier setmalloctag(rp->null, rp->pc); 1967b751ae26SDavid du Colombier break; 1968b751ae26SDavid du Colombier } 1969b751ae26SDavid du Colombier rp->ttl = 0; 1970b751ae26SDavid du Colombier rp->expire = 0; 1971b751ae26SDavid du Colombier rp->next = 0; 1972b751ae26SDavid du Colombier return rp; 1973b751ae26SDavid du Colombier } 1974b751ae26SDavid du Colombier 1975b751ae26SDavid du Colombier /* 1976b751ae26SDavid du Colombier * free a resource record and any related structs 1977b751ae26SDavid du Colombier */ 1978b751ae26SDavid du Colombier void 1979b751ae26SDavid du Colombier rrfree(RR *rp) 1980b751ae26SDavid du Colombier { 1981b751ae26SDavid du Colombier DN *dp; 1982b751ae26SDavid du Colombier RR *nrp; 1983b751ae26SDavid du Colombier Txt *t; 1984b751ae26SDavid du Colombier 1985530fef66SDavid du Colombier assert(rp->magic == RRmagic); 1986b751ae26SDavid du Colombier assert(!rp->cached); 1987b751ae26SDavid du Colombier 1988b751ae26SDavid du Colombier dp = rp->owner; 1989b751ae26SDavid du Colombier if(dp){ 1990b751ae26SDavid du Colombier assert(dp->magic == DNmagic); 1991b751ae26SDavid du Colombier for(nrp = dp->rr; nrp; nrp = nrp->next) 1992b751ae26SDavid du Colombier assert(nrp != rp); /* "rrfree of live rr" */ 1993b751ae26SDavid du Colombier } 1994b751ae26SDavid du Colombier 1995b751ae26SDavid du Colombier switch(rp->type){ 1996b751ae26SDavid du Colombier case Tsoa: 1997b751ae26SDavid du Colombier freeserverlist(rp->soa->slaves); 1998b751ae26SDavid du Colombier memset(rp->soa, 0, sizeof *rp->soa); /* cause trouble */ 1999b751ae26SDavid du Colombier free(rp->soa); 2000b751ae26SDavid du Colombier break; 2001b751ae26SDavid du Colombier case Tsrv: 2002b751ae26SDavid du Colombier memset(rp->srv, 0, sizeof *rp->srv); /* cause trouble */ 2003b751ae26SDavid du Colombier free(rp->srv); 2004b751ae26SDavid du Colombier break; 2005b751ae26SDavid du Colombier case Tkey: 2006b751ae26SDavid du Colombier free(rp->key->data); 2007b751ae26SDavid du Colombier memset(rp->key, 0, sizeof *rp->key); /* cause trouble */ 2008b751ae26SDavid du Colombier free(rp->key); 2009b751ae26SDavid du Colombier break; 2010b751ae26SDavid du Colombier case Tcert: 2011b751ae26SDavid du Colombier free(rp->cert->data); 2012b751ae26SDavid du Colombier memset(rp->cert, 0, sizeof *rp->cert); /* cause trouble */ 2013b751ae26SDavid du Colombier free(rp->cert); 2014b751ae26SDavid du Colombier break; 2015b751ae26SDavid du Colombier case Tsig: 2016b751ae26SDavid du Colombier free(rp->sig->data); 2017b751ae26SDavid du Colombier memset(rp->sig, 0, sizeof *rp->sig); /* cause trouble */ 2018b751ae26SDavid du Colombier free(rp->sig); 2019b751ae26SDavid du Colombier break; 2020b751ae26SDavid du Colombier case Tnull: 2021b751ae26SDavid du Colombier free(rp->null->data); 2022b751ae26SDavid du Colombier memset(rp->null, 0, sizeof *rp->null); /* cause trouble */ 2023b751ae26SDavid du Colombier free(rp->null); 2024b751ae26SDavid du Colombier break; 2025b751ae26SDavid du Colombier case Ttxt: 2026b751ae26SDavid du Colombier while(rp->txt != nil){ 2027b751ae26SDavid du Colombier t = rp->txt; 2028b751ae26SDavid du Colombier rp->txt = t->next; 2029b751ae26SDavid du Colombier free(t->p); 2030b751ae26SDavid du Colombier memset(t, 0, sizeof *t); /* cause trouble */ 2031b751ae26SDavid du Colombier free(t); 2032b751ae26SDavid du Colombier } 2033b751ae26SDavid du Colombier break; 2034b751ae26SDavid du Colombier } 2035b751ae26SDavid du Colombier 2036b751ae26SDavid du Colombier rp->magic = ~rp->magic; 2037b751ae26SDavid du Colombier memset(rp, 0, sizeof *rp); /* cause trouble */ 2038b751ae26SDavid du Colombier free(rp); 2039b751ae26SDavid du Colombier } 2040