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 *
13409a7d08SDavid du Colombier * aging corrupts the cache, so raise the trigger to avoid it.
1421abd8f2SDavid du Colombier */
1521abd8f2SDavid du Colombier enum {
161a8a6b0dSDavid du Colombier Deftarget = 1<<30, /* effectively disable aging */
171a8a6b0dSDavid du Colombier Minage = 1<<30,
181a8a6b0dSDavid du Colombier Defagefreq = 1<<30, /* age names this often (seconds) */
191a8a6b0dSDavid du Colombier
201a8a6b0dSDavid du Colombier /* these settings will trigger frequent aging */
211a8a6b0dSDavid du Colombier // Deftarget = 4000,
221a8a6b0dSDavid du Colombier // Minage = 5*60,
231a8a6b0dSDavid du Colombier // Defagefreq = 15*60, /* age names this often (seconds) */
24409a7d08SDavid du Colombier
25409a7d08SDavid du Colombier Restartmins = 0,
26409a7d08SDavid du Colombier // Restartmins = 600,
2781730632SDavid du Colombier };
2881730632SDavid du Colombier
293e12c5d1SDavid du Colombier /*
303e12c5d1SDavid du Colombier * Hash table for domain names. The hash is based only on the
313e12c5d1SDavid du Colombier * first element of the domain name.
323e12c5d1SDavid du Colombier */
337dd7cddfSDavid du Colombier DN *ht[HTLEN];
343e12c5d1SDavid du Colombier
354f8f669cSDavid du Colombier static struct {
367dd7cddfSDavid du Colombier Lock;
377dd7cddfSDavid du Colombier ulong names; /* names allocated */
387dd7cddfSDavid du Colombier ulong oldest; /* longest we'll leave a name around */
397dd7cddfSDavid du Colombier int active;
407dd7cddfSDavid du Colombier int mutex;
414f8f669cSDavid du Colombier ushort id; /* same size as in packet */
427dd7cddfSDavid du Colombier } dnvars;
433e12c5d1SDavid du Colombier
443e12c5d1SDavid du Colombier /* names of RR types */
453e12c5d1SDavid du Colombier char *rrtname[] =
463e12c5d1SDavid du Colombier {
473e12c5d1SDavid du Colombier [Ta] "ip",
483e12c5d1SDavid du Colombier [Tns] "ns",
493e12c5d1SDavid du Colombier [Tmd] "md",
503e12c5d1SDavid du Colombier [Tmf] "mf",
513e12c5d1SDavid du Colombier [Tcname] "cname",
523e12c5d1SDavid du Colombier [Tsoa] "soa",
533e12c5d1SDavid du Colombier [Tmb] "mb",
543e12c5d1SDavid du Colombier [Tmg] "mg",
553e12c5d1SDavid du Colombier [Tmr] "mr",
563e12c5d1SDavid du Colombier [Tnull] "null",
573e12c5d1SDavid du Colombier [Twks] "wks",
583e12c5d1SDavid du Colombier [Tptr] "ptr",
593e12c5d1SDavid du Colombier [Thinfo] "hinfo",
603e12c5d1SDavid du Colombier [Tminfo] "minfo",
613e12c5d1SDavid du Colombier [Tmx] "mx",
623e12c5d1SDavid du Colombier [Ttxt] "txt",
637dd7cddfSDavid du Colombier [Trp] "rp",
64ab3dc52fSDavid du Colombier [Tafsdb] "afsdb",
65ab3dc52fSDavid du Colombier [Tx25] "x.25",
66ab3dc52fSDavid du Colombier [Tisdn] "isdn",
67ab3dc52fSDavid du Colombier [Trt] "rt",
68ab3dc52fSDavid du Colombier [Tnsap] "nsap",
69ab3dc52fSDavid du Colombier [Tnsapptr] "nsap-ptr",
707dd7cddfSDavid du Colombier [Tsig] "sig",
71ab3dc52fSDavid du Colombier [Tkey] "key",
72ab3dc52fSDavid du Colombier [Tpx] "px",
73ab3dc52fSDavid du Colombier [Tgpos] "gpos",
745d459b5aSDavid du Colombier [Taaaa] "ipv6",
75ab3dc52fSDavid du Colombier [Tloc] "loc",
76ab3dc52fSDavid du Colombier [Tnxt] "nxt",
77ab3dc52fSDavid du Colombier [Teid] "eid",
78ab3dc52fSDavid du Colombier [Tnimloc] "nimrod",
79ab3dc52fSDavid du Colombier [Tsrv] "srv",
80ab3dc52fSDavid du Colombier [Tatma] "atma",
81ab3dc52fSDavid du Colombier [Tnaptr] "naptr",
82ab3dc52fSDavid du Colombier [Tkx] "kx",
83ab3dc52fSDavid du Colombier [Tcert] "cert",
84ab3dc52fSDavid du Colombier [Ta6] "a6",
85ab3dc52fSDavid du Colombier [Tdname] "dname",
86ab3dc52fSDavid du Colombier [Tsink] "sink",
87ab3dc52fSDavid du Colombier [Topt] "opt",
88ab3dc52fSDavid du Colombier [Tapl] "apl",
89ab3dc52fSDavid du Colombier [Tds] "ds",
90ab3dc52fSDavid du Colombier [Tsshfp] "sshfp",
91ab3dc52fSDavid du Colombier [Tipseckey] "ipseckey",
92ab3dc52fSDavid du Colombier [Trrsig] "rrsig",
93ab3dc52fSDavid du Colombier [Tnsec] "nsec",
94ab3dc52fSDavid du Colombier [Tdnskey] "dnskey",
95ab3dc52fSDavid du Colombier [Tspf] "spf",
96ab3dc52fSDavid du Colombier [Tuinfo] "uinfo",
97ab3dc52fSDavid du Colombier [Tuid] "uid",
98ab3dc52fSDavid du Colombier [Tgid] "gid",
99ab3dc52fSDavid du Colombier [Tunspec] "unspec",
100ab3dc52fSDavid du Colombier [Ttkey] "tkey",
101ab3dc52fSDavid du Colombier [Ttsig] "tsig",
1027dd7cddfSDavid du Colombier [Tixfr] "ixfr",
1037dd7cddfSDavid du Colombier [Taxfr] "axfr",
104ab3dc52fSDavid du Colombier [Tmailb] "mailb",
105ab3dc52fSDavid du Colombier [Tmaila] "maila",
106219b2ee8SDavid du Colombier [Tall] "all",
1073e12c5d1SDavid du Colombier 0,
1083e12c5d1SDavid du Colombier };
1093e12c5d1SDavid du Colombier
1103e12c5d1SDavid du Colombier /* names of response codes */
111271b8d73SDavid du Colombier char *rname[Rmask+1] =
1123e12c5d1SDavid du Colombier {
1133e12c5d1SDavid du Colombier [Rok] "ok",
1143e12c5d1SDavid du Colombier [Rformat] "format error",
1153e12c5d1SDavid du Colombier [Rserver] "server failure",
1163e12c5d1SDavid du Colombier [Rname] "bad name",
1173e12c5d1SDavid du Colombier [Runimplimented] "unimplemented",
1183e12c5d1SDavid du Colombier [Rrefused] "we don't like you",
119ab3dc52fSDavid du Colombier [Ryxdomain] "name should not exist",
120ab3dc52fSDavid du Colombier [Ryxrrset] "rr set should not exist",
121ab3dc52fSDavid du Colombier [Rnxrrset] "rr set should exist",
122ab3dc52fSDavid du Colombier [Rnotauth] "not authorative",
123ab3dc52fSDavid du Colombier [Rnotzone] "not in zone",
124ab3dc52fSDavid du Colombier [Rbadvers] "bad opt version",
125ab3dc52fSDavid du Colombier /* [Rbadsig] "bad signature", */
126ab3dc52fSDavid du Colombier [Rbadkey] "bad key",
127ab3dc52fSDavid du Colombier [Rbadtime] "bad signature time",
128ab3dc52fSDavid du Colombier [Rbadmode] "bad mode",
129ab3dc52fSDavid du Colombier [Rbadname] "duplicate key name",
130ab3dc52fSDavid du Colombier [Rbadalg] "bad algorithm",
1313e12c5d1SDavid du Colombier };
1324f8f669cSDavid du Colombier unsigned nrname = nelem(rname);
1333e12c5d1SDavid du Colombier
1343e12c5d1SDavid du Colombier /* names of op codes */
1353e12c5d1SDavid du Colombier char *opname[] =
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier [Oquery] "query",
138ab3dc52fSDavid du Colombier [Oinverse] "inverse query (retired)",
1393e12c5d1SDavid du Colombier [Ostatus] "status",
140ab3dc52fSDavid du Colombier [Oupdate] "update",
1413e12c5d1SDavid du Colombier };
1423e12c5d1SDavid du Colombier
14321abd8f2SDavid du Colombier ulong target = Deftarget;
14427acba7cSDavid du Colombier ulong start;
145bd389b36SDavid du Colombier Lock dnlock;
1463e12c5d1SDavid du Colombier
147f46c709fSDavid du Colombier static ulong agefreq = Defagefreq;
148f46c709fSDavid du Colombier
149225077b0SDavid du Colombier static int rrequiv(RR *r1, RR *r2);
1509a747e4fSDavid du Colombier static int sencodefmt(Fmt*);
15159cc4ca5SDavid du Colombier
152254fe3d3SDavid du Colombier static void
ding(void *,char * msg)153254fe3d3SDavid du Colombier ding(void*, char *msg)
154254fe3d3SDavid du Colombier {
155254fe3d3SDavid du Colombier if(strstr(msg, "alarm") != nil) {
156254fe3d3SDavid du Colombier stats.alarms++;
157254fe3d3SDavid du Colombier noted(NCONT); /* resume with system call error */
158254fe3d3SDavid du Colombier } else
159254fe3d3SDavid du Colombier noted(NDFLT); /* die */
160254fe3d3SDavid du Colombier }
161254fe3d3SDavid du Colombier
1623e12c5d1SDavid du Colombier void
dninit(void)1633e12c5d1SDavid du Colombier dninit(void)
1643e12c5d1SDavid du Colombier {
1659a747e4fSDavid du Colombier fmtinstall('E', eipfmt);
1669a747e4fSDavid du Colombier fmtinstall('I', eipfmt);
1679a747e4fSDavid du Colombier fmtinstall('V', eipfmt);
1689a747e4fSDavid du Colombier fmtinstall('R', rrfmt);
1699a747e4fSDavid du Colombier fmtinstall('Q', rravfmt);
1709a747e4fSDavid du Colombier fmtinstall('H', sencodefmt);
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier dnvars.oldest = maxage;
1737dd7cddfSDavid du Colombier dnvars.names = 0;
1744f8f669cSDavid du Colombier dnvars.id = truerand(); /* don't start with same id every time */
175254fe3d3SDavid du Colombier
176254fe3d3SDavid du Colombier notify(ding);
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier
1793e12c5d1SDavid du Colombier /*
1803e12c5d1SDavid du Colombier * hash for a domain name
1813e12c5d1SDavid du Colombier */
1823e12c5d1SDavid du Colombier static ulong
dnhash(char * name)1833e12c5d1SDavid du Colombier dnhash(char *name)
1843e12c5d1SDavid du Colombier {
1853e12c5d1SDavid du Colombier ulong hash;
1863e12c5d1SDavid du Colombier uchar *val = (uchar*)name;
1873e12c5d1SDavid du Colombier
1887dd7cddfSDavid du Colombier for(hash = 0; *val; val++)
1894f8f669cSDavid du Colombier hash = hash*13 + tolower(*val)-'a';
1903e12c5d1SDavid du Colombier return hash % HTLEN;
1913e12c5d1SDavid du Colombier }
1923e12c5d1SDavid du Colombier
1933e12c5d1SDavid du Colombier /*
1943e12c5d1SDavid du Colombier * lookup a symbol. if enter is not zero and the name is
1953e12c5d1SDavid du Colombier * not found, create it.
1963e12c5d1SDavid du Colombier */
1973e12c5d1SDavid du Colombier DN*
dnlookup(char * name,int class,int enter)1983e12c5d1SDavid du Colombier dnlookup(char *name, int class, int enter)
1993e12c5d1SDavid du Colombier {
2003e12c5d1SDavid du Colombier DN **l;
2013e12c5d1SDavid du Colombier DN *dp;
2023e12c5d1SDavid du Colombier
2033ff48bf5SDavid du Colombier l = &ht[dnhash(name)];
204bd389b36SDavid du Colombier lock(&dnlock);
2053e12c5d1SDavid du Colombier for(dp = *l; dp; dp = dp->next) {
2067dd7cddfSDavid du Colombier assert(dp->magic == DNmagic);
2073ff48bf5SDavid du Colombier if(dp->class == class && cistrcmp(dp->name, name) == 0){
2087dd7cddfSDavid du Colombier dp->referenced = now;
209bd389b36SDavid du Colombier unlock(&dnlock);
2103e12c5d1SDavid du Colombier return dp;
2113e12c5d1SDavid du Colombier }
2123e12c5d1SDavid du Colombier l = &dp->next;
2133e12c5d1SDavid du Colombier }
2144f8f669cSDavid du Colombier
2154f8f669cSDavid du Colombier if(!enter){
216bd389b36SDavid du Colombier unlock(&dnlock);
2173e12c5d1SDavid du Colombier return 0;
2183e12c5d1SDavid du Colombier }
2197dd7cddfSDavid du Colombier dnvars.names++;
2209a747e4fSDavid du Colombier dp = emalloc(sizeof(*dp));
2217dd7cddfSDavid du Colombier dp->magic = DNmagic;
2229a747e4fSDavid du Colombier dp->name = estrdup(name);
2234f8f669cSDavid du Colombier assert(dp->name != nil);
2243e12c5d1SDavid du Colombier dp->class = class;
2253e12c5d1SDavid du Colombier dp->rr = 0;
2267dd7cddfSDavid du Colombier dp->referenced = now;
227530fef66SDavid du Colombier /* add new DN to tail of the hash list. *l points to last next ptr. */
228530fef66SDavid du Colombier dp->next = nil;
2293e12c5d1SDavid du Colombier *l = dp;
230bd389b36SDavid du Colombier unlock(&dnlock);
2317dd7cddfSDavid du Colombier
2323e12c5d1SDavid du Colombier return dp;
2333e12c5d1SDavid du Colombier }
2343e12c5d1SDavid du Colombier
235225077b0SDavid du Colombier static int
rrsame(RR * rr1,RR * rr2)236225077b0SDavid du Colombier rrsame(RR *rr1, RR *rr2)
237225077b0SDavid du Colombier {
238225077b0SDavid du Colombier return rr1 == rr2 || rr2 && rrequiv(rr1, rr2) &&
239225077b0SDavid du Colombier rr1->db == rr2->db && rr1->auth == rr2->auth;
240225077b0SDavid du Colombier }
241225077b0SDavid du Colombier
242225077b0SDavid du Colombier static int
rronlist(RR * rp,RR * lp)243225077b0SDavid du Colombier rronlist(RR *rp, RR *lp)
244225077b0SDavid du Colombier {
245225077b0SDavid du Colombier for(; lp; lp = lp->next)
2464f927735SDavid du Colombier if (rrsame(lp, rp))
247225077b0SDavid du Colombier return 1;
248225077b0SDavid du Colombier return 0;
249225077b0SDavid du Colombier }
250225077b0SDavid du Colombier
2513e12c5d1SDavid du Colombier /*
2524f927735SDavid du Colombier * dump the stats
253219b2ee8SDavid du Colombier */
254219b2ee8SDavid du Colombier void
dnstats(char * file)2554f927735SDavid du Colombier dnstats(char *file)
256219b2ee8SDavid du Colombier {
257219b2ee8SDavid du Colombier int i, fd;
258219b2ee8SDavid du Colombier
25921abd8f2SDavid du Colombier fd = create(file, OWRITE, 0666);
260219b2ee8SDavid du Colombier if(fd < 0)
261219b2ee8SDavid du Colombier return;
262a41547ffSDavid du Colombier
263a41547ffSDavid du Colombier qlock(&stats);
2644f927735SDavid du Colombier fprint(fd, "# system %s\n", sysname());
265f46c709fSDavid du Colombier fprint(fd, "# slave procs high-water mark\t%lud\n", stats.slavehiwat);
266f46c709fSDavid du Colombier fprint(fd, "# queries received by 9p\t%lud\n", stats.qrecvd9p);
267f46c709fSDavid du Colombier fprint(fd, "# queries received by udp\t%lud\n", stats.qrecvdudp);
268f46c709fSDavid du Colombier fprint(fd, "# queries answered from memory\t%lud\n", stats.answinmem);
269f46c709fSDavid du Colombier fprint(fd, "# queries sent by udp\t%lud\n", stats.qsent);
270a41547ffSDavid du Colombier for (i = 0; i < nelem(stats.under10ths); i++)
271a41547ffSDavid du Colombier if (stats.under10ths[i] || i == nelem(stats.under10ths) - 1)
272f46c709fSDavid du Colombier fprint(fd, "# responses arriving within %.1f s.\t%lud\n",
273a41547ffSDavid du Colombier (double)(i+1)/10, stats.under10ths[i]);
274f46c709fSDavid du Colombier fprint(fd, "\n# queries sent & timed-out\t%lud\n", stats.tmout);
275f46c709fSDavid du Colombier fprint(fd, "# cname queries timed-out\t%lud\n", stats.tmoutcname);
276f46c709fSDavid du Colombier fprint(fd, "# ipv6 queries timed-out\t%lud\n", stats.tmoutv6);
277f46c709fSDavid du Colombier fprint(fd, "\n# negative answers received\t%lud\n", stats.negans);
2780319257bSDavid du Colombier fprint(fd, "# negative answers w Rserver set\t%lud\n", stats.negserver);
2790319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation\t%lud\n",
2800319257bSDavid du Colombier stats.negbaddeleg);
2810319257bSDavid du Colombier fprint(fd, "# negative answers w bad delegation & no answers\t%lud\n",
2820319257bSDavid du Colombier stats.negbdnoans);
2830319257bSDavid du Colombier fprint(fd, "# negative answers w no Rname set\t%lud\n", stats.negnorname);
284f46c709fSDavid du Colombier fprint(fd, "# negative answers cached\t%lud\n", stats.negcached);
285a41547ffSDavid du Colombier qunlock(&stats);
286a41547ffSDavid du Colombier
287219b2ee8SDavid du Colombier lock(&dnlock);
2886d8e4566SDavid du Colombier fprint(fd, "\n# domain names %lud target %lud\n", dnvars.names, target);
2894f927735SDavid du Colombier unlock(&dnlock);
2904f927735SDavid du Colombier close(fd);
2914f927735SDavid du Colombier }
2924f927735SDavid du Colombier
2934f927735SDavid du Colombier /*
2944f927735SDavid du Colombier * dump the cache
2954f927735SDavid du Colombier */
2964f927735SDavid du Colombier void
dndump(char * file)2974f927735SDavid du Colombier dndump(char *file)
2984f927735SDavid du Colombier {
2994f927735SDavid du Colombier int i, fd;
3004f927735SDavid du Colombier DN *dp;
3014f927735SDavid du Colombier RR *rp;
3024f927735SDavid du Colombier
3034f927735SDavid du Colombier fd = create(file, OWRITE, 0666);
3044f927735SDavid du Colombier if(fd < 0)
3054f927735SDavid du Colombier return;
3064f927735SDavid du Colombier
3074f927735SDavid du Colombier lock(&dnlock);
3084f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++)
309219b2ee8SDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){
310219b2ee8SDavid du Colombier fprint(fd, "%s\n", dp->name);
311225077b0SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next) {
3126d8e4566SDavid du Colombier fprint(fd, "\t%R %c%c %lud/%lud\n",
3134f8f669cSDavid du Colombier rp, rp->auth? 'A': 'U',
3147dd7cddfSDavid du Colombier rp->db? 'D': 'N', rp->expire, rp->ttl);
315225077b0SDavid du Colombier if (rronlist(rp, rp->next))
316225077b0SDavid du Colombier fprint(fd, "*** duplicate:\n");
317225077b0SDavid du Colombier }
318219b2ee8SDavid du Colombier }
319219b2ee8SDavid du Colombier unlock(&dnlock);
320219b2ee8SDavid du Colombier close(fd);
321219b2ee8SDavid du Colombier }
322219b2ee8SDavid du Colombier
323219b2ee8SDavid du Colombier /*
3247dd7cddfSDavid du Colombier * purge all records
3257dd7cddfSDavid du Colombier */
3267dd7cddfSDavid du Colombier void
dnpurge(void)3277dd7cddfSDavid du Colombier dnpurge(void)
3287dd7cddfSDavid du Colombier {
3297dd7cddfSDavid du Colombier DN *dp;
330a4285193SDavid du Colombier RR *rp, *srp;
3317dd7cddfSDavid du Colombier int i;
3327dd7cddfSDavid du Colombier
3337dd7cddfSDavid du Colombier lock(&dnlock);
3347dd7cddfSDavid du Colombier
3357dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
3367dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){
337a4285193SDavid du Colombier srp = rp = dp->rr;
3387dd7cddfSDavid du Colombier dp->rr = nil;
3397dd7cddfSDavid du Colombier for(; rp != nil; rp = rp->next)
3407dd7cddfSDavid du Colombier rp->cached = 0;
341a4285193SDavid du Colombier rrfreelist(srp);
3427dd7cddfSDavid du Colombier }
3437dd7cddfSDavid du Colombier
3447dd7cddfSDavid du Colombier unlock(&dnlock);
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier
347d2fd7a44SDavid du Colombier /*
3484faf7596SDavid du Colombier * delete head of *l and free the old head.
349d2fd7a44SDavid du Colombier * call with dnlock held.
350d2fd7a44SDavid du Colombier */
351225077b0SDavid du Colombier static void
rrdelhead(RR ** l)3524faf7596SDavid du Colombier rrdelhead(RR **l)
353225077b0SDavid du Colombier {
3544faf7596SDavid du Colombier RR *rp;
3554faf7596SDavid du Colombier
3564faf7596SDavid du Colombier if (canlock(&dnlock))
3574faf7596SDavid du Colombier abort(); /* rrdelhead called with dnlock not held */
3584faf7596SDavid du Colombier rp = *l;
3594faf7596SDavid du Colombier if(rp == nil)
3604faf7596SDavid du Colombier return;
3614faf7596SDavid du Colombier *l = rp->next; /* unlink head */
362225077b0SDavid du Colombier rp->cached = 0; /* avoid blowing an assertion in rrfree */
363225077b0SDavid du Colombier rrfree(rp);
364225077b0SDavid du Colombier }
365225077b0SDavid du Colombier
3667dd7cddfSDavid du Colombier /*
367d2fd7a44SDavid du Colombier * check the age of resource records, free any that have timed out.
368d2fd7a44SDavid du Colombier * call with dnlock held.
3693e12c5d1SDavid du Colombier */
3703e12c5d1SDavid du Colombier void
dnage(DN * dp)3713e12c5d1SDavid du Colombier dnage(DN *dp)
3723e12c5d1SDavid du Colombier {
3733e12c5d1SDavid du Colombier RR **l;
3743e12c5d1SDavid du Colombier RR *rp, *next;
3757dd7cddfSDavid du Colombier ulong diff;
3763e12c5d1SDavid du Colombier
3774faf7596SDavid du Colombier if (canlock(&dnlock))
3784faf7596SDavid du Colombier abort(); /* dnage called with dnlock not held */
3797dd7cddfSDavid du Colombier diff = now - dp->referenced;
3806dc4800dSDavid du Colombier if(diff < Reserved || dp->keep)
3817dd7cddfSDavid du Colombier return;
3827dd7cddfSDavid du Colombier
3833e12c5d1SDavid du Colombier l = &dp->rr;
3843e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = next){
385*03da95d6SDavid du Colombier assert(rp->magic == RRmagic);
386*03da95d6SDavid du Colombier assert(rp->cached);
3873e12c5d1SDavid du Colombier next = rp->next;
388225077b0SDavid du Colombier if(!rp->db && (rp->expire < now || diff > dnvars.oldest))
3894faf7596SDavid du Colombier rrdelhead(l); /* rp == *l before; *l == rp->next after */
390225077b0SDavid du Colombier else
3913e12c5d1SDavid du Colombier l = &rp->next;
3923e12c5d1SDavid du Colombier }
3933e12c5d1SDavid du Colombier }
3943e12c5d1SDavid du Colombier
3956dc4800dSDavid du Colombier #define MARK(dp) { if (dp) (dp)->keep = 1; }
396a41547ffSDavid du Colombier
397410ea80bSDavid du Colombier /* mark a domain name and those in its RRs as never to be aged */
398a41547ffSDavid du Colombier void
dnagenever(DN * dp,int dolock)399410ea80bSDavid du Colombier dnagenever(DN *dp, int dolock)
400a41547ffSDavid du Colombier {
401a41547ffSDavid du Colombier RR *rp;
402a41547ffSDavid du Colombier
403410ea80bSDavid du Colombier if (dolock)
404a41547ffSDavid du Colombier lock(&dnlock);
405a41547ffSDavid du Colombier
406410ea80bSDavid du Colombier /* mark all referenced domain names */
407410ea80bSDavid du Colombier MARK(dp);
408a41547ffSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
409a41547ffSDavid du Colombier MARK(rp->owner);
410410ea80bSDavid du Colombier if(rp->negative){
411410ea80bSDavid du Colombier MARK(rp->negsoaowner);
412410ea80bSDavid du Colombier continue;
413410ea80bSDavid du Colombier }
414a41547ffSDavid du Colombier switch(rp->type){
415410ea80bSDavid du Colombier case Thinfo:
416410ea80bSDavid du Colombier MARK(rp->cpu);
417410ea80bSDavid du Colombier MARK(rp->os);
418410ea80bSDavid du Colombier break;
419410ea80bSDavid du Colombier case Ttxt:
420410ea80bSDavid du Colombier break;
421410ea80bSDavid du Colombier case Tcname:
422410ea80bSDavid du Colombier case Tmb:
423410ea80bSDavid du Colombier case Tmd:
424410ea80bSDavid du Colombier case Tmf:
425a41547ffSDavid du Colombier case Tns:
426410ea80bSDavid du Colombier case Tmx:
427410ea80bSDavid du Colombier case Tsrv:
428a41547ffSDavid du Colombier MARK(rp->host);
429a41547ffSDavid du Colombier break;
430410ea80bSDavid du Colombier case Tmg:
431410ea80bSDavid du Colombier case Tmr:
432410ea80bSDavid du Colombier MARK(rp->mb);
433410ea80bSDavid du Colombier break;
434410ea80bSDavid du Colombier case Tminfo:
435410ea80bSDavid du Colombier MARK(rp->rmb);
436410ea80bSDavid du Colombier MARK(rp->mb);
437410ea80bSDavid du Colombier break;
438410ea80bSDavid du Colombier case Trp:
439410ea80bSDavid du Colombier MARK(rp->rmb);
440410ea80bSDavid du Colombier MARK(rp->rp);
441410ea80bSDavid du Colombier break;
442410ea80bSDavid du Colombier case Ta:
443410ea80bSDavid du Colombier case Taaaa:
444410ea80bSDavid du Colombier MARK(rp->ip);
445410ea80bSDavid du Colombier break;
446410ea80bSDavid du Colombier case Tptr:
447410ea80bSDavid du Colombier MARK(rp->ptr);
448410ea80bSDavid du Colombier break;
449410ea80bSDavid du Colombier case Tsoa:
450410ea80bSDavid du Colombier MARK(rp->host);
451410ea80bSDavid du Colombier MARK(rp->rmb);
452410ea80bSDavid du Colombier break;
453a41547ffSDavid du Colombier }
454a41547ffSDavid du Colombier }
455410ea80bSDavid du Colombier
456410ea80bSDavid du Colombier if (dolock)
457410ea80bSDavid du Colombier unlock(&dnlock);
4586dc4800dSDavid du Colombier }
459a41547ffSDavid du Colombier
460410ea80bSDavid du Colombier /* mark all current domain names as never to be aged */
461410ea80bSDavid du Colombier void
dnageallnever(void)462410ea80bSDavid du Colombier dnageallnever(void)
463410ea80bSDavid du Colombier {
464410ea80bSDavid du Colombier int i;
465410ea80bSDavid du Colombier DN *dp;
466410ea80bSDavid du Colombier
467410ea80bSDavid du Colombier lock(&dnlock);
468410ea80bSDavid du Colombier
469410ea80bSDavid du Colombier /* mark all referenced domain names */
470410ea80bSDavid du Colombier for(i = 0; i < HTLEN; i++)
471410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next)
472410ea80bSDavid du Colombier dnagenever(dp, 0);
473410ea80bSDavid du Colombier
474a41547ffSDavid du Colombier unlock(&dnlock);
475a41547ffSDavid du Colombier
476a41547ffSDavid du Colombier dnslog("%ld initial domain names; target is %ld", dnvars.names, target);
477a41547ffSDavid du Colombier if(dnvars.names >= target)
478a41547ffSDavid du Colombier dnslog("more initial domain names (%ld) than target (%ld)",
479a41547ffSDavid du Colombier dnvars.names, target);
480a41547ffSDavid du Colombier }
481a41547ffSDavid du Colombier
4826dc4800dSDavid du Colombier #define REF(dp) { if (dp) (dp)->refs++; }
4836dc4800dSDavid du Colombier
4847dd7cddfSDavid du Colombier /*
4857dd7cddfSDavid du Colombier * periodicly sweep for old records and remove unreferenced domain names
4867dd7cddfSDavid du Colombier *
4877dd7cddfSDavid du Colombier * only called when all other threads are locked out
4887dd7cddfSDavid du Colombier */
4897dd7cddfSDavid du Colombier void
dnageall(int doit)4907dd7cddfSDavid du Colombier dnageall(int doit)
4917dd7cddfSDavid du Colombier {
4927dd7cddfSDavid du Colombier DN *dp, **l;
493225077b0SDavid du Colombier int i;
4947dd7cddfSDavid du Colombier RR *rp;
4957dd7cddfSDavid du Colombier static ulong nextage;
4967dd7cddfSDavid du Colombier
4974f8f669cSDavid du Colombier if(dnvars.names < target || (now < nextage && !doit)){
4987dd7cddfSDavid du Colombier dnvars.oldest = maxage;
4997dd7cddfSDavid du Colombier return;
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier
5024f8f669cSDavid du Colombier if(dnvars.names >= target) {
5033cbadd90SDavid du Colombier dnslog("more names (%lud) than target (%lud)", dnvars.names,
5043cbadd90SDavid du Colombier target);
5057dd7cddfSDavid du Colombier dnvars.oldest /= 2;
50681730632SDavid du Colombier if (dnvars.oldest < Minage)
50781730632SDavid du Colombier dnvars.oldest = Minage; /* don't be silly */
5084f8f669cSDavid du Colombier }
509f46c709fSDavid du Colombier if (agefreq > dnvars.oldest / 2)
510f46c709fSDavid du Colombier nextage = now + dnvars.oldest / 2;
511f46c709fSDavid du Colombier else
512f46c709fSDavid du Colombier nextage = now + agefreq;
5137dd7cddfSDavid du Colombier
5147dd7cddfSDavid du Colombier lock(&dnlock);
5157dd7cddfSDavid du Colombier
5167dd7cddfSDavid du Colombier /* time out all old entries (and set refs to 0) */
5177dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
5187dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){
5197dd7cddfSDavid du Colombier dp->refs = 0;
5207dd7cddfSDavid du Colombier dnage(dp);
5217dd7cddfSDavid du Colombier }
5227dd7cddfSDavid du Colombier
5237dd7cddfSDavid du Colombier /* mark all referenced domain names */
5247dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
5257dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next)
5267dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
5277dd7cddfSDavid du Colombier REF(rp->owner);
5287dd7cddfSDavid du Colombier if(rp->negative){
5297dd7cddfSDavid du Colombier REF(rp->negsoaowner);
5307dd7cddfSDavid du Colombier continue;
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier switch(rp->type){
5337dd7cddfSDavid du Colombier case Thinfo:
5347dd7cddfSDavid du Colombier REF(rp->cpu);
5357dd7cddfSDavid du Colombier REF(rp->os);
5367dd7cddfSDavid du Colombier break;
5377dd7cddfSDavid du Colombier case Ttxt:
5387dd7cddfSDavid du Colombier break;
5397dd7cddfSDavid du Colombier case Tcname:
5407dd7cddfSDavid du Colombier case Tmb:
5417dd7cddfSDavid du Colombier case Tmd:
5427dd7cddfSDavid du Colombier case Tmf:
5437dd7cddfSDavid du Colombier case Tns:
5444f8f669cSDavid du Colombier case Tmx:
545225077b0SDavid du Colombier case Tsrv:
5467dd7cddfSDavid du Colombier REF(rp->host);
5477dd7cddfSDavid du Colombier break;
5487dd7cddfSDavid du Colombier case Tmg:
5497dd7cddfSDavid du Colombier case Tmr:
5507dd7cddfSDavid du Colombier REF(rp->mb);
5517dd7cddfSDavid du Colombier break;
5527dd7cddfSDavid du Colombier case Tminfo:
5537dd7cddfSDavid du Colombier REF(rp->rmb);
5547dd7cddfSDavid du Colombier REF(rp->mb);
5557dd7cddfSDavid du Colombier break;
5567dd7cddfSDavid du Colombier case Trp:
5577dd7cddfSDavid du Colombier REF(rp->rmb);
55860845620SDavid du Colombier REF(rp->rp);
5597dd7cddfSDavid du Colombier break;
5607dd7cddfSDavid du Colombier case Ta:
5615d459b5aSDavid du Colombier case Taaaa:
5627dd7cddfSDavid du Colombier REF(rp->ip);
5637dd7cddfSDavid du Colombier break;
5647dd7cddfSDavid du Colombier case Tptr:
5657dd7cddfSDavid du Colombier REF(rp->ptr);
5667dd7cddfSDavid du Colombier break;
5677dd7cddfSDavid du Colombier case Tsoa:
5687dd7cddfSDavid du Colombier REF(rp->host);
5697dd7cddfSDavid du Colombier REF(rp->rmb);
5707dd7cddfSDavid du Colombier break;
5717dd7cddfSDavid du Colombier }
5727dd7cddfSDavid du Colombier }
5737dd7cddfSDavid du Colombier
5747dd7cddfSDavid du Colombier /* sweep and remove unreferenced domain names */
5757dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++){
5767dd7cddfSDavid du Colombier l = &ht[i];
5777dd7cddfSDavid du Colombier for(dp = *l; dp; dp = *l){
578a41547ffSDavid du Colombier if(dp->rr == 0 && dp->refs == 0 && !dp->keep){
57934f77ae3SDavid du Colombier assert(dp->magic == DNmagic);
5807dd7cddfSDavid du Colombier *l = dp->next;
5814f8f669cSDavid du Colombier
5827dd7cddfSDavid du Colombier if(dp->name)
5837dd7cddfSDavid du Colombier free(dp->name);
58434f77ae3SDavid du Colombier dp->magic = ~dp->magic;
5857dd7cddfSDavid du Colombier dnvars.names--;
5864f8f669cSDavid du Colombier memset(dp, 0, sizeof *dp); /* cause trouble */
5877dd7cddfSDavid du Colombier free(dp);
5884f8f669cSDavid du Colombier
5897dd7cddfSDavid du Colombier continue;
5907dd7cddfSDavid du Colombier }
5917dd7cddfSDavid du Colombier l = &dp->next;
5927dd7cddfSDavid du Colombier }
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier unlock(&dnlock);
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier
5987dd7cddfSDavid du Colombier /*
5997dd7cddfSDavid du Colombier * timeout all database records (used when rereading db)
6007dd7cddfSDavid du Colombier */
6017dd7cddfSDavid du Colombier void
dnagedb(void)6027dd7cddfSDavid du Colombier dnagedb(void)
6037dd7cddfSDavid du Colombier {
6047dd7cddfSDavid du Colombier DN *dp;
6057dd7cddfSDavid du Colombier int i;
6067dd7cddfSDavid du Colombier RR *rp;
6077dd7cddfSDavid du Colombier
6087dd7cddfSDavid du Colombier lock(&dnlock);
6097dd7cddfSDavid du Colombier
6107dd7cddfSDavid du Colombier /* time out all database entries */
6117dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
612410ea80bSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next) {
613410ea80bSDavid du Colombier dp->keep = 0;
6147dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next)
6157dd7cddfSDavid du Colombier if(rp->db)
6167dd7cddfSDavid du Colombier rp->expire = 0;
617410ea80bSDavid du Colombier }
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier unlock(&dnlock);
6207dd7cddfSDavid du Colombier }
6217dd7cddfSDavid du Colombier
6227dd7cddfSDavid du Colombier /*
6234f8f669cSDavid du Colombier * mark all local db records about my area as authoritative,
6244f8f669cSDavid du Colombier * time out any others
6257dd7cddfSDavid du Colombier */
6267dd7cddfSDavid du Colombier void
dnauthdb(void)6277dd7cddfSDavid du Colombier dnauthdb(void)
6287dd7cddfSDavid du Colombier {
6296b0d5c8bSDavid du Colombier int i;
6304f8f669cSDavid du Colombier ulong minttl;
6316b0d5c8bSDavid du Colombier Area *area;
6324f8f669cSDavid du Colombier DN *dp;
6337dd7cddfSDavid du Colombier RR *rp;
6347dd7cddfSDavid du Colombier
6357dd7cddfSDavid du Colombier lock(&dnlock);
6367dd7cddfSDavid du Colombier
6377dd7cddfSDavid du Colombier /* time out all database entries */
6387dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
6397dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){
6407dd7cddfSDavid du Colombier area = inmyarea(dp->name);
6417dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next)
6427dd7cddfSDavid du Colombier if(rp->db){
6437dd7cddfSDavid du Colombier if(area){
6444f8f669cSDavid du Colombier minttl = area->soarr->soa->minttl;
6454f8f669cSDavid du Colombier if(rp->ttl < minttl)
6464f8f669cSDavid du Colombier rp->ttl = minttl;
6477dd7cddfSDavid du Colombier rp->auth = 1;
6487dd7cddfSDavid du Colombier }
6497dd7cddfSDavid du Colombier if(rp->expire == 0){
6507dd7cddfSDavid du Colombier rp->db = 0;
6517dd7cddfSDavid du Colombier dp->referenced = now-Reserved-1;
6527dd7cddfSDavid du Colombier }
6537dd7cddfSDavid du Colombier }
6547dd7cddfSDavid du Colombier }
6557dd7cddfSDavid du Colombier
6567dd7cddfSDavid du Colombier unlock(&dnlock);
6577dd7cddfSDavid du Colombier }
6587dd7cddfSDavid du Colombier
6597dd7cddfSDavid du Colombier /*
6607dd7cddfSDavid du Colombier * keep track of other processes to know if we can
6617dd7cddfSDavid du Colombier * garbage collect. block while garbage collecting.
6627dd7cddfSDavid du Colombier */
6637dd7cddfSDavid du Colombier int
getactivity(Request * req,int recursive)664b4b9fc2fSDavid du Colombier getactivity(Request *req, int recursive)
6657dd7cddfSDavid du Colombier {
6667dd7cddfSDavid du Colombier int rv;
6677dd7cddfSDavid du Colombier
6684f8f669cSDavid du Colombier if(traceactivity)
6694f8f669cSDavid du Colombier dnslog("get: %d active by pid %d from %p",
6704f8f669cSDavid du Colombier dnvars.active, getpid(), getcallerpc(&req));
6717dd7cddfSDavid du Colombier lock(&dnvars);
672b4b9fc2fSDavid du Colombier /*
673b4b9fc2fSDavid du Colombier * can't block here if we're already holding one
674b4b9fc2fSDavid du Colombier * of the dnvars.active (recursive). will deadlock.
675b4b9fc2fSDavid du Colombier */
676b4b9fc2fSDavid du Colombier while(!recursive && dnvars.mutex){
6777dd7cddfSDavid du Colombier unlock(&dnvars);
678d6d99297SDavid du Colombier sleep(100); /* tune; was 200 */
6797dd7cddfSDavid du Colombier lock(&dnvars);
6807dd7cddfSDavid du Colombier }
6817dd7cddfSDavid du Colombier rv = ++dnvars.active;
6824f8f669cSDavid du Colombier now = time(nil);
683a41547ffSDavid du Colombier nowns = nsec();
6847dd7cddfSDavid du Colombier req->id = ++dnvars.id;
6857dd7cddfSDavid du Colombier unlock(&dnvars);
6867dd7cddfSDavid du Colombier
6877dd7cddfSDavid du Colombier return rv;
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier void
putactivity(int recursive)690b4b9fc2fSDavid du Colombier putactivity(int recursive)
6917dd7cddfSDavid du Colombier {
6927dd7cddfSDavid du Colombier static ulong lastclean;
6937dd7cddfSDavid du Colombier
6944f8f669cSDavid du Colombier if(traceactivity)
6954f8f669cSDavid du Colombier dnslog("put: %d active by pid %d",
6964f8f669cSDavid du Colombier dnvars.active, getpid());
6977dd7cddfSDavid du Colombier lock(&dnvars);
6987dd7cddfSDavid du Colombier dnvars.active--;
6994f8f669cSDavid du Colombier assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */
7007dd7cddfSDavid du Colombier
7017dd7cddfSDavid du Colombier /*
7027dd7cddfSDavid du Colombier * clean out old entries and check for new db periodicly
703b4b9fc2fSDavid du Colombier * can't block here if being called to let go a "recursive" lock
704b4b9fc2fSDavid du Colombier * or we'll deadlock waiting for ourselves to give up the dnvars.active.
7057dd7cddfSDavid du Colombier */
7064f8f669cSDavid du Colombier if (recursive || dnvars.mutex ||
7074f8f669cSDavid du Colombier (needrefresh == 0 && dnvars.active > 0)){
7087dd7cddfSDavid du Colombier unlock(&dnvars);
7097dd7cddfSDavid du Colombier return;
7107dd7cddfSDavid du Colombier }
7117dd7cddfSDavid du Colombier
7127dd7cddfSDavid du Colombier /* wait till we're alone */
7137dd7cddfSDavid du Colombier dnvars.mutex = 1;
7147dd7cddfSDavid du Colombier while(dnvars.active > 0){
7157dd7cddfSDavid du Colombier unlock(&dnvars);
716d6d99297SDavid du Colombier sleep(100); /* tune; was 100 */
7177dd7cddfSDavid du Colombier lock(&dnvars);
7187dd7cddfSDavid du Colombier }
7197dd7cddfSDavid du Colombier unlock(&dnvars);
7207dd7cddfSDavid du Colombier
7217dd7cddfSDavid du Colombier db2cache(needrefresh);
72227acba7cSDavid du Colombier
72327acba7cSDavid du Colombier /* if we've been running for long enough, restart */
72427acba7cSDavid du Colombier if(start == 0)
72527acba7cSDavid du Colombier start = time(nil);
726409a7d08SDavid du Colombier if(Restartmins > 0 && time(nil) - start > Restartmins*60){
72727acba7cSDavid du Colombier dnslog("killing all dns procs for timed restart");
72827acba7cSDavid du Colombier postnote(PNGROUP, getpid(), "die");
72927acba7cSDavid du Colombier dnvars.mutex = 0;
73027acba7cSDavid du Colombier exits("restart");
73127acba7cSDavid du Colombier }
73227acba7cSDavid du Colombier
7337dd7cddfSDavid du Colombier dnageall(0);
7347dd7cddfSDavid du Colombier
7357dd7cddfSDavid du Colombier /* let others back in */
7367dd7cddfSDavid du Colombier lastclean = now;
7377dd7cddfSDavid du Colombier needrefresh = 0;
7387dd7cddfSDavid du Colombier dnvars.mutex = 0;
7397dd7cddfSDavid du Colombier }
7407dd7cddfSDavid du Colombier
741d2fd7a44SDavid du Colombier int
rrlistlen(RR * rp)742d2fd7a44SDavid du Colombier rrlistlen(RR *rp)
743d2fd7a44SDavid du Colombier {
744d2fd7a44SDavid du Colombier int n;
745d2fd7a44SDavid du Colombier
746d2fd7a44SDavid du Colombier n = 0;
747d2fd7a44SDavid du Colombier for(; rp; rp = rp->next)
748d2fd7a44SDavid du Colombier ++n;
749d2fd7a44SDavid du Colombier return n;
750d2fd7a44SDavid du Colombier }
751d2fd7a44SDavid du Colombier
7523e12c5d1SDavid du Colombier /*
7536dc4800dSDavid du Colombier * Attach a single resource record to a domain name (new->owner).
7543e12c5d1SDavid du Colombier * - Avoid duplicates with already present RR's
7553e12c5d1SDavid du Colombier * - Chain all RR's of the same type adjacent to one another
7563e12c5d1SDavid du Colombier * - chain authoritative RR's ahead of non-authoritative ones
7576dc4800dSDavid du Colombier * - remove any expired RR's
758225077b0SDavid du Colombier * If new is a stale duplicate, rrfree it.
7596dc4800dSDavid du Colombier * Must be called with dnlock held.
7603e12c5d1SDavid du Colombier */
7613e12c5d1SDavid du Colombier static void
rrattach1(RR * new,int auth)7623e12c5d1SDavid du Colombier rrattach1(RR *new, int auth)
7633e12c5d1SDavid du Colombier {
7643e12c5d1SDavid du Colombier RR **l;
7653e12c5d1SDavid du Colombier RR *rp;
7663e12c5d1SDavid du Colombier DN *dp;
7673e12c5d1SDavid du Colombier
768*03da95d6SDavid du Colombier assert(new->magic == RRmagic);
769*03da95d6SDavid du Colombier assert(!new->cached);
7707dd7cddfSDavid du Colombier
7714f8f669cSDavid du Colombier // dnslog("rrattach1: %s", new->owner->name);
772e9b54818SDavid du Colombier if(!new->db) {
773e9b54818SDavid du Colombier /*
774e9b54818SDavid du Colombier * try not to let responses expire before we
775e9b54818SDavid du Colombier * can use them to complete this query, by extending
776e464c1a8SDavid du Colombier * past (or nearly past) expiration time.
777e9b54818SDavid du Colombier */
778e464c1a8SDavid du Colombier new->expire = new->ttl > now + Min? new->ttl: now + 10*Min;
779e9b54818SDavid du Colombier } else
7807dd7cddfSDavid du Colombier new->expire = now + Year;
7813e12c5d1SDavid du Colombier dp = new->owner;
7827dd7cddfSDavid du Colombier assert(dp->magic == DNmagic);
7837dd7cddfSDavid du Colombier new->auth |= auth;
7843e12c5d1SDavid du Colombier new->next = 0;
7853e12c5d1SDavid du Colombier
7863e12c5d1SDavid du Colombier /*
7873ff48bf5SDavid du Colombier * find first rr of the right type
7883e12c5d1SDavid du Colombier */
7893e12c5d1SDavid du Colombier l = &dp->rr;
7907dd7cddfSDavid du Colombier for(rp = *l; rp; rp = *l){
791*03da95d6SDavid du Colombier assert(rp->magic == RRmagic);
792*03da95d6SDavid du Colombier assert(rp->cached);
7933e12c5d1SDavid du Colombier if(rp->type == new->type)
7943e12c5d1SDavid du Colombier break;
7953e12c5d1SDavid du Colombier l = &rp->next;
7963e12c5d1SDavid du Colombier }
7973e12c5d1SDavid du Colombier
7983e12c5d1SDavid du Colombier /*
7997dd7cddfSDavid du Colombier * negative entries replace positive entries
8007dd7cddfSDavid du Colombier * positive entries replace negative entries
8017dd7cddfSDavid du Colombier * newer entries replace older entries with the same fields
802225077b0SDavid du Colombier *
803225077b0SDavid du Colombier * look farther ahead than just the next entry when looking
804225077b0SDavid du Colombier * for duplicates; RRs of a given type can have different rdata
805225077b0SDavid du Colombier * fields (e.g. multiple NS servers).
8063e12c5d1SDavid du Colombier */
807225077b0SDavid du Colombier while ((rp = *l) != nil){
808*03da95d6SDavid du Colombier assert(rp->magic == RRmagic);
809*03da95d6SDavid du Colombier assert(rp->cached);
8107dd7cddfSDavid du Colombier if(rp->type != new->type)
8113e12c5d1SDavid du Colombier break;
8127dd7cddfSDavid du Colombier
8137dd7cddfSDavid du Colombier if(rp->db == new->db && rp->auth == new->auth){
8147dd7cddfSDavid du Colombier /* negative drives out positive and vice versa */
8157dd7cddfSDavid du Colombier if(rp->negative != new->negative) {
8164faf7596SDavid du Colombier /* rp == *l before; *l == rp->next after */
8174faf7596SDavid du Colombier rrdelhead(l);
8184faf7596SDavid du Colombier continue;
8193e12c5d1SDavid du Colombier }
8207dd7cddfSDavid du Colombier /* all things equal, pick the newer one */
821225077b0SDavid du Colombier else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
8227dd7cddfSDavid du Colombier /* new drives out old */
823225077b0SDavid du Colombier if (new->ttl <= rp->ttl &&
824225077b0SDavid du Colombier new->expire <= rp->expire) {
8253e12c5d1SDavid du Colombier rrfree(new);
8263e12c5d1SDavid du Colombier return;
8273e12c5d1SDavid du Colombier }
8284faf7596SDavid du Colombier /* rp == *l before; *l == rp->next after */
8294faf7596SDavid du Colombier rrdelhead(l);
8304faf7596SDavid du Colombier continue;
8317dd7cddfSDavid du Colombier }
832225077b0SDavid du Colombier /*
833225077b0SDavid du Colombier * Hack for pointer records. This makes sure
8343ff48bf5SDavid du Colombier * the ordering in the list reflects the ordering
8353ff48bf5SDavid du Colombier * received or read from the database
8363ff48bf5SDavid du Colombier */
837225077b0SDavid du Colombier else if(rp->type == Tptr &&
838225077b0SDavid du Colombier !rp->negative && !new->negative &&
839225077b0SDavid du Colombier rp->ptr->ordinal > new->ptr->ordinal)
8403ff48bf5SDavid du Colombier break;
8413ff48bf5SDavid du Colombier }
8423e12c5d1SDavid du Colombier l = &rp->next;
8433e12c5d1SDavid du Colombier }
8443e12c5d1SDavid du Colombier
845530fef66SDavid du Colombier if (rronlist(new, rp)) {
8464f927735SDavid du Colombier /* should not happen; duplicates were processed above */
847530fef66SDavid du Colombier dnslog("adding duplicate %R to list of %R; aborting", new, rp);
8484f927735SDavid du Colombier abort();
8494f927735SDavid du Colombier }
8503e12c5d1SDavid du Colombier /*
8513e12c5d1SDavid du Colombier * add to chain
8523e12c5d1SDavid du Colombier */
8537dd7cddfSDavid du Colombier new->cached = 1;
854530fef66SDavid du Colombier new->next = rp;
8553e12c5d1SDavid du Colombier *l = new;
8563e12c5d1SDavid du Colombier }
8573e12c5d1SDavid du Colombier
8583e12c5d1SDavid du Colombier /*
8593e12c5d1SDavid du Colombier * Attach a list of resource records to a domain name.
860225077b0SDavid du Colombier * May rrfree any stale duplicate RRs; dismembers the list.
861225077b0SDavid du Colombier * Upon return, every RR in the list will have been rrfree-d
862225077b0SDavid du Colombier * or attached to its domain name.
8636dc4800dSDavid du Colombier * See rrattach1 for properties preserved.
8643e12c5d1SDavid du Colombier */
8653e12c5d1SDavid du Colombier void
rrattach(RR * rp,int auth)8663e12c5d1SDavid du Colombier rrattach(RR *rp, int auth)
8673e12c5d1SDavid du Colombier {
868e6d9d902SDavid du Colombier RR *next, *tp;
869d2fd7a44SDavid du Colombier DN *dp;
8703e12c5d1SDavid du Colombier
871bd389b36SDavid du Colombier lock(&dnlock);
8723e12c5d1SDavid du Colombier for(; rp; rp = next){
8733e12c5d1SDavid du Colombier next = rp->next;
8744f8f669cSDavid du Colombier rp->next = nil;
875d2fd7a44SDavid du Colombier dp = rp->owner;
8767dd7cddfSDavid du Colombier
8774f8f669cSDavid du Colombier // dnslog("rrattach: %s", rp->owner->name);
878c3617180SDavid du Colombier /* avoid any outside spoofing; leave keepers alone */
879c3617180SDavid du Colombier if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name)
880c3617180SDavid du Colombier // || dp->keep /* TODO: make this work */
881c3617180SDavid du Colombier )
8827dd7cddfSDavid du Colombier rrfree(rp);
883d2fd7a44SDavid du Colombier else {
8844faf7596SDavid du Colombier /* ameliorate the memory leak (someday delete this) */
885530fef66SDavid du Colombier if (0 && rrlistlen(dp->rr) > 50 && !dp->keep) {
886530fef66SDavid du Colombier dnslog("rrattach(%s): rr list too long; "
887530fef66SDavid du Colombier "freeing it", dp->name);
888e6d9d902SDavid du Colombier tp = dp->rr;
889530fef66SDavid du Colombier dp->rr = nil;
890e6d9d902SDavid du Colombier rrfreelist(tp);
891530fef66SDavid du Colombier } else
892530fef66SDavid du Colombier USED(dp);
8933e12c5d1SDavid du Colombier rrattach1(rp, auth);
894d2fd7a44SDavid du Colombier }
8953e12c5d1SDavid du Colombier }
896bd389b36SDavid du Colombier unlock(&dnlock);
8973e12c5d1SDavid du Colombier }
8983e12c5d1SDavid du Colombier
899530fef66SDavid du Colombier /* should be called with dnlock held */
9004f8f669cSDavid du Colombier RR**
rrcopy(RR * rp,RR ** last)9017dd7cddfSDavid du Colombier rrcopy(RR *rp, RR **last)
9027dd7cddfSDavid du Colombier {
9034f8f669cSDavid du Colombier Cert *cert;
9044f8f669cSDavid du Colombier Key *key;
9054f8f669cSDavid du Colombier Null *null;
9067dd7cddfSDavid du Colombier RR *nrp;
9077dd7cddfSDavid du Colombier SOA *soa;
9089a747e4fSDavid du Colombier Sig *sig;
90960845620SDavid du Colombier Txt *t, *nt, **l;
9107dd7cddfSDavid du Colombier
9114faf7596SDavid du Colombier if (canlock(&dnlock))
9124faf7596SDavid du Colombier abort(); /* rrcopy called with dnlock not held */
9137dd7cddfSDavid du Colombier nrp = rralloc(rp->type);
914a41547ffSDavid du Colombier setmalloctag(nrp, getcallerpc(&rp));
9159a747e4fSDavid du Colombier switch(rp->type){
91660845620SDavid du Colombier case Ttxt:
91760845620SDavid du Colombier *nrp = *rp;
91860845620SDavid du Colombier l = &nrp->txt;
91960845620SDavid du Colombier *l = nil;
92060845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next){
92160845620SDavid du Colombier nt = emalloc(sizeof(*nt));
92260845620SDavid du Colombier nt->p = estrdup(t->p);
92360845620SDavid du Colombier nt->next = nil;
92460845620SDavid du Colombier *l = nt;
92560845620SDavid du Colombier l = &nt->next;
92660845620SDavid du Colombier }
92760845620SDavid du Colombier break;
9289a747e4fSDavid du Colombier case Tsoa:
9297dd7cddfSDavid du Colombier soa = nrp->soa;
9307dd7cddfSDavid du Colombier *nrp = *rp;
9317dd7cddfSDavid du Colombier nrp->soa = soa;
9327dd7cddfSDavid du Colombier *nrp->soa = *rp->soa;
933dc5a79c1SDavid du Colombier nrp->soa->slaves = copyserverlist(rp->soa->slaves);
9349a747e4fSDavid du Colombier break;
9354f8f669cSDavid du Colombier case Tsrv:
9364f8f669cSDavid du Colombier *nrp = *rp;
937fd87a217SDavid du Colombier nrp->srv = emalloc(sizeof *nrp->srv);
9384f8f669cSDavid du Colombier *nrp->srv = *rp->srv;
9394f8f669cSDavid du Colombier break;
9409a747e4fSDavid du Colombier case Tkey:
9419a747e4fSDavid du Colombier key = nrp->key;
9429a747e4fSDavid du Colombier *nrp = *rp;
9439a747e4fSDavid du Colombier nrp->key = key;
9449a747e4fSDavid du Colombier *key = *rp->key;
9459a747e4fSDavid du Colombier key->data = emalloc(key->dlen);
9469a747e4fSDavid du Colombier memmove(key->data, rp->key->data, rp->key->dlen);
9479a747e4fSDavid du Colombier break;
9489a747e4fSDavid du Colombier case Tsig:
9499a747e4fSDavid du Colombier sig = nrp->sig;
9509a747e4fSDavid du Colombier *nrp = *rp;
9519a747e4fSDavid du Colombier nrp->sig = sig;
9529a747e4fSDavid du Colombier *sig = *rp->sig;
9539a747e4fSDavid du Colombier sig->data = emalloc(sig->dlen);
9549a747e4fSDavid du Colombier memmove(sig->data, rp->sig->data, rp->sig->dlen);
9559a747e4fSDavid du Colombier break;
9569a747e4fSDavid du Colombier case Tcert:
9579a747e4fSDavid du Colombier cert = nrp->cert;
9589a747e4fSDavid du Colombier *nrp = *rp;
9599a747e4fSDavid du Colombier nrp->cert = cert;
9609a747e4fSDavid du Colombier *cert = *rp->cert;
9619a747e4fSDavid du Colombier cert->data = emalloc(cert->dlen);
9629a747e4fSDavid du Colombier memmove(cert->data, rp->cert->data, rp->cert->dlen);
9639a747e4fSDavid du Colombier break;
9649a747e4fSDavid du Colombier case Tnull:
9659a747e4fSDavid du Colombier null = nrp->null;
9669a747e4fSDavid du Colombier *nrp = *rp;
9679a747e4fSDavid du Colombier nrp->null = null;
9689a747e4fSDavid du Colombier *null = *rp->null;
9699a747e4fSDavid du Colombier null->data = emalloc(null->dlen);
9709a747e4fSDavid du Colombier memmove(null->data, rp->null->data, rp->null->dlen);
9719a747e4fSDavid du Colombier break;
9729a747e4fSDavid du Colombier default:
9739a747e4fSDavid du Colombier *nrp = *rp;
9749a747e4fSDavid du Colombier break;
9757dd7cddfSDavid du Colombier }
9767dd7cddfSDavid du Colombier nrp->cached = 0;
9777dd7cddfSDavid du Colombier nrp->next = 0;
9787dd7cddfSDavid du Colombier *last = nrp;
9797dd7cddfSDavid du Colombier return &nrp->next;
9807dd7cddfSDavid du Colombier }
9817dd7cddfSDavid du Colombier
9823e12c5d1SDavid du Colombier /*
9833e12c5d1SDavid du Colombier * lookup a resource record of a particular type and
9847dd7cddfSDavid du Colombier * class attached to a domain name. Return copies.
9857dd7cddfSDavid du Colombier *
9867dd7cddfSDavid du Colombier * Priority ordering is:
9877dd7cddfSDavid du Colombier * db authoritative
9887dd7cddfSDavid du Colombier * not timed out network authoritative
9897dd7cddfSDavid du Colombier * not timed out network unauthoritative
9907dd7cddfSDavid du Colombier * unauthoritative db
9917dd7cddfSDavid du Colombier *
99280ee5cbfSDavid du Colombier * if flag NOneg is set, don't return negative cached entries.
9937dd7cddfSDavid du Colombier * return nothing instead.
9943e12c5d1SDavid du Colombier */
9953e12c5d1SDavid du Colombier RR*
rrlookup(DN * dp,int type,int flag)9967dd7cddfSDavid du Colombier rrlookup(DN *dp, int type, int flag)
9973e12c5d1SDavid du Colombier {
9987dd7cddfSDavid du Colombier RR *rp, *first, **last;
9993e12c5d1SDavid du Colombier
10007dd7cddfSDavid du Colombier assert(dp->magic == DNmagic);
10017dd7cddfSDavid du Colombier
10027dd7cddfSDavid du Colombier first = 0;
10037dd7cddfSDavid du Colombier last = &first;
10047dd7cddfSDavid du Colombier lock(&dnlock);
10057dd7cddfSDavid du Colombier
10067dd7cddfSDavid du Colombier /* try for an authoritative db entry */
10073e12c5d1SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
100898813beeSDavid du Colombier assert(rp->magic == RRmagic);
100998813beeSDavid du Colombier assert(rp->cached);
10107dd7cddfSDavid du Colombier if(rp->db)
10117dd7cddfSDavid du Colombier if(rp->auth)
1012a41547ffSDavid du Colombier if(tsame(type, rp->type)) {
10134e5f5f32SDavid du Colombier last = rrcopy(rp, last);
1014a41547ffSDavid du Colombier // setmalloctag(*last, getcallerpc(&dp));
1015a41547ffSDavid du Colombier }
10163e12c5d1SDavid du Colombier }
10177dd7cddfSDavid du Colombier if(first)
10187dd7cddfSDavid du Colombier goto out;
10197dd7cddfSDavid du Colombier
10204f8f669cSDavid du Colombier /* try for a living authoritative network entry */
10217dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
10227dd7cddfSDavid du Colombier if(!rp->db)
10237dd7cddfSDavid du Colombier if(rp->auth)
10247dd7cddfSDavid du Colombier if(rp->ttl + 60 > now)
10257dd7cddfSDavid du Colombier if(tsame(type, rp->type)){
10267dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative)
10277dd7cddfSDavid du Colombier goto out;
10287dd7cddfSDavid du Colombier last = rrcopy(rp, last);
10297dd7cddfSDavid du Colombier }
10307dd7cddfSDavid du Colombier }
10317dd7cddfSDavid du Colombier if(first)
10327dd7cddfSDavid du Colombier goto out;
10337dd7cddfSDavid du Colombier
10344f8f669cSDavid du Colombier /* try for a living unauthoritative network entry */
10357dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
10367dd7cddfSDavid du Colombier if(!rp->db)
10377dd7cddfSDavid du Colombier if(rp->ttl + 60 > now)
10387dd7cddfSDavid du Colombier if(tsame(type, rp->type)){
10397dd7cddfSDavid du Colombier if(flag == NOneg && rp->negative)
10407dd7cddfSDavid du Colombier goto out;
10414e5f5f32SDavid du Colombier last = rrcopy(rp, last);
10427dd7cddfSDavid du Colombier }
10437dd7cddfSDavid du Colombier }
10447dd7cddfSDavid du Colombier if(first)
10457dd7cddfSDavid du Colombier goto out;
10467dd7cddfSDavid du Colombier
10477dd7cddfSDavid du Colombier /* try for an unauthoritative db entry */
10487dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
10497dd7cddfSDavid du Colombier if(rp->db)
10507dd7cddfSDavid du Colombier if(tsame(type, rp->type))
10517dd7cddfSDavid du Colombier last = rrcopy(rp, last);
10527dd7cddfSDavid du Colombier }
10537dd7cddfSDavid du Colombier if(first)
10547dd7cddfSDavid du Colombier goto out;
10557dd7cddfSDavid du Colombier
10567dd7cddfSDavid du Colombier /* otherwise, settle for anything we got (except for negative caches) */
10574f8f669cSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next)
10587dd7cddfSDavid du Colombier if(tsame(type, rp->type)){
10597dd7cddfSDavid du Colombier if(rp->negative)
10607dd7cddfSDavid du Colombier goto out;
10617dd7cddfSDavid du Colombier last = rrcopy(rp, last);
10627dd7cddfSDavid du Colombier }
10637dd7cddfSDavid du Colombier
10647dd7cddfSDavid du Colombier out:
10657dd7cddfSDavid du Colombier unique(first);
1066c3617180SDavid du Colombier unlock(&dnlock);
10674f8f669cSDavid du Colombier // dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first);
1068a41547ffSDavid du Colombier // if (first)
1069a41547ffSDavid du Colombier // setmalloctag(first, getcallerpc(&dp));
10707dd7cddfSDavid du Colombier return first;
10713e12c5d1SDavid du Colombier }
10723e12c5d1SDavid du Colombier
10733e12c5d1SDavid du Colombier /*
10743e12c5d1SDavid du Colombier * convert an ascii RR type name to its integer representation
10753e12c5d1SDavid du Colombier */
10763e12c5d1SDavid du Colombier int
rrtype(char * atype)10773e12c5d1SDavid du Colombier rrtype(char *atype)
10783e12c5d1SDavid du Colombier {
10793e12c5d1SDavid du Colombier int i;
10803e12c5d1SDavid du Colombier
1081219b2ee8SDavid du Colombier for(i = 0; i <= Tall; i++)
10823e12c5d1SDavid du Colombier if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
10833e12c5d1SDavid du Colombier return i;
10847dd7cddfSDavid du Colombier
10854f8f669cSDavid du Colombier /* make any a synonym for all */
10867dd7cddfSDavid du Colombier if(strcmp(atype, "any") == 0)
10877dd7cddfSDavid du Colombier return Tall;
1088d9924332SDavid du Colombier else if(isascii(atype[0]) && isdigit(atype[0]))
10893e12c5d1SDavid du Colombier return atoi(atype);
1090d9924332SDavid du Colombier else
1091d9924332SDavid du Colombier return -1;
10923e12c5d1SDavid du Colombier }
10933e12c5d1SDavid du Colombier
10943e12c5d1SDavid du Colombier /*
10955d459b5aSDavid du Colombier * return 0 if not a supported rr type
10965d459b5aSDavid du Colombier */
10975d459b5aSDavid du Colombier int
rrsupported(int type)10985d459b5aSDavid du Colombier rrsupported(int type)
10995d459b5aSDavid du Colombier {
11005d459b5aSDavid du Colombier if(type < 0 || type >Tall)
11015d459b5aSDavid du Colombier return 0;
11024f8f669cSDavid du Colombier return rrtname[type] != nil;
11035d459b5aSDavid du Colombier }
11045d459b5aSDavid du Colombier
11055d459b5aSDavid du Colombier /*
1106219b2ee8SDavid du Colombier * compare 2 types
1107219b2ee8SDavid du Colombier */
1108219b2ee8SDavid du Colombier int
tsame(int t1,int t2)1109219b2ee8SDavid du Colombier tsame(int t1, int t2)
1110219b2ee8SDavid du Colombier {
1111219b2ee8SDavid du Colombier return t1 == t2 || t1 == Tall;
1112219b2ee8SDavid du Colombier }
1113219b2ee8SDavid du Colombier
1114219b2ee8SDavid du Colombier /*
11157dd7cddfSDavid du Colombier * Add resource records to a list, duplicate them if they are cached
1116530fef66SDavid du Colombier * RR's since these are shared. should be called with dnlock held
1117530fef66SDavid du Colombier * to avoid racing down the start chain.
11183e12c5d1SDavid du Colombier */
11193e12c5d1SDavid du Colombier RR*
rrcat(RR ** start,RR * rp)11207dd7cddfSDavid du Colombier rrcat(RR **start, RR *rp)
11213e12c5d1SDavid du Colombier {
1122225077b0SDavid du Colombier RR *olp, *nlp;
11233e12c5d1SDavid du Colombier RR **last;
11243e12c5d1SDavid du Colombier
11254faf7596SDavid du Colombier if (canlock(&dnlock))
11264faf7596SDavid du Colombier abort(); /* rrcat called with dnlock not held */
1127225077b0SDavid du Colombier /* check for duplicates */
1128225077b0SDavid du Colombier for (olp = *start; 0 && olp; olp = olp->next)
1129225077b0SDavid du Colombier for (nlp = rp; nlp; nlp = nlp->next)
1130225077b0SDavid du Colombier if (rrsame(nlp, olp))
1131225077b0SDavid du Colombier dnslog("rrcat: duplicate RR: %R", nlp);
1132225077b0SDavid du Colombier USED(olp);
1133225077b0SDavid du Colombier
11343e12c5d1SDavid du Colombier last = start;
11354f8f669cSDavid du Colombier while(*last != nil)
11363e12c5d1SDavid du Colombier last = &(*last)->next;
11373e12c5d1SDavid du Colombier
11387dd7cddfSDavid du Colombier *last = rp;
11397dd7cddfSDavid du Colombier return *start;
11403e12c5d1SDavid du Colombier }
11413e12c5d1SDavid du Colombier
11427dd7cddfSDavid du Colombier /*
11437dd7cddfSDavid du Colombier * remove negative cache rr's from an rr list
11447dd7cddfSDavid du Colombier */
11457dd7cddfSDavid du Colombier RR*
rrremneg(RR ** l)11467dd7cddfSDavid du Colombier rrremneg(RR **l)
11477dd7cddfSDavid du Colombier {
11487dd7cddfSDavid du Colombier RR **nl, *rp;
11497dd7cddfSDavid du Colombier RR *first;
11507dd7cddfSDavid du Colombier
115159f7772cSDavid du Colombier if (canlock(&dnlock))
115259f7772cSDavid du Colombier abort(); /* rrremneg called with dnlock not held */
11537dd7cddfSDavid du Colombier first = nil;
11547dd7cddfSDavid du Colombier nl = &first;
11557dd7cddfSDavid du Colombier while(*l != nil){
11567dd7cddfSDavid du Colombier rp = *l;
11577dd7cddfSDavid du Colombier if(rp->negative){
11587dd7cddfSDavid du Colombier *l = rp->next;
11597dd7cddfSDavid du Colombier *nl = rp;
11607dd7cddfSDavid du Colombier nl = &rp->next;
11617dd7cddfSDavid du Colombier *nl = nil;
11627dd7cddfSDavid du Colombier } else
116380ee5cbfSDavid du Colombier l = &rp->next;
11647dd7cddfSDavid du Colombier }
11657dd7cddfSDavid du Colombier
11667dd7cddfSDavid du Colombier return first;
11677dd7cddfSDavid du Colombier }
11687dd7cddfSDavid du Colombier
11697dd7cddfSDavid du Colombier /*
11707dd7cddfSDavid du Colombier * remove rr's of a particular type from an rr list
11717dd7cddfSDavid du Colombier */
11727dd7cddfSDavid du Colombier RR*
rrremtype(RR ** l,int type)11737dd7cddfSDavid du Colombier rrremtype(RR **l, int type)
11747dd7cddfSDavid du Colombier {
11754f8f669cSDavid du Colombier RR *first, *rp;
11764f8f669cSDavid du Colombier RR **nl;
11777dd7cddfSDavid du Colombier
11787dd7cddfSDavid du Colombier first = nil;
11797dd7cddfSDavid du Colombier nl = &first;
11807dd7cddfSDavid du Colombier while(*l != nil){
11817dd7cddfSDavid du Colombier rp = *l;
11827dd7cddfSDavid du Colombier if(rp->type == type){
11837dd7cddfSDavid du Colombier *l = rp->next;
11847dd7cddfSDavid du Colombier *nl = rp;
11857dd7cddfSDavid du Colombier nl = &rp->next;
11867dd7cddfSDavid du Colombier *nl = nil;
11877dd7cddfSDavid du Colombier } else
11887dd7cddfSDavid du Colombier l = &(*l)->next;
11897dd7cddfSDavid du Colombier }
11907dd7cddfSDavid du Colombier
11917dd7cddfSDavid du Colombier return first;
11923e12c5d1SDavid du Colombier }
11933e12c5d1SDavid du Colombier
11944f8f669cSDavid du Colombier static char *
dnname(DN * dn)11954f8f669cSDavid du Colombier dnname(DN *dn)
11964f8f669cSDavid du Colombier {
11974f8f669cSDavid du Colombier return dn? dn->name: "<null>";
11984f8f669cSDavid du Colombier }
11994f8f669cSDavid du Colombier
12003e12c5d1SDavid du Colombier /*
12013e12c5d1SDavid du Colombier * print conversion for rr records
12023e12c5d1SDavid du Colombier */
12033e12c5d1SDavid du Colombier int
rrfmt(Fmt * f)12049a747e4fSDavid du Colombier rrfmt(Fmt *f)
12053e12c5d1SDavid du Colombier {
12066b0d5c8bSDavid du Colombier int rv;
12074f8f669cSDavid du Colombier char *strp;
12086b0d5c8bSDavid du Colombier char buf[Domlen];
12094f8f669cSDavid du Colombier Fmt fstr;
12104f8f669cSDavid du Colombier RR *rp;
1211dc5a79c1SDavid du Colombier Server *s;
12124f8f669cSDavid du Colombier SOA *soa;
12134f8f669cSDavid du Colombier Srv *srv;
121460845620SDavid du Colombier Txt *t;
12153e12c5d1SDavid du Colombier
12169a747e4fSDavid du Colombier fmtstrinit(&fstr);
12179a747e4fSDavid du Colombier
12189a747e4fSDavid du Colombier rp = va_arg(f->args, RR*);
12194f8f669cSDavid du Colombier if(rp == nil){
12209a747e4fSDavid du Colombier fmtprint(&fstr, "<null>");
1221219b2ee8SDavid du Colombier goto out;
1222219b2ee8SDavid du Colombier }
1223219b2ee8SDavid du Colombier
12244f8f669cSDavid du Colombier fmtprint(&fstr, "%s %s", dnname(rp->owner),
12259a747e4fSDavid du Colombier rrname(rp->type, buf, sizeof buf));
12267dd7cddfSDavid du Colombier
12277dd7cddfSDavid du Colombier if(rp->negative){
12289a747e4fSDavid du Colombier fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);
12297dd7cddfSDavid du Colombier goto out;
12307dd7cddfSDavid du Colombier }
12313e12c5d1SDavid du Colombier
12323e12c5d1SDavid du Colombier switch(rp->type){
12333e12c5d1SDavid du Colombier case Thinfo:
12344f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os));
12353e12c5d1SDavid du Colombier break;
12363e12c5d1SDavid du Colombier case Tcname:
12373e12c5d1SDavid du Colombier case Tmb:
12383e12c5d1SDavid du Colombier case Tmd:
12393e12c5d1SDavid du Colombier case Tmf:
12403e12c5d1SDavid du Colombier case Tns:
12414f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->host));
12423e12c5d1SDavid du Colombier break;
12433e12c5d1SDavid du Colombier case Tmg:
12443e12c5d1SDavid du Colombier case Tmr:
12454f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->mb));
12463e12c5d1SDavid du Colombier break;
12473e12c5d1SDavid du Colombier case Tminfo:
12484f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb));
12493e12c5d1SDavid du Colombier break;
12503e12c5d1SDavid du Colombier case Tmx:
12514f8f669cSDavid du Colombier fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host));
12523e12c5d1SDavid du Colombier break;
12533e12c5d1SDavid du Colombier case Ta:
12545d459b5aSDavid du Colombier case Taaaa:
12554f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ip));
12563e12c5d1SDavid du Colombier break;
12573e12c5d1SDavid du Colombier case Tptr:
12584f8f669cSDavid du Colombier // fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr),
12594f8f669cSDavid du Colombier // rp->ptr? rp->ptr->ordinal: "<null>");
12604f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s", dnname(rp->ptr));
12613e12c5d1SDavid du Colombier break;
12623e12c5d1SDavid du Colombier case Tsoa:
12634f8f669cSDavid du Colombier soa = rp->soa;
12644f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud",
12654f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb),
12664f8f669cSDavid du Colombier (soa? soa->serial: 0),
12674f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0),
12684f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0));
12694f8f669cSDavid du Colombier if (soa)
12704f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next)
1271dc5a79c1SDavid du Colombier fmtprint(&fstr, " %s", s->name);
12723e12c5d1SDavid du Colombier break;
12734f8f669cSDavid du Colombier case Tsrv:
12744f8f669cSDavid du Colombier srv = rp->srv;
12754f8f669cSDavid du Colombier fmtprint(&fstr, "\t%ud %ud %ud %s",
12764f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0),
1277225077b0SDavid du Colombier rp->port, dnname(rp->host));
12784f8f669cSDavid du Colombier break;
12799a747e4fSDavid du Colombier case Tnull:
12804f8f669cSDavid du Colombier if (rp->null == nil)
12814f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null>");
12824f8f669cSDavid du Colombier else
12834f8f669cSDavid du Colombier fmtprint(&fstr, "\t%.*H", rp->null->dlen,
12844f8f669cSDavid du Colombier rp->null->data);
12859a747e4fSDavid du Colombier break;
12867dd7cddfSDavid du Colombier case Ttxt:
128760845620SDavid du Colombier fmtprint(&fstr, "\t");
128860845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next)
128960845620SDavid du Colombier fmtprint(&fstr, "%s", t->p);
12907dd7cddfSDavid du Colombier break;
12917dd7cddfSDavid du Colombier case Trp:
12924f8f669cSDavid du Colombier fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp));
12937dd7cddfSDavid du Colombier break;
12947dd7cddfSDavid du Colombier case Tkey:
12954f8f669cSDavid du Colombier if (rp->key == nil)
12964f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>");
12974f8f669cSDavid du Colombier else
12984f8f669cSDavid du Colombier fmtprint(&fstr, "\t%d %d %d", rp->key->flags,
12994f8f669cSDavid du Colombier rp->key->proto, rp->key->alg);
13007dd7cddfSDavid du Colombier break;
13017dd7cddfSDavid du Colombier case Tsig:
13024f8f669cSDavid du Colombier if (rp->sig == nil)
13034f8f669cSDavid du Colombier fmtprint(&fstr,
13044f8f669cSDavid du Colombier "\t<null> <null> <null> <null> <null> <null> <null> <null>");
13054f8f669cSDavid du Colombier else
13069a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
13074f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels,
13084f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep,
13094f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer));
13107dd7cddfSDavid du Colombier break;
13117dd7cddfSDavid du Colombier case Tcert:
13124f8f669cSDavid du Colombier if (rp->cert == nil)
13134f8f669cSDavid du Colombier fmtprint(&fstr, "\t<null> <null> <null>");
13144f8f669cSDavid du Colombier else
13159a747e4fSDavid du Colombier fmtprint(&fstr, "\t%d %d %d",
13164f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg);
13173e12c5d1SDavid du Colombier break;
13183e12c5d1SDavid du Colombier }
1319219b2ee8SDavid du Colombier out:
13209a747e4fSDavid du Colombier strp = fmtstrflush(&fstr);
13219a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp);
13229a747e4fSDavid du Colombier free(strp);
13239a747e4fSDavid du Colombier return rv;
13243e12c5d1SDavid du Colombier }
13253e12c5d1SDavid du Colombier
13263e12c5d1SDavid du Colombier /*
13277dd7cddfSDavid du Colombier * print conversion for rr records in attribute value form
13287dd7cddfSDavid du Colombier */
13297dd7cddfSDavid du Colombier int
rravfmt(Fmt * f)13309a747e4fSDavid du Colombier rravfmt(Fmt *f)
13317dd7cddfSDavid du Colombier {
13324f8f669cSDavid du Colombier int rv, quote;
13339a747e4fSDavid du Colombier char *strp;
13349a747e4fSDavid du Colombier Fmt fstr;
13354f8f669cSDavid du Colombier RR *rp;
1336dc5a79c1SDavid du Colombier Server *s;
13374f8f669cSDavid du Colombier SOA *soa;
13384f8f669cSDavid du Colombier Srv *srv;
133960845620SDavid du Colombier Txt *t;
13407dd7cddfSDavid du Colombier
13419a747e4fSDavid du Colombier fmtstrinit(&fstr);
13429a747e4fSDavid du Colombier
13439a747e4fSDavid du Colombier rp = va_arg(f->args, RR*);
13444f8f669cSDavid du Colombier if(rp == nil){
13459a747e4fSDavid du Colombier fmtprint(&fstr, "<null>");
13467dd7cddfSDavid du Colombier goto out;
13477dd7cddfSDavid du Colombier }
13487dd7cddfSDavid du Colombier
13497dd7cddfSDavid du Colombier if(rp->type == Tptr)
13504f8f669cSDavid du Colombier fmtprint(&fstr, "ptr=%s", dnname(rp->owner));
13517dd7cddfSDavid du Colombier else
13524f8f669cSDavid du Colombier fmtprint(&fstr, "dom=%s", dnname(rp->owner));
13537dd7cddfSDavid du Colombier
13547dd7cddfSDavid du Colombier switch(rp->type){
13557dd7cddfSDavid du Colombier case Thinfo:
13564f8f669cSDavid du Colombier fmtprint(&fstr, " cpu=%s os=%s",
13574f8f669cSDavid du Colombier dnname(rp->cpu), dnname(rp->os));
13587dd7cddfSDavid du Colombier break;
13597dd7cddfSDavid du Colombier case Tcname:
13604f8f669cSDavid du Colombier fmtprint(&fstr, " cname=%s", dnname(rp->host));
13617dd7cddfSDavid du Colombier break;
13627dd7cddfSDavid du Colombier case Tmb:
13637dd7cddfSDavid du Colombier case Tmd:
13647dd7cddfSDavid du Colombier case Tmf:
13654f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->host));
13667dd7cddfSDavid du Colombier break;
13677dd7cddfSDavid du Colombier case Tns:
13684f8f669cSDavid du Colombier fmtprint(&fstr, " ns=%s", dnname(rp->host));
13697dd7cddfSDavid du Colombier break;
13707dd7cddfSDavid du Colombier case Tmg:
13717dd7cddfSDavid du Colombier case Tmr:
13724f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s", dnname(rp->mb));
13737dd7cddfSDavid du Colombier break;
13747dd7cddfSDavid du Colombier case Tminfo:
13754f8f669cSDavid du Colombier fmtprint(&fstr, " mbox=%s mbox=%s",
13764f8f669cSDavid du Colombier dnname(rp->mb), dnname(rp->rmb));
13777dd7cddfSDavid du Colombier break;
13787dd7cddfSDavid du Colombier case Tmx:
13794f8f669cSDavid du Colombier fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host));
13807dd7cddfSDavid du Colombier break;
13817dd7cddfSDavid du Colombier case Ta:
13825d459b5aSDavid du Colombier case Taaaa:
13834f8f669cSDavid du Colombier fmtprint(&fstr, " ip=%s", dnname(rp->ip));
13847dd7cddfSDavid du Colombier break;
13857dd7cddfSDavid du Colombier case Tptr:
13864f8f669cSDavid du Colombier fmtprint(&fstr, " dom=%s", dnname(rp->ptr));
13877dd7cddfSDavid du Colombier break;
13887dd7cddfSDavid du Colombier case Tsoa:
13894f8f669cSDavid du Colombier soa = rp->soa;
13904f8f669cSDavid du Colombier fmtprint(&fstr,
13914f8f669cSDavid du Colombier " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
13924f8f669cSDavid du Colombier dnname(rp->host), dnname(rp->rmb),
13934f8f669cSDavid du Colombier (soa? soa->serial: 0),
13944f8f669cSDavid du Colombier (soa? soa->refresh: 0), (soa? soa->retry: 0),
13954f8f669cSDavid du Colombier (soa? soa->expire: 0), (soa? soa->minttl: 0));
13964f8f669cSDavid du Colombier for(s = soa->slaves; s != nil; s = s->next)
1397dc5a79c1SDavid du Colombier fmtprint(&fstr, " dnsslave=%s", s->name);
13987dd7cddfSDavid du Colombier break;
13994f8f669cSDavid du Colombier case Tsrv:
14004f8f669cSDavid du Colombier srv = rp->srv;
14014f8f669cSDavid du Colombier fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s",
14024f8f669cSDavid du Colombier (srv? srv->pri: 0), (srv? srv->weight: 0),
1403225077b0SDavid du Colombier rp->port, dnname(rp->host));
14044f8f669cSDavid du Colombier break;
14059a747e4fSDavid du Colombier case Tnull:
14064f8f669cSDavid du Colombier if (rp->null == nil)
14074f8f669cSDavid du Colombier fmtprint(&fstr, " null=<null>");
14084f8f669cSDavid du Colombier else
14094f8f669cSDavid du Colombier fmtprint(&fstr, " null=%.*H", rp->null->dlen,
14104f8f669cSDavid du Colombier rp->null->data);
14119a747e4fSDavid du Colombier break;
14127dd7cddfSDavid du Colombier case Ttxt:
141360845620SDavid du Colombier fmtprint(&fstr, " txt=");
141460845620SDavid du Colombier quote = 0;
141560845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next)
141660845620SDavid du Colombier if(strchr(t->p, ' '))
141760845620SDavid du Colombier quote = 1;
141860845620SDavid du Colombier if(quote)
141960845620SDavid du Colombier fmtprint(&fstr, "\"");
142060845620SDavid du Colombier for(t = rp->txt; t != nil; t = t->next)
142160845620SDavid du Colombier fmtprint(&fstr, "%s", t->p);
142260845620SDavid du Colombier if(quote)
142360845620SDavid du Colombier fmtprint(&fstr, "\"");
14247dd7cddfSDavid du Colombier break;
14257dd7cddfSDavid du Colombier case Trp:
14264f8f669cSDavid du Colombier fmtprint(&fstr, " rp=%s txt=%s",
14274f8f669cSDavid du Colombier dnname(rp->rmb), dnname(rp->rp));
14287dd7cddfSDavid du Colombier break;
14297dd7cddfSDavid du Colombier case Tkey:
14304f8f669cSDavid du Colombier if (rp->key == nil)
14314f8f669cSDavid du Colombier fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>");
14324f8f669cSDavid du Colombier else
14339a747e4fSDavid du Colombier fmtprint(&fstr, " flags=%d proto=%d alg=%d",
14347dd7cddfSDavid du Colombier rp->key->flags, rp->key->proto, rp->key->alg);
14357dd7cddfSDavid du Colombier break;
14367dd7cddfSDavid du Colombier case Tsig:
14374f8f669cSDavid du Colombier if (rp->sig == nil)
14384f8f669cSDavid du Colombier fmtprint(&fstr,
14394f8f669cSDavid du Colombier " type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>");
14404f8f669cSDavid du Colombier else
14414f8f669cSDavid du Colombier fmtprint(&fstr,
14424f8f669cSDavid du Colombier " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
14434f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels,
14444f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep,
14454f8f669cSDavid du Colombier rp->sig->tag, dnname(rp->sig->signer));
14467dd7cddfSDavid du Colombier break;
14477dd7cddfSDavid du Colombier case Tcert:
14484f8f669cSDavid du Colombier if (rp->cert == nil)
14494f8f669cSDavid du Colombier fmtprint(&fstr, " type=<null> tag=<null> alg=<null>");
14504f8f669cSDavid du Colombier else
14519a747e4fSDavid du Colombier fmtprint(&fstr, " type=%d tag=%d alg=%d",
14524f8f669cSDavid du Colombier rp->cert->type, rp->cert->tag, rp->cert->alg);
14537dd7cddfSDavid du Colombier break;
14547dd7cddfSDavid du Colombier }
14557dd7cddfSDavid du Colombier out:
14569a747e4fSDavid du Colombier strp = fmtstrflush(&fstr);
14579a747e4fSDavid du Colombier rv = fmtstrcpy(f, strp);
14589a747e4fSDavid du Colombier free(strp);
14599a747e4fSDavid du Colombier return rv;
14603e12c5d1SDavid du Colombier }
14617dd7cddfSDavid du Colombier
14627dd7cddfSDavid du Colombier void
warning(char * fmt,...)14637dd7cddfSDavid du Colombier warning(char *fmt, ...)
14647dd7cddfSDavid du Colombier {
14654f8f669cSDavid du Colombier char dnserr[256];
14667dd7cddfSDavid du Colombier va_list arg;
14677dd7cddfSDavid du Colombier
14687dd7cddfSDavid du Colombier va_start(arg, fmt);
14699a747e4fSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
14707dd7cddfSDavid du Colombier va_end(arg);
14714f8f669cSDavid du Colombier syslog(1, logfile, dnserr); /* on console too */
14724f8f669cSDavid du Colombier }
14734f8f669cSDavid du Colombier
14744f8f669cSDavid du Colombier void
dnslog(char * fmt,...)14754f8f669cSDavid du Colombier dnslog(char *fmt, ...)
14764f8f669cSDavid du Colombier {
14774f8f669cSDavid du Colombier char dnserr[256];
14784f8f669cSDavid du Colombier va_list arg;
14794f8f669cSDavid du Colombier
14804f8f669cSDavid du Colombier va_start(arg, fmt);
14814f8f669cSDavid du Colombier vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
14824f8f669cSDavid du Colombier va_end(arg);
14834f8f669cSDavid du Colombier syslog(0, logfile, dnserr);
14844f8f669cSDavid du Colombier }
14854f8f669cSDavid du Colombier
14864f8f669cSDavid du Colombier /*
14874f8f669cSDavid du Colombier * based on libthread's threadsetname, but drags in less library code.
14884f8f669cSDavid du Colombier * actually just sets the arguments displayed.
14894f8f669cSDavid du Colombier */
14904f8f669cSDavid du Colombier void
procsetname(char * fmt,...)14914f8f669cSDavid du Colombier procsetname(char *fmt, ...)
14924f8f669cSDavid du Colombier {
14934f8f669cSDavid du Colombier int fd;
14944f8f669cSDavid du Colombier char *cmdname;
14954f8f669cSDavid du Colombier char buf[128];
14964f8f669cSDavid du Colombier va_list arg;
14974f8f669cSDavid du Colombier
14984f8f669cSDavid du Colombier va_start(arg, fmt);
14994f8f669cSDavid du Colombier cmdname = vsmprint(fmt, arg);
15004f8f669cSDavid du Colombier va_end(arg);
15014f8f669cSDavid du Colombier if (cmdname == nil)
15024f8f669cSDavid du Colombier return;
15034f8f669cSDavid du Colombier snprint(buf, sizeof buf, "#p/%d/args", getpid());
15044f8f669cSDavid du Colombier if((fd = open(buf, OWRITE)) >= 0){
15054f8f669cSDavid du Colombier write(fd, cmdname, strlen(cmdname)+1);
15064f8f669cSDavid du Colombier close(fd);
15074f8f669cSDavid du Colombier }
15084f8f669cSDavid du Colombier free(cmdname);
15097dd7cddfSDavid du Colombier }
15107dd7cddfSDavid du Colombier
15117dd7cddfSDavid du Colombier /*
15127dd7cddfSDavid du Colombier * create a slave process to handle a request to avoid one request blocking
15137dd7cddfSDavid du Colombier * another
15147dd7cddfSDavid du Colombier */
15157dd7cddfSDavid du Colombier void
slave(Request * req)15167dd7cddfSDavid du Colombier slave(Request *req)
15177dd7cddfSDavid du Colombier {
1518a41547ffSDavid du Colombier int ppid, procs;
15197dd7cddfSDavid du Colombier
15207dd7cddfSDavid du Colombier if(req->isslave)
15217dd7cddfSDavid du Colombier return; /* we're already a slave process */
15227dd7cddfSDavid du Colombier
1523b4b9fc2fSDavid du Colombier /*
1524b4b9fc2fSDavid du Colombier * These calls to putactivity cannot block.
1525b4b9fc2fSDavid du Colombier * After getactivity(), the current process is counted
1526b4b9fc2fSDavid du Colombier * twice in dnvars.active (one will pass to the child).
1527b4b9fc2fSDavid du Colombier * If putactivity tries to wait for dnvars.active == 0,
1528b4b9fc2fSDavid du Colombier * it will never happen.
1529b4b9fc2fSDavid du Colombier */
1530b4b9fc2fSDavid du Colombier
15317dd7cddfSDavid du Colombier /* limit parallelism */
1532a41547ffSDavid du Colombier procs = getactivity(req, 1);
1533a41547ffSDavid du Colombier if (procs > stats.slavehiwat)
1534a41547ffSDavid du Colombier stats.slavehiwat = procs;
1535a41547ffSDavid du Colombier if(procs > Maxactive){
15364f8f669cSDavid du Colombier if(traceactivity)
15374f8f669cSDavid du Colombier dnslog("[%d] too much activity", getpid());
1538b4b9fc2fSDavid du Colombier putactivity(1);
15397dd7cddfSDavid du Colombier return;
15407dd7cddfSDavid du Colombier }
15417dd7cddfSDavid du Colombier
1542c73252aeSDavid du Colombier /*
1543c73252aeSDavid du Colombier * parent returns to main loop, child does the work.
1544c73252aeSDavid du Colombier * don't change note group.
1545c73252aeSDavid du Colombier */
1546b4b9fc2fSDavid du Colombier ppid = getpid();
1547c73252aeSDavid du Colombier switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
15487dd7cddfSDavid du Colombier case -1:
1549b4b9fc2fSDavid du Colombier putactivity(1);
15507dd7cddfSDavid du Colombier break;
15517dd7cddfSDavid du Colombier case 0:
15524f8f669cSDavid du Colombier procsetname("request slave of pid %d", ppid);
15534f8f669cSDavid du Colombier if(traceactivity)
1554a41547ffSDavid du Colombier dnslog("[%d] take activity from %d", getpid(), ppid);
15554f8f669cSDavid du Colombier req->isslave = 1; /* why not `= getpid()'? */
15567dd7cddfSDavid du Colombier break;
15577dd7cddfSDavid du Colombier default:
15584f8f669cSDavid du Colombier /*
15594f8f669cSDavid du Colombier * this relies on rfork producing separate, initially-identical
15604f8f669cSDavid du Colombier * stacks, thus giving us two copies of `req', one in each
15614f8f669cSDavid du Colombier * process.
15624f8f669cSDavid du Colombier */
15636aaebd7dSDavid du Colombier alarm(0);
15647dd7cddfSDavid du Colombier longjmp(req->mret, 1);
15657dd7cddfSDavid du Colombier }
15667dd7cddfSDavid du Colombier }
15677dd7cddfSDavid du Colombier
15687dd7cddfSDavid du Colombier /*
15697dd7cddfSDavid du Colombier * chasing down double free's
15707dd7cddfSDavid du Colombier */
15717dd7cddfSDavid du Colombier void
dncheck(void * p,int dolock)15727dd7cddfSDavid du Colombier dncheck(void *p, int dolock)
15737dd7cddfSDavid du Colombier {
15747dd7cddfSDavid du Colombier int i;
15757dd7cddfSDavid du Colombier DN *dp;
15767dd7cddfSDavid du Colombier RR *rp;
15777dd7cddfSDavid du Colombier
15787dd7cddfSDavid du Colombier if(p != nil){
15797dd7cddfSDavid du Colombier dp = p;
15807dd7cddfSDavid du Colombier assert(dp->magic == DNmagic);
15817dd7cddfSDavid du Colombier }
15827dd7cddfSDavid du Colombier
15837dd7cddfSDavid du Colombier if(!testing)
15847dd7cddfSDavid du Colombier return;
15857dd7cddfSDavid du Colombier
15867dd7cddfSDavid du Colombier if(dolock)
15877dd7cddfSDavid du Colombier lock(&dnlock);
15889a747e4fSDavid du Colombier poolcheck(mainmem);
15897dd7cddfSDavid du Colombier for(i = 0; i < HTLEN; i++)
15907dd7cddfSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next){
15917dd7cddfSDavid du Colombier assert(dp != p);
15927dd7cddfSDavid du Colombier assert(dp->magic == DNmagic);
15937dd7cddfSDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
15947dd7cddfSDavid du Colombier assert(rp->magic == RRmagic);
15957dd7cddfSDavid du Colombier assert(rp->cached);
15967dd7cddfSDavid du Colombier assert(rp->owner == dp);
1597225077b0SDavid du Colombier /* also check for duplicate rrs */
15984f927735SDavid du Colombier if (dolock && rronlist(rp, rp->next)) {
15994f927735SDavid du Colombier dnslog("%R duplicates its next chain "
16004f927735SDavid du Colombier "(%R); aborting", rp, rp->next);
16014f927735SDavid du Colombier abort();
16024f927735SDavid du Colombier }
16037dd7cddfSDavid du Colombier }
16047dd7cddfSDavid du Colombier }
16057dd7cddfSDavid du Colombier if(dolock)
16067dd7cddfSDavid du Colombier unlock(&dnlock);
16077dd7cddfSDavid du Colombier }
16087dd7cddfSDavid du Colombier
16097dd7cddfSDavid du Colombier static int
rrequiv(RR * r1,RR * r2)16107dd7cddfSDavid du Colombier rrequiv(RR *r1, RR *r2)
16117dd7cddfSDavid du Colombier {
16127dd7cddfSDavid du Colombier return r1->owner == r2->owner
16137dd7cddfSDavid du Colombier && r1->type == r2->type
16147dd7cddfSDavid du Colombier && r1->arg0 == r2->arg0
1615225077b0SDavid du Colombier && r1->arg1 == r2->arg1;
16167dd7cddfSDavid du Colombier }
16177dd7cddfSDavid du Colombier
1618c3617180SDavid du Colombier /* called with dnlock held */
16197dd7cddfSDavid du Colombier void
unique(RR * rp)16207dd7cddfSDavid du Colombier unique(RR *rp)
16217dd7cddfSDavid du Colombier {
16227dd7cddfSDavid du Colombier RR **l, *nrp;
16237dd7cddfSDavid du Colombier
16247dd7cddfSDavid du Colombier for(; rp; rp = rp->next){
16257dd7cddfSDavid du Colombier l = &rp->next;
16264f8f669cSDavid du Colombier for(nrp = *l; nrp; nrp = *l)
16277dd7cddfSDavid du Colombier if(rrequiv(rp, nrp)){
16287dd7cddfSDavid du Colombier *l = nrp->next;
16297dd7cddfSDavid du Colombier rrfree(nrp);
16307dd7cddfSDavid du Colombier } else
16317dd7cddfSDavid du Colombier l = &nrp->next;
16327dd7cddfSDavid du Colombier }
16337dd7cddfSDavid du Colombier }
16347dd7cddfSDavid du Colombier
16357dd7cddfSDavid du Colombier /*
16367dd7cddfSDavid du Colombier * true if second domain is subsumed by the first
16377dd7cddfSDavid du Colombier */
16387dd7cddfSDavid du Colombier int
subsume(char * higher,char * lower)16397dd7cddfSDavid du Colombier subsume(char *higher, char *lower)
16407dd7cddfSDavid du Colombier {
16417dd7cddfSDavid du Colombier int hn, ln;
16427dd7cddfSDavid du Colombier
16437dd7cddfSDavid du Colombier ln = strlen(lower);
16447dd7cddfSDavid du Colombier hn = strlen(higher);
16454f8f669cSDavid du Colombier if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 ||
16464f8f669cSDavid du Colombier ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
16477dd7cddfSDavid du Colombier return 0;
16487dd7cddfSDavid du Colombier return 1;
16497dd7cddfSDavid du Colombier }
16507dd7cddfSDavid du Colombier
16517dd7cddfSDavid du Colombier /*
16527dd7cddfSDavid du Colombier * randomize the order we return items to provide some
16535d459b5aSDavid du Colombier * load balancing for servers.
16545d459b5aSDavid du Colombier *
16555d459b5aSDavid du Colombier * only randomize the first class of entries
16567dd7cddfSDavid du Colombier */
16577dd7cddfSDavid du Colombier RR*
randomize(RR * rp)16587dd7cddfSDavid du Colombier randomize(RR *rp)
16597dd7cddfSDavid du Colombier {
16605d459b5aSDavid du Colombier RR *first, *last, *x, *base;
16617dd7cddfSDavid du Colombier ulong n;
16627dd7cddfSDavid du Colombier
16637dd7cddfSDavid du Colombier if(rp == nil || rp->next == nil)
16647dd7cddfSDavid du Colombier return rp;
16657dd7cddfSDavid du Colombier
16663cbadd90SDavid du Colombier /* just randomize addresses, mx's and ns's */
16677dd7cddfSDavid du Colombier for(x = rp; x; x = x->next)
1668adb31a62SDavid du Colombier if(x->type != Ta && x->type != Taaaa &&
1669adb31a62SDavid du Colombier x->type != Tmx && x->type != Tns)
16707dd7cddfSDavid du Colombier return rp;
16717dd7cddfSDavid du Colombier
16725d459b5aSDavid du Colombier base = rp;
16735d459b5aSDavid du Colombier
16747dd7cddfSDavid du Colombier n = rand();
16757dd7cddfSDavid du Colombier last = first = nil;
16767dd7cddfSDavid du Colombier while(rp != nil){
16775d459b5aSDavid du Colombier /* stop randomizing if we've moved past our class */
16785d459b5aSDavid du Colombier if(base->auth != rp->auth || base->db != rp->db){
16795d459b5aSDavid du Colombier last->next = rp;
16805d459b5aSDavid du Colombier break;
16815d459b5aSDavid du Colombier }
16825d459b5aSDavid du Colombier
16837dd7cddfSDavid du Colombier /* unchain */
16847dd7cddfSDavid du Colombier x = rp;
16857dd7cddfSDavid du Colombier rp = x->next;
16867dd7cddfSDavid du Colombier x->next = nil;
16877dd7cddfSDavid du Colombier
1688225077b0SDavid du Colombier if(n&1){
16897dd7cddfSDavid du Colombier /* add to tail */
16907dd7cddfSDavid du Colombier if(last == nil)
16917dd7cddfSDavid du Colombier first = x;
16927dd7cddfSDavid du Colombier else
16937dd7cddfSDavid du Colombier last->next = x;
16947dd7cddfSDavid du Colombier last = x;
16957dd7cddfSDavid du Colombier } else {
16967dd7cddfSDavid du Colombier /* add to head */
16977dd7cddfSDavid du Colombier if(last == nil)
16987dd7cddfSDavid du Colombier last = x;
16997dd7cddfSDavid du Colombier x->next = first;
17007dd7cddfSDavid du Colombier first = x;
17017dd7cddfSDavid du Colombier }
17027dd7cddfSDavid du Colombier
17037dd7cddfSDavid du Colombier /* reroll the dice */
17047dd7cddfSDavid du Colombier n >>= 1;
17057dd7cddfSDavid du Colombier }
17063cbadd90SDavid du Colombier
17077dd7cddfSDavid du Colombier return first;
17087dd7cddfSDavid du Colombier }
170959cc4ca5SDavid du Colombier
17109a747e4fSDavid du Colombier static int
sencodefmt(Fmt * f)17119a747e4fSDavid du Colombier sencodefmt(Fmt *f)
171259cc4ca5SDavid du Colombier {
17134f8f669cSDavid du Colombier int i, len, ilen, rv;
17144f8f669cSDavid du Colombier char *out, *buf;
17159a747e4fSDavid du Colombier uchar *b;
17164f8f669cSDavid du Colombier char obuf[64]; /* rsc optimization */
171759cc4ca5SDavid du Colombier
17189a747e4fSDavid du Colombier if(!(f->flags&FmtPrec) || f->prec < 1)
17199a747e4fSDavid du Colombier goto error;
17209a747e4fSDavid du Colombier
17219a747e4fSDavid du Colombier b = va_arg(f->args, uchar*);
17229a747e4fSDavid du Colombier if(b == nil)
17239a747e4fSDavid du Colombier goto error;
17249a747e4fSDavid du Colombier
17259a747e4fSDavid du Colombier /* if it's a printable, go for it */
17269a747e4fSDavid du Colombier len = f->prec;
17279a747e4fSDavid du Colombier for(i = 0; i < len; i++)
17289a747e4fSDavid du Colombier if(!isprint(b[i]))
17299a747e4fSDavid du Colombier break;
17309a747e4fSDavid du Colombier if(i == len){
17319a747e4fSDavid du Colombier if(len >= sizeof obuf)
17329a747e4fSDavid du Colombier len = sizeof(obuf)-1;
17339a747e4fSDavid du Colombier memmove(obuf, b, len);
17349a747e4fSDavid du Colombier obuf[len] = 0;
17359a747e4fSDavid du Colombier fmtstrcpy(f, obuf);
17369a747e4fSDavid du Colombier return 0;
173759cc4ca5SDavid du Colombier }
173859cc4ca5SDavid du Colombier
17399a747e4fSDavid du Colombier ilen = f->prec;
17409a747e4fSDavid du Colombier f->prec = 0;
17419a747e4fSDavid du Colombier f->flags &= ~FmtPrec;
17429a747e4fSDavid du Colombier switch(f->r){
17439a747e4fSDavid du Colombier case '<':
17449a747e4fSDavid du Colombier len = (8*ilen+4)/5 + 3;
17459a747e4fSDavid du Colombier break;
17469a747e4fSDavid du Colombier case '[':
17479a747e4fSDavid du Colombier len = (8*ilen+5)/6 + 4;
17489a747e4fSDavid du Colombier break;
17499a747e4fSDavid du Colombier case 'H':
17509a747e4fSDavid du Colombier len = 2*ilen + 1;
17519a747e4fSDavid du Colombier break;
17529a747e4fSDavid du Colombier default:
17539a747e4fSDavid du Colombier goto error;
17549a747e4fSDavid du Colombier }
175559cc4ca5SDavid du Colombier
17569a747e4fSDavid du Colombier if(len > sizeof(obuf)){
17579a747e4fSDavid du Colombier buf = malloc(len);
17589a747e4fSDavid du Colombier if(buf == nil)
17599a747e4fSDavid du Colombier goto error;
17609a747e4fSDavid du Colombier } else
17619a747e4fSDavid du Colombier buf = obuf;
17629a747e4fSDavid du Colombier
17634f8f669cSDavid du Colombier /* convert */
17649a747e4fSDavid du Colombier out = buf;
17659a747e4fSDavid du Colombier switch(f->r){
17669a747e4fSDavid du Colombier case '<':
17679a747e4fSDavid du Colombier rv = enc32(out, len, b, ilen);
17689a747e4fSDavid du Colombier break;
17699a747e4fSDavid du Colombier case '[':
17709a747e4fSDavid du Colombier rv = enc64(out, len, b, ilen);
17719a747e4fSDavid du Colombier break;
17729a747e4fSDavid du Colombier case 'H':
17739a747e4fSDavid du Colombier rv = enc16(out, len, b, ilen);
17749a747e4fSDavid du Colombier break;
17759a747e4fSDavid du Colombier default:
17769a747e4fSDavid du Colombier rv = -1;
17779a747e4fSDavid du Colombier break;
17789a747e4fSDavid du Colombier }
17799a747e4fSDavid du Colombier if(rv < 0)
17809a747e4fSDavid du Colombier goto error;
17819a747e4fSDavid du Colombier
17829a747e4fSDavid du Colombier fmtstrcpy(f, buf);
17839a747e4fSDavid du Colombier if(buf != obuf)
17849a747e4fSDavid du Colombier free(buf);
17859a747e4fSDavid du Colombier return 0;
17869a747e4fSDavid du Colombier
17879a747e4fSDavid du Colombier error:
17889a747e4fSDavid du Colombier return fmtstrcpy(f, "<encodefmt>");
17899a747e4fSDavid du Colombier }
17909a747e4fSDavid du Colombier
17919a747e4fSDavid du Colombier void*
emalloc(int size)17929a747e4fSDavid du Colombier emalloc(int size)
17939a747e4fSDavid du Colombier {
17949a747e4fSDavid du Colombier char *x;
17959a747e4fSDavid du Colombier
17969a747e4fSDavid du Colombier x = mallocz(size, 1);
17979a747e4fSDavid du Colombier if(x == nil)
17989a747e4fSDavid du Colombier abort();
179934f77ae3SDavid du Colombier setmalloctag(x, getcallerpc(&size));
18009a747e4fSDavid du Colombier return x;
18019a747e4fSDavid du Colombier }
18029a747e4fSDavid du Colombier
18039a747e4fSDavid du Colombier char*
estrdup(char * s)18049a747e4fSDavid du Colombier estrdup(char *s)
18059a747e4fSDavid du Colombier {
18069a747e4fSDavid du Colombier int size;
18079a747e4fSDavid du Colombier char *p;
18089a747e4fSDavid du Colombier
18099a747e4fSDavid du Colombier size = strlen(s)+1;
18109a747e4fSDavid du Colombier p = mallocz(size, 0);
18119a747e4fSDavid du Colombier if(p == nil)
18129a747e4fSDavid du Colombier abort();
18139a747e4fSDavid du Colombier memmove(p, s, size);
181434f77ae3SDavid du Colombier setmalloctag(p, getcallerpc(&s));
18159a747e4fSDavid du Colombier return p;
181659cc4ca5SDavid du Colombier }
18173ff48bf5SDavid du Colombier
18183ff48bf5SDavid du Colombier /*
18193ff48bf5SDavid du Colombier * create a pointer record
18203ff48bf5SDavid du Colombier */
18213ff48bf5SDavid du Colombier static RR*
mkptr(DN * dp,char * ptr,ulong ttl)18223ff48bf5SDavid du Colombier mkptr(DN *dp, char *ptr, ulong ttl)
18233ff48bf5SDavid du Colombier {
18243ff48bf5SDavid du Colombier DN *ipdp;
18253ff48bf5SDavid du Colombier RR *rp;
18263ff48bf5SDavid du Colombier
18273ff48bf5SDavid du Colombier ipdp = dnlookup(ptr, Cin, 1);
18283ff48bf5SDavid du Colombier
18293ff48bf5SDavid du Colombier rp = rralloc(Tptr);
18303ff48bf5SDavid du Colombier rp->ptr = dp;
18313ff48bf5SDavid du Colombier rp->owner = ipdp;
18323ff48bf5SDavid du Colombier rp->db = 1;
18333ff48bf5SDavid du Colombier if(ttl)
18343ff48bf5SDavid du Colombier rp->ttl = ttl;
18353ff48bf5SDavid du Colombier return rp;
18363ff48bf5SDavid du Colombier }
18373ff48bf5SDavid du Colombier
183853874d13SDavid du Colombier void bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes);
183953874d13SDavid du Colombier
18403ff48bf5SDavid du Colombier /*
18413ff48bf5SDavid du Colombier * look for all ip addresses in this network and make
18423ff48bf5SDavid du Colombier * pointer records for them.
18433ff48bf5SDavid du Colombier */
18443ff48bf5SDavid du Colombier void
dnptr(uchar * net,uchar * mask,char * dom,int forwtype,int subdoms,int ttl)184553874d13SDavid du Colombier dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl)
18463ff48bf5SDavid du Colombier {
184753874d13SDavid du Colombier int i, j, len;
18484f8f669cSDavid du Colombier char *p, *e;
18494f8f669cSDavid du Colombier char ptr[Domlen];
185053874d13SDavid du Colombier uchar *ipp;
18514f8f669cSDavid du Colombier uchar ip[IPaddrlen], nnet[IPaddrlen];
185253874d13SDavid du Colombier uchar nibip[IPaddrlen*2];
18533ff48bf5SDavid du Colombier DN *dp;
18543ff48bf5SDavid du Colombier RR *rp, *nrp, *first, **l;
18553ff48bf5SDavid du Colombier
18563ff48bf5SDavid du Colombier l = &first;
18573ff48bf5SDavid du Colombier first = nil;
18584f8f669cSDavid du Colombier for(i = 0; i < HTLEN; i++)
18594f8f669cSDavid du Colombier for(dp = ht[i]; dp; dp = dp->next)
18603ff48bf5SDavid du Colombier for(rp = dp->rr; rp; rp = rp->next){
186153874d13SDavid du Colombier if(rp->type != forwtype || rp->negative)
18623ff48bf5SDavid du Colombier continue;
18633ff48bf5SDavid du Colombier parseip(ip, rp->ip->name);
18643ff48bf5SDavid du Colombier maskip(ip, mask, nnet);
18653ff48bf5SDavid du Colombier if(ipcmp(net, nnet) != 0)
18663ff48bf5SDavid du Colombier continue;
186753874d13SDavid du Colombier
186853874d13SDavid du Colombier ipp = ip;
186953874d13SDavid du Colombier len = IPaddrlen;
187053874d13SDavid du Colombier if (forwtype == Taaaa) {
187153874d13SDavid du Colombier bytes2nibbles(nibip, ip, IPaddrlen);
187253874d13SDavid du Colombier ipp = nibip;
187353874d13SDavid du Colombier len = 2*IPaddrlen;
187453874d13SDavid du Colombier }
187553874d13SDavid du Colombier
18763ff48bf5SDavid du Colombier p = ptr;
18773ff48bf5SDavid du Colombier e = ptr+sizeof(ptr);
187853874d13SDavid du Colombier for(j = len - 1; j >= len - subdoms; j--)
187953874d13SDavid du Colombier p = seprint(p, e, (forwtype == Ta?
188053874d13SDavid du Colombier "%d.": "%x."), ipp[j]);
18813ff48bf5SDavid du Colombier seprint(p, e, "%s", dom);
188253874d13SDavid du Colombier
18833ff48bf5SDavid du Colombier nrp = mkptr(dp, ptr, ttl);
18843ff48bf5SDavid du Colombier *l = nrp;
18853ff48bf5SDavid du Colombier l = &nrp->next;
18863ff48bf5SDavid du Colombier }
18873ff48bf5SDavid du Colombier
18883ff48bf5SDavid du Colombier for(rp = first; rp != nil; rp = nrp){
18893ff48bf5SDavid du Colombier nrp = rp->next;
18903ff48bf5SDavid du Colombier rp->next = nil;
18916dc4800dSDavid du Colombier rrattach(rp, Authoritative);
18923ff48bf5SDavid du Colombier }
18933ff48bf5SDavid du Colombier }
1894dc5a79c1SDavid du Colombier
1895dc5a79c1SDavid du Colombier void
addserver(Server ** l,char * name)1896dc5a79c1SDavid du Colombier addserver(Server **l, char *name)
1897dc5a79c1SDavid du Colombier {
1898dc5a79c1SDavid du Colombier Server *s;
1899dc5a79c1SDavid du Colombier
1900dc5a79c1SDavid du Colombier while(*l)
1901dc5a79c1SDavid du Colombier l = &(*l)->next;
1902dc5a79c1SDavid du Colombier s = malloc(sizeof(Server)+strlen(name)+1);
1903dc5a79c1SDavid du Colombier if(s == nil)
1904dc5a79c1SDavid du Colombier return;
1905dc5a79c1SDavid du Colombier s->name = (char*)(s+1);
1906dc5a79c1SDavid du Colombier strcpy(s->name, name);
1907dc5a79c1SDavid du Colombier s->next = nil;
1908dc5a79c1SDavid du Colombier *l = s;
1909dc5a79c1SDavid du Colombier }
1910dc5a79c1SDavid du Colombier
1911dc5a79c1SDavid du Colombier Server*
copyserverlist(Server * s)1912dc5a79c1SDavid du Colombier copyserverlist(Server *s)
1913dc5a79c1SDavid du Colombier {
1914dc5a79c1SDavid du Colombier Server *ns;
1915dc5a79c1SDavid du Colombier
1916dc5a79c1SDavid du Colombier for(ns = nil; s != nil; s = s->next)
1917dc5a79c1SDavid du Colombier addserver(&ns, s->name);
1918dc5a79c1SDavid du Colombier return ns;
1919dc5a79c1SDavid du Colombier }
1920b751ae26SDavid du Colombier
1921b751ae26SDavid du Colombier
1922b751ae26SDavid du Colombier /* from here down is copied to ip/snoopy/dns.c periodically to update it */
1923b751ae26SDavid du Colombier
1924b751ae26SDavid du Colombier /*
1925b751ae26SDavid du Colombier * convert an integer RR type to it's ascii name
1926b751ae26SDavid du Colombier */
1927b751ae26SDavid du Colombier char*
rrname(int type,char * buf,int len)1928b751ae26SDavid du Colombier rrname(int type, char *buf, int len)
1929b751ae26SDavid du Colombier {
1930b751ae26SDavid du Colombier char *t;
1931b751ae26SDavid du Colombier
1932b751ae26SDavid du Colombier t = nil;
1933b751ae26SDavid du Colombier if(type >= 0 && type <= Tall)
1934b751ae26SDavid du Colombier t = rrtname[type];
1935b751ae26SDavid du Colombier if(t==nil){
1936b751ae26SDavid du Colombier snprint(buf, len, "%d", type);
1937b751ae26SDavid du Colombier t = buf;
1938b751ae26SDavid du Colombier }
1939b751ae26SDavid du Colombier return t;
1940b751ae26SDavid du Colombier }
1941b751ae26SDavid du Colombier
1942b751ae26SDavid du Colombier /*
1943b751ae26SDavid du Colombier * free a list of resource records and any related structs
1944b751ae26SDavid du Colombier */
1945b751ae26SDavid du Colombier void
rrfreelist(RR * rp)1946b751ae26SDavid du Colombier rrfreelist(RR *rp)
1947b751ae26SDavid du Colombier {
1948b751ae26SDavid du Colombier RR *next;
1949b751ae26SDavid du Colombier
1950b751ae26SDavid du Colombier for(; rp; rp = next){
1951b751ae26SDavid du Colombier next = rp->next;
1952b751ae26SDavid du Colombier rrfree(rp);
1953b751ae26SDavid du Colombier }
1954b751ae26SDavid du Colombier }
1955b751ae26SDavid du Colombier
1956b751ae26SDavid du Colombier void
freeserverlist(Server * s)1957b751ae26SDavid du Colombier freeserverlist(Server *s)
1958b751ae26SDavid du Colombier {
1959b751ae26SDavid du Colombier Server *next;
1960b751ae26SDavid du Colombier
1961b751ae26SDavid du Colombier for(; s != nil; s = next){
1962b751ae26SDavid du Colombier next = s->next;
1963b751ae26SDavid du Colombier free(s);
1964b751ae26SDavid du Colombier }
1965b751ae26SDavid du Colombier }
1966b751ae26SDavid du Colombier
1967b751ae26SDavid du Colombier /*
1968b751ae26SDavid du Colombier * allocate a resource record of a given type
1969b751ae26SDavid du Colombier */
1970b751ae26SDavid du Colombier RR*
rralloc(int type)1971b751ae26SDavid du Colombier rralloc(int type)
1972b751ae26SDavid du Colombier {
1973b751ae26SDavid du Colombier RR *rp;
1974b751ae26SDavid du Colombier
1975b751ae26SDavid du Colombier rp = emalloc(sizeof(*rp));
1976b751ae26SDavid du Colombier rp->magic = RRmagic;
1977b751ae26SDavid du Colombier rp->pc = getcallerpc(&type);
1978b751ae26SDavid du Colombier rp->type = type;
1979fd87a217SDavid du Colombier if (rp->type != type)
1980fd87a217SDavid du Colombier dnslog("rralloc: bogus type %d", type);
1981b751ae26SDavid du Colombier setmalloctag(rp, rp->pc);
1982b751ae26SDavid du Colombier switch(type){
1983b751ae26SDavid du Colombier case Tsoa:
1984b751ae26SDavid du Colombier rp->soa = emalloc(sizeof(*rp->soa));
1985b751ae26SDavid du Colombier rp->soa->slaves = nil;
1986b751ae26SDavid du Colombier setmalloctag(rp->soa, rp->pc);
1987b751ae26SDavid du Colombier break;
1988b751ae26SDavid du Colombier case Tsrv:
1989b751ae26SDavid du Colombier rp->srv = emalloc(sizeof(*rp->srv));
1990b751ae26SDavid du Colombier setmalloctag(rp->srv, rp->pc);
1991b751ae26SDavid du Colombier break;
1992b751ae26SDavid du Colombier case Tkey:
1993b751ae26SDavid du Colombier rp->key = emalloc(sizeof(*rp->key));
1994b751ae26SDavid du Colombier setmalloctag(rp->key, rp->pc);
1995b751ae26SDavid du Colombier break;
1996b751ae26SDavid du Colombier case Tcert:
1997b751ae26SDavid du Colombier rp->cert = emalloc(sizeof(*rp->cert));
1998b751ae26SDavid du Colombier setmalloctag(rp->cert, rp->pc);
1999b751ae26SDavid du Colombier break;
2000b751ae26SDavid du Colombier case Tsig:
2001b751ae26SDavid du Colombier rp->sig = emalloc(sizeof(*rp->sig));
2002b751ae26SDavid du Colombier setmalloctag(rp->sig, rp->pc);
2003b751ae26SDavid du Colombier break;
2004b751ae26SDavid du Colombier case Tnull:
2005b751ae26SDavid du Colombier rp->null = emalloc(sizeof(*rp->null));
2006b751ae26SDavid du Colombier setmalloctag(rp->null, rp->pc);
2007b751ae26SDavid du Colombier break;
2008b751ae26SDavid du Colombier }
2009b751ae26SDavid du Colombier rp->ttl = 0;
2010b751ae26SDavid du Colombier rp->expire = 0;
2011b751ae26SDavid du Colombier rp->next = 0;
2012b751ae26SDavid du Colombier return rp;
2013b751ae26SDavid du Colombier }
2014b751ae26SDavid du Colombier
2015b751ae26SDavid du Colombier /*
2016b751ae26SDavid du Colombier * free a resource record and any related structs
2017b751ae26SDavid du Colombier */
2018b751ae26SDavid du Colombier void
rrfree(RR * rp)2019b751ae26SDavid du Colombier rrfree(RR *rp)
2020b751ae26SDavid du Colombier {
2021b751ae26SDavid du Colombier DN *dp;
2022b751ae26SDavid du Colombier RR *nrp;
2023b751ae26SDavid du Colombier Txt *t;
2024b751ae26SDavid du Colombier
2025530fef66SDavid du Colombier assert(rp->magic == RRmagic);
2026b751ae26SDavid du Colombier assert(!rp->cached);
2027b751ae26SDavid du Colombier
202827acba7cSDavid du Colombier /* our callers often hold dnlock. it's needed to examine dp safely. */
2029b751ae26SDavid du Colombier dp = rp->owner;
2030b751ae26SDavid du Colombier if(dp){
203127acba7cSDavid du Colombier /* if someone else holds dnlock, skip the sanity check. */
203227acba7cSDavid du Colombier if (canlock(&dnlock)) {
2033b751ae26SDavid du Colombier assert(dp->magic == DNmagic);
2034b751ae26SDavid du Colombier for(nrp = dp->rr; nrp; nrp = nrp->next)
2035b751ae26SDavid du Colombier assert(nrp != rp); /* "rrfree of live rr" */
203627acba7cSDavid du Colombier unlock(&dnlock);
203727acba7cSDavid du Colombier }
2038b751ae26SDavid du Colombier }
2039b751ae26SDavid du Colombier
2040b751ae26SDavid du Colombier switch(rp->type){
2041b751ae26SDavid du Colombier case Tsoa:
2042b751ae26SDavid du Colombier freeserverlist(rp->soa->slaves);
2043b751ae26SDavid du Colombier memset(rp->soa, 0, sizeof *rp->soa); /* cause trouble */
2044b751ae26SDavid du Colombier free(rp->soa);
2045b751ae26SDavid du Colombier break;
2046b751ae26SDavid du Colombier case Tsrv:
2047b751ae26SDavid du Colombier memset(rp->srv, 0, sizeof *rp->srv); /* cause trouble */
2048b751ae26SDavid du Colombier free(rp->srv);
2049b751ae26SDavid du Colombier break;
2050b751ae26SDavid du Colombier case Tkey:
2051b751ae26SDavid du Colombier free(rp->key->data);
2052b751ae26SDavid du Colombier memset(rp->key, 0, sizeof *rp->key); /* cause trouble */
2053b751ae26SDavid du Colombier free(rp->key);
2054b751ae26SDavid du Colombier break;
2055b751ae26SDavid du Colombier case Tcert:
2056b751ae26SDavid du Colombier free(rp->cert->data);
2057b751ae26SDavid du Colombier memset(rp->cert, 0, sizeof *rp->cert); /* cause trouble */
2058b751ae26SDavid du Colombier free(rp->cert);
2059b751ae26SDavid du Colombier break;
2060b751ae26SDavid du Colombier case Tsig:
2061b751ae26SDavid du Colombier free(rp->sig->data);
2062b751ae26SDavid du Colombier memset(rp->sig, 0, sizeof *rp->sig); /* cause trouble */
2063b751ae26SDavid du Colombier free(rp->sig);
2064b751ae26SDavid du Colombier break;
2065b751ae26SDavid du Colombier case Tnull:
2066b751ae26SDavid du Colombier free(rp->null->data);
2067b751ae26SDavid du Colombier memset(rp->null, 0, sizeof *rp->null); /* cause trouble */
2068b751ae26SDavid du Colombier free(rp->null);
2069b751ae26SDavid du Colombier break;
2070b751ae26SDavid du Colombier case Ttxt:
2071b751ae26SDavid du Colombier while(rp->txt != nil){
2072b751ae26SDavid du Colombier t = rp->txt;
2073b751ae26SDavid du Colombier rp->txt = t->next;
2074b751ae26SDavid du Colombier free(t->p);
2075b751ae26SDavid du Colombier memset(t, 0, sizeof *t); /* cause trouble */
2076b751ae26SDavid du Colombier free(t);
2077b751ae26SDavid du Colombier }
2078b751ae26SDavid du Colombier break;
2079b751ae26SDavid du Colombier }
2080b751ae26SDavid du Colombier
2081b751ae26SDavid du Colombier rp->magic = ~rp->magic;
2082b751ae26SDavid du Colombier memset(rp, 0, sizeof *rp); /* cause trouble */
2083b751ae26SDavid du Colombier free(rp);
2084b751ae26SDavid du Colombier }
2085