xref: /plan9/sys/src/cmd/ndb/dn.c (revision ff579efb6d9c16f03df7f0fbdbd7810dcb61813e)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <pool.h>
5 #include <ctype.h>
6 #include "dns.h"
7 
8 /*
9  *  this comment used to say `our target is 4000 names cached, this should
10  *  be larger on large servers'.  dns at Bell Labs starts off with
11  *  about 1780 names.
12  *
13  * aging seems to corrupt the cache, so raise the trigger from 4000 until we
14  * figure it out.
15  */
16 enum {
17 	Deftarget = 8000,
18 };
19 enum {
20 	Minage		= 10*60,
21 	Defagefreq	= 30*60,	/* age names this often (seconds) */
22 };
23 
24 /*
25  *  Hash table for domain names.  The hash is based only on the
26  *  first element of the domain name.
27  */
28 DN *ht[HTLEN];
29 
30 static struct {
31 	Lock;
32 	ulong	names;		/* names allocated */
33 	ulong	oldest;		/* longest we'll leave a name around */
34 	int	active;
35 	int	mutex;
36 	ushort	id;		/* same size as in packet */
37 } dnvars;
38 
39 /* names of RR types */
40 char *rrtname[] =
41 {
42 [Ta]		"ip",
43 [Tns]		"ns",
44 [Tmd]		"md",
45 [Tmf]		"mf",
46 [Tcname]	"cname",
47 [Tsoa]		"soa",
48 [Tmb]		"mb",
49 [Tmg]		"mg",
50 [Tmr]		"mr",
51 [Tnull]		"null",
52 [Twks]		"wks",
53 [Tptr]		"ptr",
54 [Thinfo]	"hinfo",
55 [Tminfo]	"minfo",
56 [Tmx]		"mx",
57 [Ttxt]		"txt",
58 [Trp]		"rp",
59 [Tafsdb]	"afsdb",
60 [Tx25]		"x.25",
61 [Tisdn]		"isdn",
62 [Trt]		"rt",
63 [Tnsap]		"nsap",
64 [Tnsapptr]	"nsap-ptr",
65 [Tsig]		"sig",
66 [Tkey]		"key",
67 [Tpx]		"px",
68 [Tgpos]		"gpos",
69 [Taaaa]		"ipv6",
70 [Tloc]		"loc",
71 [Tnxt]		"nxt",
72 [Teid]		"eid",
73 [Tnimloc]	"nimrod",
74 [Tsrv]		"srv",
75 [Tatma]		"atma",
76 [Tnaptr]	"naptr",
77 [Tkx]		"kx",
78 [Tcert]		"cert",
79 [Ta6]		"a6",
80 [Tdname]	"dname",
81 [Tsink]		"sink",
82 [Topt]		"opt",
83 [Tapl]		"apl",
84 [Tds]		"ds",
85 [Tsshfp]	"sshfp",
86 [Tipseckey]	"ipseckey",
87 [Trrsig]	"rrsig",
88 [Tnsec]		"nsec",
89 [Tdnskey]	"dnskey",
90 [Tspf]		"spf",
91 [Tuinfo]	"uinfo",
92 [Tuid]		"uid",
93 [Tgid]		"gid",
94 [Tunspec]	"unspec",
95 [Ttkey]		"tkey",
96 [Ttsig]		"tsig",
97 [Tixfr]		"ixfr",
98 [Taxfr]		"axfr",
99 [Tmailb]	"mailb",
100 [Tmaila]	"maila",
101 [Tall]		"all",
102 		0,
103 };
104 
105 /* names of response codes */
106 char *rname[Rmask+1] =
107 {
108 [Rok]			"ok",
109 [Rformat]		"format error",
110 [Rserver]		"server failure",
111 [Rname]			"bad name",
112 [Runimplimented]	"unimplemented",
113 [Rrefused]		"we don't like you",
114 [Ryxdomain]		"name should not exist",
115 [Ryxrrset]		"rr set should not exist",
116 [Rnxrrset]		"rr set should exist",
117 [Rnotauth]		"not authorative",
118 [Rnotzone]		"not in zone",
119 [Rbadvers]		"bad opt version",
120 /* [Rbadsig]		"bad signature", */
121 [Rbadkey]		"bad key",
122 [Rbadtime]		"bad signature time",
123 [Rbadmode]		"bad mode",
124 [Rbadname]		"duplicate key name",
125 [Rbadalg]		"bad algorithm",
126 };
127 unsigned nrname = nelem(rname);
128 
129 /* names of op codes */
130 char *opname[] =
131 {
132 [Oquery]	"query",
133 [Oinverse]	"inverse query (retired)",
134 [Ostatus]	"status",
135 [Oupdate]	"update",
136 };
137 
138 ulong target = Deftarget;
139 Lock	dnlock;
140 
141 static ulong agefreq = Defagefreq;
142 
143 static int rrequiv(RR *r1, RR *r2);
144 static int sencodefmt(Fmt*);
145 
146 static void
147 ding(void*, char *msg)
148 {
149 	if(strstr(msg, "alarm") != nil) {
150 		stats.alarms++;
151 		noted(NCONT);		/* resume with system call error */
152 	} else
153 		noted(NDFLT);		/* die */
154 }
155 
156 void
157 dninit(void)
158 {
159 	fmtinstall('E', eipfmt);
160 	fmtinstall('I', eipfmt);
161 	fmtinstall('V', eipfmt);
162 	fmtinstall('R', rrfmt);
163 	fmtinstall('Q', rravfmt);
164 	fmtinstall('H', sencodefmt);
165 
166 	dnvars.oldest = maxage;
167 	dnvars.names = 0;
168 	dnvars.id = truerand();	/* don't start with same id every time */
169 
170 	notify(ding);
171 }
172 
173 /*
174  *  hash for a domain name
175  */
176 static ulong
177 dnhash(char *name)
178 {
179 	ulong hash;
180 	uchar *val = (uchar*)name;
181 
182 	for(hash = 0; *val; val++)
183 		hash = hash*13 + tolower(*val)-'a';
184 	return hash % HTLEN;
185 }
186 
187 /*
188  *  lookup a symbol.  if enter is not zero and the name is
189  *  not found, create it.
190  */
191 DN*
192 dnlookup(char *name, int class, int enter)
193 {
194 	DN **l;
195 	DN *dp;
196 
197 	l = &ht[dnhash(name)];
198 	lock(&dnlock);
199 	for(dp = *l; dp; dp = dp->next) {
200 		assert(dp->magic == DNmagic);
201 		if(dp->class == class && cistrcmp(dp->name, name) == 0){
202 			dp->referenced = now;
203 			unlock(&dnlock);
204 			return dp;
205 		}
206 		l = &dp->next;
207 	}
208 
209 	if(!enter){
210 		unlock(&dnlock);
211 		return 0;
212 	}
213 	dnvars.names++;
214 	dp = emalloc(sizeof(*dp));
215 	dp->magic = DNmagic;
216 	dp->name = estrdup(name);
217 	assert(dp->name != nil);
218 	dp->class = class;
219 	dp->rr = 0;
220 	dp->next = 0;
221 	dp->referenced = now;
222 	*l = dp;
223 	unlock(&dnlock);
224 
225 	return dp;
226 }
227 
228 static int
229 rrsame(RR *rr1, RR *rr2)
230 {
231 	return rr1 == rr2 || rr2 && rrequiv(rr1, rr2) &&
232 		rr1->db == rr2->db && rr1->auth == rr2->auth;
233 }
234 
235 static int
236 rronlist(RR *rp, RR *lp)
237 {
238 	for(; lp; lp = lp->next)
239 		if (rrsame(lp, rp))
240 			return 1;
241 	return 0;
242 }
243 
244 /*
245  * dump the stats
246  */
247 void
248 dnstats(char *file)
249 {
250 	int i, fd;
251 
252 	fd = create(file, OWRITE, 0666);
253 	if(fd < 0)
254 		return;
255 
256 	qlock(&stats);
257 	fprint(fd, "# system %s\n", sysname());
258 	fprint(fd, "# slave procs high-water mark\t%lud\n", stats.slavehiwat);
259 	fprint(fd, "# queries received by 9p\t%lud\n", stats.qrecvd9p);
260 	fprint(fd, "# queries received by udp\t%lud\n", stats.qrecvdudp);
261 	fprint(fd, "# queries answered from memory\t%lud\n", stats.answinmem);
262 	fprint(fd, "# queries sent by udp\t%lud\n", stats.qsent);
263 	for (i = 0; i < nelem(stats.under10ths); i++)
264 		if (stats.under10ths[i] || i == nelem(stats.under10ths) - 1)
265 			fprint(fd, "# responses arriving within %.1f s.\t%lud\n",
266 				(double)(i+1)/10, stats.under10ths[i]);
267 	fprint(fd, "\n# queries sent & timed-out\t%lud\n", stats.tmout);
268 	fprint(fd, "# cname queries timed-out\t%lud\n", stats.tmoutcname);
269 	fprint(fd, "# ipv6  queries timed-out\t%lud\n", stats.tmoutv6);
270 	fprint(fd, "\n# negative answers received\t%lud\n", stats.negans);
271 	fprint(fd, "# negative answers w Rserver set\t%lud\n", stats.negserver);
272 	fprint(fd, "# negative answers w bad delegation\t%lud\n",
273 		stats.negbaddeleg);
274 	fprint(fd, "# negative answers w bad delegation & no answers\t%lud\n",
275 		stats.negbdnoans);
276 	fprint(fd, "# negative answers w no Rname set\t%lud\n", stats.negnorname);
277 	fprint(fd, "# negative answers cached\t%lud\n", stats.negcached);
278 	qunlock(&stats);
279 
280 	lock(&dnlock);
281 	fprint(fd, "\n# domain names %lud target %lud\n", dnvars.names, target);
282 	unlock(&dnlock);
283 	close(fd);
284 }
285 
286 /*
287  *  dump the cache
288  */
289 void
290 dndump(char *file)
291 {
292 	int i, fd;
293 	DN *dp;
294 	RR *rp;
295 
296 	fd = create(file, OWRITE, 0666);
297 	if(fd < 0)
298 		return;
299 
300 	lock(&dnlock);
301 	for(i = 0; i < HTLEN; i++)
302 		for(dp = ht[i]; dp; dp = dp->next){
303 			fprint(fd, "%s\n", dp->name);
304 			for(rp = dp->rr; rp; rp = rp->next) {
305 				fprint(fd, "\t%R %c%c %lud/%lud\n",
306 					rp, rp->auth? 'A': 'U',
307 					rp->db? 'D': 'N', rp->expire, rp->ttl);
308 				if (rronlist(rp, rp->next))
309 					fprint(fd, "*** duplicate:\n");
310 			}
311 		}
312 	unlock(&dnlock);
313 	close(fd);
314 }
315 
316 /*
317  *  purge all records
318  */
319 void
320 dnpurge(void)
321 {
322 	DN *dp;
323 	RR *rp, *srp;
324 	int i;
325 
326 	lock(&dnlock);
327 
328 	for(i = 0; i < HTLEN; i++)
329 		for(dp = ht[i]; dp; dp = dp->next){
330 			srp = rp = dp->rr;
331 			dp->rr = nil;
332 			for(; rp != nil; rp = rp->next)
333 				rp->cached = 0;
334 			rrfreelist(srp);
335 		}
336 
337 	unlock(&dnlock);
338 }
339 
340 /*
341  *  delete rp from *l, free rp.
342  *  call with dnlock held.
343  */
344 static void
345 rrdelete(RR **l, RR *rp)
346 {
347 	*l = rp->next;
348 	rp->cached = 0;		/* avoid blowing an assertion in rrfree */
349 	rrfree(rp);
350 }
351 
352 /*
353  *  check the age of resource records, free any that have timed out.
354  *  call with dnlock held.
355  */
356 void
357 dnage(DN *dp)
358 {
359 	RR **l;
360 	RR *rp, *next;
361 	ulong diff;
362 
363 	diff = now - dp->referenced;
364 	if(diff < Reserved || dp->keep)
365 		return;
366 
367 	l = &dp->rr;
368 	for(rp = dp->rr; rp; rp = next){
369 		assert(rp->magic == RRmagic && rp->cached);
370 		next = rp->next;
371 		if(!rp->db && (rp->expire < now || diff > dnvars.oldest))
372 			rrdelete(l, rp);
373 		else
374 			l = &rp->next;
375 	}
376 }
377 
378 #define MARK(dp)	{ if (dp) (dp)->keep = 1; }
379 
380 /* mark a domain name and those in its RRs as never to be aged */
381 void
382 dnagenever(DN *dp, int dolock)
383 {
384 	RR *rp;
385 
386 	if (dolock)
387 		lock(&dnlock);
388 
389 	/* mark all referenced domain names */
390 	MARK(dp);
391 	for(rp = dp->rr; rp; rp = rp->next){
392 		MARK(rp->owner);
393 		if(rp->negative){
394 			MARK(rp->negsoaowner);
395 			continue;
396 		}
397 		switch(rp->type){
398 		case Thinfo:
399 			MARK(rp->cpu);
400 			MARK(rp->os);
401 			break;
402 		case Ttxt:
403 			break;
404 		case Tcname:
405 		case Tmb:
406 		case Tmd:
407 		case Tmf:
408 		case Tns:
409 		case Tmx:
410 		case Tsrv:
411 			MARK(rp->host);
412 			break;
413 		case Tmg:
414 		case Tmr:
415 			MARK(rp->mb);
416 			break;
417 		case Tminfo:
418 			MARK(rp->rmb);
419 			MARK(rp->mb);
420 			break;
421 		case Trp:
422 			MARK(rp->rmb);
423 			MARK(rp->rp);
424 			break;
425 		case Ta:
426 		case Taaaa:
427 			MARK(rp->ip);
428 			break;
429 		case Tptr:
430 			MARK(rp->ptr);
431 			break;
432 		case Tsoa:
433 			MARK(rp->host);
434 			MARK(rp->rmb);
435 			break;
436 		}
437 	}
438 
439 	if (dolock)
440 		unlock(&dnlock);
441 }
442 
443 /* mark all current domain names as never to be aged */
444 void
445 dnageallnever(void)
446 {
447 	int i;
448 	DN *dp;
449 
450 	lock(&dnlock);
451 
452 	/* mark all referenced domain names */
453 	for(i = 0; i < HTLEN; i++)
454 		for(dp = ht[i]; dp; dp = dp->next)
455 			dnagenever(dp, 0);
456 
457 	unlock(&dnlock);
458 
459 	dnslog("%ld initial domain names; target is %ld", dnvars.names, target);
460 	if(dnvars.names >= target)
461 		dnslog("more initial domain names (%ld) than target (%ld)",
462 			dnvars.names, target);
463 }
464 
465 #define REF(dp)	{ if (dp) (dp)->refs++; }
466 
467 /*
468  *  periodicly sweep for old records and remove unreferenced domain names
469  *
470  *  only called when all other threads are locked out
471  */
472 void
473 dnageall(int doit)
474 {
475 	DN *dp, **l;
476 	int i;
477 	RR *rp;
478 	static ulong nextage;
479 
480 	if(dnvars.names < target || (now < nextage && !doit)){
481 		dnvars.oldest = maxage;
482 		return;
483 	}
484 
485 	if(dnvars.names >= target) {
486 		dnslog("more names (%lud) than target (%lud)", dnvars.names,
487 			target);
488 		dnvars.oldest /= 2;
489 		if (dnvars.oldest < Minage)
490 			dnvars.oldest = Minage;		/* don't be silly */
491 	}
492 	if (agefreq > dnvars.oldest / 2)
493 		nextage = now + dnvars.oldest / 2;
494 	else
495 		nextage = now + agefreq;
496 
497 	lock(&dnlock);
498 
499 	/* time out all old entries (and set refs to 0) */
500 	for(i = 0; i < HTLEN; i++)
501 		for(dp = ht[i]; dp; dp = dp->next){
502 			dp->refs = 0;
503 			dnage(dp);
504 		}
505 
506 	/* mark all referenced domain names */
507 	for(i = 0; i < HTLEN; i++)
508 		for(dp = ht[i]; dp; dp = dp->next)
509 			for(rp = dp->rr; rp; rp = rp->next){
510 				REF(rp->owner);
511 				if(rp->negative){
512 					REF(rp->negsoaowner);
513 					continue;
514 				}
515 				switch(rp->type){
516 				case Thinfo:
517 					REF(rp->cpu);
518 					REF(rp->os);
519 					break;
520 				case Ttxt:
521 					break;
522 				case Tcname:
523 				case Tmb:
524 				case Tmd:
525 				case Tmf:
526 				case Tns:
527 				case Tmx:
528 				case Tsrv:
529 					REF(rp->host);
530 					break;
531 				case Tmg:
532 				case Tmr:
533 					REF(rp->mb);
534 					break;
535 				case Tminfo:
536 					REF(rp->rmb);
537 					REF(rp->mb);
538 					break;
539 				case Trp:
540 					REF(rp->rmb);
541 					REF(rp->rp);
542 					break;
543 				case Ta:
544 				case Taaaa:
545 					REF(rp->ip);
546 					break;
547 				case Tptr:
548 					REF(rp->ptr);
549 					break;
550 				case Tsoa:
551 					REF(rp->host);
552 					REF(rp->rmb);
553 					break;
554 				}
555 			}
556 
557 	/* sweep and remove unreferenced domain names */
558 	for(i = 0; i < HTLEN; i++){
559 		l = &ht[i];
560 		for(dp = *l; dp; dp = *l){
561 			if(dp->rr == 0 && dp->refs == 0 && !dp->keep){
562 				assert(dp->magic == DNmagic);
563 				*l = dp->next;
564 
565 				if(dp->name)
566 					free(dp->name);
567 				dp->magic = ~dp->magic;
568 				dnvars.names--;
569 				memset(dp, 0, sizeof *dp); /* cause trouble */
570 				free(dp);
571 
572 				continue;
573 			}
574 			l = &dp->next;
575 		}
576 	}
577 
578 	unlock(&dnlock);
579 }
580 
581 /*
582  *  timeout all database records (used when rereading db)
583  */
584 void
585 dnagedb(void)
586 {
587 	DN *dp;
588 	int i;
589 	RR *rp;
590 
591 	lock(&dnlock);
592 
593 	/* time out all database entries */
594 	for(i = 0; i < HTLEN; i++)
595 		for(dp = ht[i]; dp; dp = dp->next) {
596 			dp->keep = 0;
597 			for(rp = dp->rr; rp; rp = rp->next)
598 				if(rp->db)
599 					rp->expire = 0;
600 		}
601 
602 	unlock(&dnlock);
603 }
604 
605 /*
606  *  mark all local db records about my area as authoritative,
607  *  time out any others
608  */
609 void
610 dnauthdb(void)
611 {
612 	int i;
613 	ulong minttl;
614 	Area *area;
615 	DN *dp;
616 	RR *rp;
617 
618 	lock(&dnlock);
619 
620 	/* time out all database entries */
621 	for(i = 0; i < HTLEN; i++)
622 		for(dp = ht[i]; dp; dp = dp->next){
623 			area = inmyarea(dp->name);
624 			for(rp = dp->rr; rp; rp = rp->next)
625 				if(rp->db){
626 					if(area){
627 						minttl = area->soarr->soa->minttl;
628 						if(rp->ttl < minttl)
629 							rp->ttl = minttl;
630 						rp->auth = 1;
631 					}
632 					if(rp->expire == 0){
633 						rp->db = 0;
634 						dp->referenced = now-Reserved-1;
635 					}
636 				}
637 		}
638 
639 	unlock(&dnlock);
640 }
641 
642 /*
643  *  keep track of other processes to know if we can
644  *  garbage collect.  block while garbage collecting.
645  */
646 int
647 getactivity(Request *req, int recursive)
648 {
649 	int rv;
650 
651 	if(traceactivity)
652 		dnslog("get: %d active by pid %d from %p",
653 			dnvars.active, getpid(), getcallerpc(&req));
654 	lock(&dnvars);
655 	/*
656 	 * can't block here if we're already holding one
657 	 * of the dnvars.active (recursive).  will deadlock.
658 	 */
659 	while(!recursive && dnvars.mutex){
660 		unlock(&dnvars);
661 		sleep(100);			/* tune; was 200 */
662 		lock(&dnvars);
663 	}
664 	rv = ++dnvars.active;
665 	now = time(nil);
666 	nowns = nsec();
667 	req->id = ++dnvars.id;
668 	unlock(&dnvars);
669 
670 	return rv;
671 }
672 void
673 putactivity(int recursive)
674 {
675 	static ulong lastclean;
676 
677 	if(traceactivity)
678 		dnslog("put: %d active by pid %d",
679 			dnvars.active, getpid());
680 	lock(&dnvars);
681 	dnvars.active--;
682 	assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */
683 
684 	/*
685 	 *  clean out old entries and check for new db periodicly
686 	 *  can't block here if being called to let go a "recursive" lock
687 	 *  or we'll deadlock waiting for ourselves to give up the dnvars.active.
688 	 */
689 	if (recursive || dnvars.mutex ||
690 	    (needrefresh == 0 && dnvars.active > 0)){
691 		unlock(&dnvars);
692 		return;
693 	}
694 
695 	/* wait till we're alone */
696 	dnvars.mutex = 1;
697 	while(dnvars.active > 0){
698 		unlock(&dnvars);
699 		sleep(100);		/* tune; was 100 */
700 		lock(&dnvars);
701 	}
702 	unlock(&dnvars);
703 
704 	db2cache(needrefresh);
705 	dnageall(0);
706 
707 	/* let others back in */
708 	lastclean = now;
709 	needrefresh = 0;
710 	dnvars.mutex = 0;
711 }
712 
713 int
714 rrlistlen(RR *rp)
715 {
716 	int n;
717 
718 	n = 0;
719 	for(; rp; rp = rp->next)
720 		++n;
721 	return n;
722 }
723 
724 /*
725  *  Attach a single resource record to a domain name (new->owner).
726  *	- Avoid duplicates with already present RR's
727  *	- Chain all RR's of the same type adjacent to one another
728  *	- chain authoritative RR's ahead of non-authoritative ones
729  *	- remove any expired RR's
730  *  If new is a stale duplicate, rrfree it.
731  *  Must be called with dnlock held.
732  */
733 static void
734 rrattach1(RR *new, int auth)
735 {
736 	RR **l;
737 	RR *rp;
738 	DN *dp;
739 
740 	assert(new->magic == RRmagic && !new->cached);
741 
742 //	dnslog("rrattach1: %s", new->owner->name);
743 	if(!new->db)
744 		new->expire = new->ttl;
745 	else
746 		new->expire = now + Year;
747 	dp = new->owner;
748 	assert(dp->magic == DNmagic);
749 	new->auth |= auth;
750 	new->next = 0;
751 
752 	/*
753 	 *  find first rr of the right type
754 	 */
755 	l = &dp->rr;
756 	for(rp = *l; rp; rp = *l){
757 		assert(rp->magic == RRmagic && rp->cached);
758 		if(rp->type == new->type)
759 			break;
760 		l = &rp->next;
761 	}
762 
763 	/*
764 	 *  negative entries replace positive entries
765 	 *  positive entries replace negative entries
766 	 *  newer entries replace older entries with the same fields
767 	 *
768 	 *  look farther ahead than just the next entry when looking
769 	 *  for duplicates; RRs of a given type can have different rdata
770 	 *  fields (e.g. multiple NS servers).
771 	 */
772 	while ((rp = *l) != nil){
773 		assert(rp->magic == RRmagic && rp->cached);
774 		if(rp->type != new->type)
775 			break;
776 
777 		if(rp->db == new->db && rp->auth == new->auth){
778 			/* negative drives out positive and vice versa */
779 			if(rp->negative != new->negative) {
780 				rrdelete(l, rp);
781 				continue;		/* *l == rp->next */
782 			}
783 			/* all things equal, pick the newer one */
784 			else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
785 				/* new drives out old */
786 				if (new->ttl <= rp->ttl &&
787 				    new->expire <= rp->expire) {
788 					rrfree(new);
789 					return;
790 				}
791 				rrdelete(l, rp);
792 				continue;		/* *l == rp->next */
793 			}
794 			/*
795 			 *  Hack for pointer records.  This makes sure
796 			 *  the ordering in the list reflects the ordering
797 			 *  received or read from the database
798 			 */
799 			else if(rp->type == Tptr &&
800 			    !rp->negative && !new->negative &&
801 			    rp->ptr->ordinal > new->ptr->ordinal)
802 				break;
803 		}
804 		l = &rp->next;
805 	}
806 
807 	if (rronlist(new, *l)) {
808 		/* should not happen; duplicates were processed above */
809 		dnslog("adding duplicate %R to list of %R; aborting", new, *l);
810 		abort();
811 	}
812 	/*
813 	 *  add to chain
814 	 */
815 	new->cached = 1;
816 	new->next = *l;
817 	*l = new;
818 }
819 
820 /*
821  *  Attach a list of resource records to a domain name.
822  *  May rrfree any stale duplicate RRs; dismembers the list.
823  *  Upon return, every RR in the list will have been rrfree-d
824  *  or attached to its domain name.
825  *  See rrattach1 for properties preserved.
826  */
827 void
828 rrattach(RR *rp, int auth)
829 {
830 	RR *next;
831 	DN *dp;
832 
833 	lock(&dnlock);
834 	for(; rp; rp = next){
835 		next = rp->next;
836 		rp->next = nil;
837 		dp = rp->owner;
838 
839 		/* avoid any outside spoofing */
840 //		dnslog("rrattach: %s", rp->owner->name);
841 		if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name))
842 			rrfree(rp);
843 		else {
844 			rrattach1(rp, auth);
845 			if (rrlistlen(dp->rr) % 100 == 0)
846 				dnslog("rrlookup(%s): rr list len is multiple"
847 					" of 100", dp->name);
848 		}
849 	}
850 	unlock(&dnlock);
851 }
852 
853 RR**
854 rrcopy(RR *rp, RR **last)
855 {
856 	Cert *cert;
857 	Key *key;
858 	Null *null;
859 	RR *nrp;
860 	SOA *soa;
861 	Sig *sig;
862 	Txt *t, *nt, **l;
863 
864 	nrp = rralloc(rp->type);
865 	setmalloctag(nrp, getcallerpc(&rp));
866 	switch(rp->type){
867 	case Ttxt:
868 		*nrp = *rp;
869 		l = &nrp->txt;
870 		*l = nil;
871 		for(t = rp->txt; t != nil; t = t->next){
872 			nt = emalloc(sizeof(*nt));
873 			nt->p = estrdup(t->p);
874 			nt->next = nil;
875 			*l = nt;
876 			l = &nt->next;
877 		}
878 		break;
879 	case Tsoa:
880 		soa = nrp->soa;
881 		*nrp = *rp;
882 		nrp->soa = soa;
883 		*nrp->soa = *rp->soa;
884 		nrp->soa->slaves = copyserverlist(rp->soa->slaves);
885 		break;
886 	case Tsrv:
887 		*nrp = *rp;
888 		nrp->srv = emalloc(sizeof *nrp->srv);
889 		*nrp->srv = *rp->srv;
890 		break;
891 	case Tkey:
892 		key = nrp->key;
893 		*nrp = *rp;
894 		nrp->key = key;
895 		*key = *rp->key;
896 		key->data = emalloc(key->dlen);
897 		memmove(key->data, rp->key->data, rp->key->dlen);
898 		break;
899 	case Tsig:
900 		sig = nrp->sig;
901 		*nrp = *rp;
902 		nrp->sig = sig;
903 		*sig = *rp->sig;
904 		sig->data = emalloc(sig->dlen);
905 		memmove(sig->data, rp->sig->data, rp->sig->dlen);
906 		break;
907 	case Tcert:
908 		cert = nrp->cert;
909 		*nrp = *rp;
910 		nrp->cert = cert;
911 		*cert = *rp->cert;
912 		cert->data = emalloc(cert->dlen);
913 		memmove(cert->data, rp->cert->data, rp->cert->dlen);
914 		break;
915 	case Tnull:
916 		null = nrp->null;
917 		*nrp = *rp;
918 		nrp->null = null;
919 		*null = *rp->null;
920 		null->data = emalloc(null->dlen);
921 		memmove(null->data, rp->null->data, rp->null->dlen);
922 		break;
923 	default:
924 		*nrp = *rp;
925 		break;
926 	}
927 	nrp->cached = 0;
928 	nrp->next = 0;
929 	*last = nrp;
930 	return &nrp->next;
931 }
932 
933 /*
934  *  lookup a resource record of a particular type and
935  *  class attached to a domain name.  Return copies.
936  *
937  *  Priority ordering is:
938  *	db authoritative
939  *	not timed out network authoritative
940  *	not timed out network unauthoritative
941  *	unauthoritative db
942  *
943  *  if flag NOneg is set, don't return negative cached entries.
944  *  return nothing instead.
945  */
946 RR*
947 rrlookup(DN *dp, int type, int flag)
948 {
949 	RR *rp, *first, **last;
950 
951 	assert(dp->magic == DNmagic);
952 
953 	first = 0;
954 	last = &first;
955 	lock(&dnlock);
956 
957 	/* try for an authoritative db entry */
958 	for(rp = dp->rr; rp; rp = rp->next){
959 		assert(rp->magic == RRmagic && rp->cached);
960 		if(rp->db)
961 		if(rp->auth)
962 		if(tsame(type, rp->type)) {
963 			last = rrcopy(rp, last);
964 			// setmalloctag(*last, getcallerpc(&dp));
965 		}
966 	}
967 	if(first)
968 		goto out;
969 
970 	/* try for a living authoritative network entry */
971 	for(rp = dp->rr; rp; rp = rp->next){
972 		if(!rp->db)
973 		if(rp->auth)
974 		if(rp->ttl + 60 > now)
975 		if(tsame(type, rp->type)){
976 			if(flag == NOneg && rp->negative)
977 				goto out;
978 			last = rrcopy(rp, last);
979 		}
980 	}
981 	if(first)
982 		goto out;
983 
984 	/* try for a living unauthoritative network entry */
985 	for(rp = dp->rr; rp; rp = rp->next){
986 		if(!rp->db)
987 		if(rp->ttl + 60 > now)
988 		if(tsame(type, rp->type)){
989 			if(flag == NOneg && rp->negative)
990 				goto out;
991 			last = rrcopy(rp, last);
992 		}
993 	}
994 	if(first)
995 		goto out;
996 
997 	/* try for an unauthoritative db entry */
998 	for(rp = dp->rr; rp; rp = rp->next){
999 		if(rp->db)
1000 		if(tsame(type, rp->type))
1001 			last = rrcopy(rp, last);
1002 	}
1003 	if(first)
1004 		goto out;
1005 
1006 	/* otherwise, settle for anything we got (except for negative caches) */
1007 	for(rp = dp->rr; rp; rp = rp->next)
1008 		if(tsame(type, rp->type)){
1009 			if(rp->negative)
1010 				goto out;
1011 			last = rrcopy(rp, last);
1012 		}
1013 
1014 out:
1015 	unlock(&dnlock);
1016 	unique(first);
1017 //	dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first);
1018 //	if (first)
1019 //		setmalloctag(first, getcallerpc(&dp));
1020 	return first;
1021 }
1022 
1023 /*
1024  *  convert an ascii RR type name to its integer representation
1025  */
1026 int
1027 rrtype(char *atype)
1028 {
1029 	int i;
1030 
1031 	for(i = 0; i <= Tall; i++)
1032 		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
1033 			return i;
1034 
1035 	/* make any a synonym for all */
1036 	if(strcmp(atype, "any") == 0)
1037 		return Tall;
1038 	return atoi(atype);
1039 }
1040 
1041 /*
1042  *  return 0 if not a supported rr type
1043  */
1044 int
1045 rrsupported(int type)
1046 {
1047 	if(type < 0 || type >Tall)
1048 		return 0;
1049 	return rrtname[type] != nil;
1050 }
1051 
1052 /*
1053  *  compare 2 types
1054  */
1055 int
1056 tsame(int t1, int t2)
1057 {
1058 	return t1 == t2 || t1 == Tall;
1059 }
1060 
1061 /*
1062  *  Add resource records to a list, duplicate them if they are cached
1063  *  RR's since these are shared.
1064  */
1065 RR*
1066 rrcat(RR **start, RR *rp)
1067 {
1068 	RR *olp, *nlp;
1069 	RR **last;
1070 
1071 	/* check for duplicates */
1072 	for (olp = *start; 0 && olp; olp = olp->next)
1073 		for (nlp = rp; nlp; nlp = nlp->next)
1074 			if (rrsame(nlp, olp))
1075 				dnslog("rrcat: duplicate RR: %R", nlp);
1076 	USED(olp);
1077 
1078 	last = start;
1079 	while(*last != nil)
1080 		last = &(*last)->next;
1081 
1082 	*last = rp;
1083 	return *start;
1084 }
1085 
1086 /*
1087  *  remove negative cache rr's from an rr list
1088  */
1089 RR*
1090 rrremneg(RR **l)
1091 {
1092 	RR **nl, *rp;
1093 	RR *first;
1094 
1095 	first = nil;
1096 	nl = &first;
1097 	while(*l != nil){
1098 		rp = *l;
1099 		if(rp->negative){
1100 			*l = rp->next;
1101 			*nl = rp;
1102 			nl = &rp->next;
1103 			*nl = nil;
1104 		} else
1105 			l = &rp->next;
1106 	}
1107 
1108 	return first;
1109 }
1110 
1111 /*
1112  *  remove rr's of a particular type from an rr list
1113  */
1114 RR*
1115 rrremtype(RR **l, int type)
1116 {
1117 	RR *first, *rp;
1118 	RR **nl;
1119 
1120 	first = nil;
1121 	nl = &first;
1122 	while(*l != nil){
1123 		rp = *l;
1124 		if(rp->type == type){
1125 			*l = rp->next;
1126 			*nl = rp;
1127 			nl = &rp->next;
1128 			*nl = nil;
1129 		} else
1130 			l = &(*l)->next;
1131 	}
1132 
1133 	return first;
1134 }
1135 
1136 static char *
1137 dnname(DN *dn)
1138 {
1139 	return dn? dn->name: "<null>";
1140 }
1141 
1142 /*
1143  *  print conversion for rr records
1144  */
1145 int
1146 rrfmt(Fmt *f)
1147 {
1148 	int rv;
1149 	char *strp;
1150 	char buf[Domlen];
1151 	Fmt fstr;
1152 	RR *rp;
1153 	Server *s;
1154 	SOA *soa;
1155 	Srv *srv;
1156 	Txt *t;
1157 
1158 	fmtstrinit(&fstr);
1159 
1160 	rp = va_arg(f->args, RR*);
1161 	if(rp == nil){
1162 		fmtprint(&fstr, "<null>");
1163 		goto out;
1164 	}
1165 
1166 	fmtprint(&fstr, "%s %s", dnname(rp->owner),
1167 		rrname(rp->type, buf, sizeof buf));
1168 
1169 	if(rp->negative){
1170 		fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);
1171 		goto out;
1172 	}
1173 
1174 	switch(rp->type){
1175 	case Thinfo:
1176 		fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os));
1177 		break;
1178 	case Tcname:
1179 	case Tmb:
1180 	case Tmd:
1181 	case Tmf:
1182 	case Tns:
1183 		fmtprint(&fstr, "\t%s", dnname(rp->host));
1184 		break;
1185 	case Tmg:
1186 	case Tmr:
1187 		fmtprint(&fstr, "\t%s", dnname(rp->mb));
1188 		break;
1189 	case Tminfo:
1190 		fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb));
1191 		break;
1192 	case Tmx:
1193 		fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host));
1194 		break;
1195 	case Ta:
1196 	case Taaaa:
1197 		fmtprint(&fstr, "\t%s", dnname(rp->ip));
1198 		break;
1199 	case Tptr:
1200 //		fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr),
1201 //			rp->ptr? rp->ptr->ordinal: "<null>");
1202 		fmtprint(&fstr, "\t%s", dnname(rp->ptr));
1203 		break;
1204 	case Tsoa:
1205 		soa = rp->soa;
1206 		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud",
1207 			dnname(rp->host), dnname(rp->rmb),
1208 			(soa? soa->serial: 0),
1209 			(soa? soa->refresh: 0), (soa? soa->retry: 0),
1210 			(soa? soa->expire: 0), (soa? soa->minttl: 0));
1211 		if (soa)
1212 			for(s = soa->slaves; s != nil; s = s->next)
1213 				fmtprint(&fstr, " %s", s->name);
1214 		break;
1215 	case Tsrv:
1216 		srv = rp->srv;
1217 		fmtprint(&fstr, "\t%ud %ud %ud %s",
1218 			(srv? srv->pri: 0), (srv? srv->weight: 0),
1219 			rp->port, dnname(rp->host));
1220 		break;
1221 	case Tnull:
1222 		if (rp->null == nil)
1223 			fmtprint(&fstr, "\t<null>");
1224 		else
1225 			fmtprint(&fstr, "\t%.*H", rp->null->dlen,
1226 				rp->null->data);
1227 		break;
1228 	case Ttxt:
1229 		fmtprint(&fstr, "\t");
1230 		for(t = rp->txt; t != nil; t = t->next)
1231 			fmtprint(&fstr, "%s", t->p);
1232 		break;
1233 	case Trp:
1234 		fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp));
1235 		break;
1236 	case Tkey:
1237 		if (rp->key == nil)
1238 			fmtprint(&fstr, "\t<null> <null> <null>");
1239 		else
1240 			fmtprint(&fstr, "\t%d %d %d", rp->key->flags,
1241 				rp->key->proto, rp->key->alg);
1242 		break;
1243 	case Tsig:
1244 		if (rp->sig == nil)
1245 			fmtprint(&fstr,
1246 		   "\t<null> <null> <null> <null> <null> <null> <null> <null>");
1247 		else
1248 			fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
1249 				rp->sig->type, rp->sig->alg, rp->sig->labels,
1250 				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
1251 				rp->sig->tag, dnname(rp->sig->signer));
1252 		break;
1253 	case Tcert:
1254 		if (rp->cert == nil)
1255 			fmtprint(&fstr, "\t<null> <null> <null>");
1256 		else
1257 			fmtprint(&fstr, "\t%d %d %d",
1258 				rp->cert->type, rp->cert->tag, rp->cert->alg);
1259 		break;
1260 	}
1261 out:
1262 	strp = fmtstrflush(&fstr);
1263 	rv = fmtstrcpy(f, strp);
1264 	free(strp);
1265 	return rv;
1266 }
1267 
1268 /*
1269  *  print conversion for rr records in attribute value form
1270  */
1271 int
1272 rravfmt(Fmt *f)
1273 {
1274 	int rv, quote;
1275 	char *strp;
1276 	Fmt fstr;
1277 	RR *rp;
1278 	Server *s;
1279 	SOA *soa;
1280 	Srv *srv;
1281 	Txt *t;
1282 
1283 	fmtstrinit(&fstr);
1284 
1285 	rp = va_arg(f->args, RR*);
1286 	if(rp == nil){
1287 		fmtprint(&fstr, "<null>");
1288 		goto out;
1289 	}
1290 
1291 	if(rp->type == Tptr)
1292 		fmtprint(&fstr, "ptr=%s", dnname(rp->owner));
1293 	else
1294 		fmtprint(&fstr, "dom=%s", dnname(rp->owner));
1295 
1296 	switch(rp->type){
1297 	case Thinfo:
1298 		fmtprint(&fstr, " cpu=%s os=%s",
1299 			dnname(rp->cpu), dnname(rp->os));
1300 		break;
1301 	case Tcname:
1302 		fmtprint(&fstr, " cname=%s", dnname(rp->host));
1303 		break;
1304 	case Tmb:
1305 	case Tmd:
1306 	case Tmf:
1307 		fmtprint(&fstr, " mbox=%s", dnname(rp->host));
1308 		break;
1309 	case Tns:
1310 		fmtprint(&fstr,  " ns=%s", dnname(rp->host));
1311 		break;
1312 	case Tmg:
1313 	case Tmr:
1314 		fmtprint(&fstr, " mbox=%s", dnname(rp->mb));
1315 		break;
1316 	case Tminfo:
1317 		fmtprint(&fstr, " mbox=%s mbox=%s",
1318 			dnname(rp->mb), dnname(rp->rmb));
1319 		break;
1320 	case Tmx:
1321 		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host));
1322 		break;
1323 	case Ta:
1324 	case Taaaa:
1325 		fmtprint(&fstr, " ip=%s", dnname(rp->ip));
1326 		break;
1327 	case Tptr:
1328 		fmtprint(&fstr, " dom=%s", dnname(rp->ptr));
1329 		break;
1330 	case Tsoa:
1331 		soa = rp->soa;
1332 		fmtprint(&fstr,
1333 " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
1334 			dnname(rp->host), dnname(rp->rmb),
1335 			(soa? soa->serial: 0),
1336 			(soa? soa->refresh: 0), (soa? soa->retry: 0),
1337 			(soa? soa->expire: 0), (soa? soa->minttl: 0));
1338 		for(s = soa->slaves; s != nil; s = s->next)
1339 			fmtprint(&fstr, " dnsslave=%s", s->name);
1340 		break;
1341 	case Tsrv:
1342 		srv = rp->srv;
1343 		fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s",
1344 			(srv? srv->pri: 0), (srv? srv->weight: 0),
1345 			rp->port, dnname(rp->host));
1346 		break;
1347 	case Tnull:
1348 		if (rp->null == nil)
1349 			fmtprint(&fstr, " null=<null>");
1350 		else
1351 			fmtprint(&fstr, " null=%.*H", rp->null->dlen,
1352 				rp->null->data);
1353 		break;
1354 	case Ttxt:
1355 		fmtprint(&fstr, " txt=");
1356 		quote = 0;
1357 		for(t = rp->txt; t != nil; t = t->next)
1358 			if(strchr(t->p, ' '))
1359 				quote = 1;
1360 		if(quote)
1361 			fmtprint(&fstr, "\"");
1362 		for(t = rp->txt; t != nil; t = t->next)
1363 			fmtprint(&fstr, "%s", t->p);
1364 		if(quote)
1365 			fmtprint(&fstr, "\"");
1366 		break;
1367 	case Trp:
1368 		fmtprint(&fstr, " rp=%s txt=%s",
1369 			dnname(rp->rmb), dnname(rp->rp));
1370 		break;
1371 	case Tkey:
1372 		if (rp->key == nil)
1373 			fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>");
1374 		else
1375 			fmtprint(&fstr, " flags=%d proto=%d alg=%d",
1376 				rp->key->flags, rp->key->proto, rp->key->alg);
1377 		break;
1378 	case Tsig:
1379 		if (rp->sig == nil)
1380 			fmtprint(&fstr,
1381 " type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>");
1382 		else
1383 			fmtprint(&fstr,
1384 " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
1385 				rp->sig->type, rp->sig->alg, rp->sig->labels,
1386 				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
1387 				rp->sig->tag, dnname(rp->sig->signer));
1388 		break;
1389 	case Tcert:
1390 		if (rp->cert == nil)
1391 			fmtprint(&fstr, " type=<null> tag=<null> alg=<null>");
1392 		else
1393 			fmtprint(&fstr, " type=%d tag=%d alg=%d",
1394 				rp->cert->type, rp->cert->tag, rp->cert->alg);
1395 		break;
1396 	}
1397 out:
1398 	strp = fmtstrflush(&fstr);
1399 	rv = fmtstrcpy(f, strp);
1400 	free(strp);
1401 	return rv;
1402 }
1403 
1404 void
1405 warning(char *fmt, ...)
1406 {
1407 	char dnserr[256];
1408 	va_list arg;
1409 
1410 	va_start(arg, fmt);
1411 	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
1412 	va_end(arg);
1413 	syslog(1, logfile, dnserr);		/* on console too */
1414 }
1415 
1416 void
1417 dnslog(char *fmt, ...)
1418 {
1419 	char dnserr[256];
1420 	va_list arg;
1421 
1422 	va_start(arg, fmt);
1423 	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
1424 	va_end(arg);
1425 	syslog(0, logfile, dnserr);
1426 }
1427 
1428 /*
1429  * based on libthread's threadsetname, but drags in less library code.
1430  * actually just sets the arguments displayed.
1431  */
1432 void
1433 procsetname(char *fmt, ...)
1434 {
1435 	int fd;
1436 	char *cmdname;
1437 	char buf[128];
1438 	va_list arg;
1439 
1440 	va_start(arg, fmt);
1441 	cmdname = vsmprint(fmt, arg);
1442 	va_end(arg);
1443 	if (cmdname == nil)
1444 		return;
1445 	snprint(buf, sizeof buf, "#p/%d/args", getpid());
1446 	if((fd = open(buf, OWRITE)) >= 0){
1447 		write(fd, cmdname, strlen(cmdname)+1);
1448 		close(fd);
1449 	}
1450 	free(cmdname);
1451 }
1452 
1453 /*
1454  *  create a slave process to handle a request to avoid one request blocking
1455  *  another
1456  */
1457 void
1458 slave(Request *req)
1459 {
1460 	int ppid, procs;
1461 
1462 	if(req->isslave)
1463 		return;		/* we're already a slave process */
1464 
1465 	/*
1466 	 * These calls to putactivity cannot block.
1467 	 * After getactivity(), the current process is counted
1468 	 * twice in dnvars.active (one will pass to the child).
1469 	 * If putactivity tries to wait for dnvars.active == 0,
1470 	 * it will never happen.
1471 	 */
1472 
1473 	/* limit parallelism */
1474 	procs = getactivity(req, 1);
1475 	if (procs > stats.slavehiwat)
1476 		stats.slavehiwat = procs;
1477 	if(procs > Maxactive){
1478 		if(traceactivity)
1479 			dnslog("[%d] too much activity", getpid());
1480 		putactivity(1);
1481 		return;
1482 	}
1483 
1484 	/*
1485 	 * parent returns to main loop, child does the work.
1486 	 * don't change note group.
1487 	 */
1488 	ppid = getpid();
1489 	switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
1490 	case -1:
1491 		putactivity(1);
1492 		break;
1493 	case 0:
1494 		procsetname("request slave of pid %d", ppid);
1495  		if(traceactivity)
1496 			dnslog("[%d] take activity from %d", getpid(), ppid);
1497 		req->isslave = 1;	/* why not `= getpid()'? */
1498 		break;
1499 	default:
1500 		/*
1501 		 * this relies on rfork producing separate, initially-identical
1502 		 * stacks, thus giving us two copies of `req', one in each
1503 		 * process.
1504 		 */
1505 		alarm(0);
1506 		longjmp(req->mret, 1);
1507 	}
1508 }
1509 
1510 /*
1511  *  chasing down double free's
1512  */
1513 void
1514 dncheck(void *p, int dolock)
1515 {
1516 	int i;
1517 	DN *dp;
1518 	RR *rp;
1519 
1520 	if(p != nil){
1521 		dp = p;
1522 		assert(dp->magic == DNmagic);
1523 	}
1524 
1525 	if(!testing)
1526 		return;
1527 
1528 	if(dolock)
1529 		lock(&dnlock);
1530 	poolcheck(mainmem);
1531 	for(i = 0; i < HTLEN; i++)
1532 		for(dp = ht[i]; dp; dp = dp->next){
1533 			assert(dp != p);
1534 			assert(dp->magic == DNmagic);
1535 			for(rp = dp->rr; rp; rp = rp->next){
1536 				assert(rp->magic == RRmagic);
1537 				assert(rp->cached);
1538 				assert(rp->owner == dp);
1539 				/* also check for duplicate rrs */
1540 				if (dolock && rronlist(rp, rp->next)) {
1541 					dnslog("%R duplicates its next chain "
1542 						"(%R); aborting", rp, rp->next);
1543 					abort();
1544 				}
1545 			}
1546 		}
1547 	if(dolock)
1548 		unlock(&dnlock);
1549 }
1550 
1551 static int
1552 rrequiv(RR *r1, RR *r2)
1553 {
1554 	return r1->owner == r2->owner
1555 		&& r1->type == r2->type
1556 		&& r1->arg0 == r2->arg0
1557 		&& r1->arg1 == r2->arg1;
1558 }
1559 
1560 void
1561 unique(RR *rp)
1562 {
1563 	RR **l, *nrp;
1564 
1565 	for(; rp; rp = rp->next){
1566 		l = &rp->next;
1567 		for(nrp = *l; nrp; nrp = *l)
1568 			if(rrequiv(rp, nrp)){
1569 				*l = nrp->next;
1570 				rrfree(nrp);
1571 			} else
1572 				l = &nrp->next;
1573 	}
1574 }
1575 
1576 /*
1577  *  true if second domain is subsumed by the first
1578  */
1579 int
1580 subsume(char *higher, char *lower)
1581 {
1582 	int hn, ln;
1583 
1584 	ln = strlen(lower);
1585 	hn = strlen(higher);
1586 	if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 ||
1587 	    ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
1588 		return 0;
1589 	return 1;
1590 }
1591 
1592 /*
1593  *  randomize the order we return items to provide some
1594  *  load balancing for servers.
1595  *
1596  *  only randomize the first class of entries
1597  */
1598 RR*
1599 randomize(RR *rp)
1600 {
1601 	RR *first, *last, *x, *base;
1602 	ulong n;
1603 
1604 	if(rp == nil || rp->next == nil)
1605 		return rp;
1606 
1607 	/* just randomize addresses, mx's and ns's */
1608 	for(x = rp; x; x = x->next)
1609 		if(x->type != Ta && x->type != Taaaa &&
1610 		    x->type != Tmx && x->type != Tns)
1611 			return rp;
1612 
1613 	base = rp;
1614 
1615 	n = rand();
1616 	last = first = nil;
1617 	while(rp != nil){
1618 		/* stop randomizing if we've moved past our class */
1619 		if(base->auth != rp->auth || base->db != rp->db){
1620 			last->next = rp;
1621 			break;
1622 		}
1623 
1624 		/* unchain */
1625 		x = rp;
1626 		rp = x->next;
1627 		x->next = nil;
1628 
1629 		if(n&1){
1630 			/* add to tail */
1631 			if(last == nil)
1632 				first = x;
1633 			else
1634 				last->next = x;
1635 			last = x;
1636 		} else {
1637 			/* add to head */
1638 			if(last == nil)
1639 				last = x;
1640 			x->next = first;
1641 			first = x;
1642 		}
1643 
1644 		/* reroll the dice */
1645 		n >>= 1;
1646 	}
1647 
1648 	return first;
1649 }
1650 
1651 static int
1652 sencodefmt(Fmt *f)
1653 {
1654 	int i, len, ilen, rv;
1655 	char *out, *buf;
1656 	uchar *b;
1657 	char obuf[64];		/* rsc optimization */
1658 
1659 	if(!(f->flags&FmtPrec) || f->prec < 1)
1660 		goto error;
1661 
1662 	b = va_arg(f->args, uchar*);
1663 	if(b == nil)
1664 		goto error;
1665 
1666 	/* if it's a printable, go for it */
1667 	len = f->prec;
1668 	for(i = 0; i < len; i++)
1669 		if(!isprint(b[i]))
1670 			break;
1671 	if(i == len){
1672 		if(len >= sizeof obuf)
1673 			len = sizeof(obuf)-1;
1674 		memmove(obuf, b, len);
1675 		obuf[len] = 0;
1676 		fmtstrcpy(f, obuf);
1677 		return 0;
1678 	}
1679 
1680 	ilen = f->prec;
1681 	f->prec = 0;
1682 	f->flags &= ~FmtPrec;
1683 	switch(f->r){
1684 	case '<':
1685 		len = (8*ilen+4)/5 + 3;
1686 		break;
1687 	case '[':
1688 		len = (8*ilen+5)/6 + 4;
1689 		break;
1690 	case 'H':
1691 		len = 2*ilen + 1;
1692 		break;
1693 	default:
1694 		goto error;
1695 	}
1696 
1697 	if(len > sizeof(obuf)){
1698 		buf = malloc(len);
1699 		if(buf == nil)
1700 			goto error;
1701 	} else
1702 		buf = obuf;
1703 
1704 	/* convert */
1705 	out = buf;
1706 	switch(f->r){
1707 	case '<':
1708 		rv = enc32(out, len, b, ilen);
1709 		break;
1710 	case '[':
1711 		rv = enc64(out, len, b, ilen);
1712 		break;
1713 	case 'H':
1714 		rv = enc16(out, len, b, ilen);
1715 		break;
1716 	default:
1717 		rv = -1;
1718 		break;
1719 	}
1720 	if(rv < 0)
1721 		goto error;
1722 
1723 	fmtstrcpy(f, buf);
1724 	if(buf != obuf)
1725 		free(buf);
1726 	return 0;
1727 
1728 error:
1729 	return fmtstrcpy(f, "<encodefmt>");
1730 }
1731 
1732 void*
1733 emalloc(int size)
1734 {
1735 	char *x;
1736 
1737 	x = mallocz(size, 1);
1738 	if(x == nil)
1739 		abort();
1740 	setmalloctag(x, getcallerpc(&size));
1741 	return x;
1742 }
1743 
1744 char*
1745 estrdup(char *s)
1746 {
1747 	int size;
1748 	char *p;
1749 
1750 	size = strlen(s)+1;
1751 	p = mallocz(size, 0);
1752 	if(p == nil)
1753 		abort();
1754 	memmove(p, s, size);
1755 	setmalloctag(p, getcallerpc(&s));
1756 	return p;
1757 }
1758 
1759 /*
1760  *  create a pointer record
1761  */
1762 static RR*
1763 mkptr(DN *dp, char *ptr, ulong ttl)
1764 {
1765 	DN *ipdp;
1766 	RR *rp;
1767 
1768 	ipdp = dnlookup(ptr, Cin, 1);
1769 
1770 	rp = rralloc(Tptr);
1771 	rp->ptr = dp;
1772 	rp->owner = ipdp;
1773 	rp->db = 1;
1774 	if(ttl)
1775 		rp->ttl = ttl;
1776 	return rp;
1777 }
1778 
1779 void	bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes);
1780 
1781 /*
1782  *  look for all ip addresses in this network and make
1783  *  pointer records for them.
1784  */
1785 void
1786 dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl)
1787 {
1788 	int i, j, len;
1789 	char *p, *e;
1790 	char ptr[Domlen];
1791 	uchar *ipp;
1792 	uchar ip[IPaddrlen], nnet[IPaddrlen];
1793 	uchar nibip[IPaddrlen*2];
1794 	DN *dp;
1795 	RR *rp, *nrp, *first, **l;
1796 
1797 	l = &first;
1798 	first = nil;
1799 	for(i = 0; i < HTLEN; i++)
1800 		for(dp = ht[i]; dp; dp = dp->next)
1801 			for(rp = dp->rr; rp; rp = rp->next){
1802 				if(rp->type != forwtype || rp->negative)
1803 					continue;
1804 				parseip(ip, rp->ip->name);
1805 				maskip(ip, mask, nnet);
1806 				if(ipcmp(net, nnet) != 0)
1807 					continue;
1808 
1809 				ipp = ip;
1810 				len = IPaddrlen;
1811 				if (forwtype == Taaaa) {
1812 					bytes2nibbles(nibip, ip, IPaddrlen);
1813 					ipp = nibip;
1814 					len = 2*IPaddrlen;
1815 				}
1816 
1817 				p = ptr;
1818 				e = ptr+sizeof(ptr);
1819 				for(j = len - 1; j >= len - subdoms; j--)
1820 					p = seprint(p, e, (forwtype == Ta?
1821 						"%d.": "%x."), ipp[j]);
1822 				seprint(p, e, "%s", dom);
1823 
1824 				nrp = mkptr(dp, ptr, ttl);
1825 				*l = nrp;
1826 				l = &nrp->next;
1827 			}
1828 
1829 	for(rp = first; rp != nil; rp = nrp){
1830 		nrp = rp->next;
1831 		rp->next = nil;
1832 		rrattach(rp, Authoritative);
1833 	}
1834 }
1835 
1836 void
1837 addserver(Server **l, char *name)
1838 {
1839 	Server *s;
1840 
1841 	while(*l)
1842 		l = &(*l)->next;
1843 	s = malloc(sizeof(Server)+strlen(name)+1);
1844 	if(s == nil)
1845 		return;
1846 	s->name = (char*)(s+1);
1847 	strcpy(s->name, name);
1848 	s->next = nil;
1849 	*l = s;
1850 }
1851 
1852 Server*
1853 copyserverlist(Server *s)
1854 {
1855 	Server *ns;
1856 
1857 	for(ns = nil; s != nil; s = s->next)
1858 		addserver(&ns, s->name);
1859 	return ns;
1860 }
1861 
1862 
1863 /* from here down is copied to ip/snoopy/dns.c periodically to update it */
1864 
1865 /*
1866  *  convert an integer RR type to it's ascii name
1867  */
1868 char*
1869 rrname(int type, char *buf, int len)
1870 {
1871 	char *t;
1872 
1873 	t = nil;
1874 	if(type >= 0 && type <= Tall)
1875 		t = rrtname[type];
1876 	if(t==nil){
1877 		snprint(buf, len, "%d", type);
1878 		t = buf;
1879 	}
1880 	return t;
1881 }
1882 
1883 /*
1884  *  free a list of resource records and any related structs
1885  */
1886 void
1887 rrfreelist(RR *rp)
1888 {
1889 	RR *next;
1890 
1891 	for(; rp; rp = next){
1892 		next = rp->next;
1893 		rrfree(rp);
1894 	}
1895 }
1896 
1897 void
1898 freeserverlist(Server *s)
1899 {
1900 	Server *next;
1901 
1902 	for(; s != nil; s = next){
1903 		next = s->next;
1904 		free(s);
1905 	}
1906 }
1907 
1908 /*
1909  *  allocate a resource record of a given type
1910  */
1911 RR*
1912 rralloc(int type)
1913 {
1914 	RR *rp;
1915 
1916 	rp = emalloc(sizeof(*rp));
1917 	rp->magic = RRmagic;
1918 	rp->pc = getcallerpc(&type);
1919 	rp->type = type;
1920 	if (rp->type != type)
1921 		dnslog("rralloc: bogus type %d", type);
1922 	setmalloctag(rp, rp->pc);
1923 	switch(type){
1924 	case Tsoa:
1925 		rp->soa = emalloc(sizeof(*rp->soa));
1926 		rp->soa->slaves = nil;
1927 		setmalloctag(rp->soa, rp->pc);
1928 		break;
1929 	case Tsrv:
1930 		rp->srv = emalloc(sizeof(*rp->srv));
1931 		setmalloctag(rp->srv, rp->pc);
1932 		break;
1933 	case Tkey:
1934 		rp->key = emalloc(sizeof(*rp->key));
1935 		setmalloctag(rp->key, rp->pc);
1936 		break;
1937 	case Tcert:
1938 		rp->cert = emalloc(sizeof(*rp->cert));
1939 		setmalloctag(rp->cert, rp->pc);
1940 		break;
1941 	case Tsig:
1942 		rp->sig = emalloc(sizeof(*rp->sig));
1943 		setmalloctag(rp->sig, rp->pc);
1944 		break;
1945 	case Tnull:
1946 		rp->null = emalloc(sizeof(*rp->null));
1947 		setmalloctag(rp->null, rp->pc);
1948 		break;
1949 	}
1950 	rp->ttl = 0;
1951 	rp->expire = 0;
1952 	rp->next = 0;
1953 	return rp;
1954 }
1955 
1956 /*
1957  *  free a resource record and any related structs
1958  */
1959 void
1960 rrfree(RR *rp)
1961 {
1962 	DN *dp;
1963 	RR *nrp;
1964 	Txt *t;
1965 
1966 	assert(rp->magic = RRmagic);
1967 	assert(!rp->cached);
1968 
1969 	dp = rp->owner;
1970 	if(dp){
1971 		assert(dp->magic == DNmagic);
1972 		for(nrp = dp->rr; nrp; nrp = nrp->next)
1973 			assert(nrp != rp);	/* "rrfree of live rr" */
1974 	}
1975 
1976 	switch(rp->type){
1977 	case Tsoa:
1978 		freeserverlist(rp->soa->slaves);
1979 		memset(rp->soa, 0, sizeof *rp->soa);	/* cause trouble */
1980 		free(rp->soa);
1981 		break;
1982 	case Tsrv:
1983 		memset(rp->srv, 0, sizeof *rp->srv);	/* cause trouble */
1984 		free(rp->srv);
1985 		break;
1986 	case Tkey:
1987 		free(rp->key->data);
1988 		memset(rp->key, 0, sizeof *rp->key);	/* cause trouble */
1989 		free(rp->key);
1990 		break;
1991 	case Tcert:
1992 		free(rp->cert->data);
1993 		memset(rp->cert, 0, sizeof *rp->cert);	/* cause trouble */
1994 		free(rp->cert);
1995 		break;
1996 	case Tsig:
1997 		free(rp->sig->data);
1998 		memset(rp->sig, 0, sizeof *rp->sig);	/* cause trouble */
1999 		free(rp->sig);
2000 		break;
2001 	case Tnull:
2002 		free(rp->null->data);
2003 		memset(rp->null, 0, sizeof *rp->null);	/* cause trouble */
2004 		free(rp->null);
2005 		break;
2006 	case Ttxt:
2007 		while(rp->txt != nil){
2008 			t = rp->txt;
2009 			rp->txt = t->next;
2010 			free(t->p);
2011 			memset(t, 0, sizeof *t);	/* cause trouble */
2012 			free(t);
2013 		}
2014 		break;
2015 	}
2016 
2017 	rp->magic = ~rp->magic;
2018 	memset(rp, 0, sizeof *rp);		/* cause trouble */
2019 	free(rp);
2020 }
2021