xref: /plan9/sys/src/cmd/ndb/dn.c (revision a8482e058adfb9039bb8aaa40ea4270fc64ff0a4)
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.  trying again with 4000...
15  */
16 enum {
17 	Deftarget = 4000,
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 all current domain names as never to be aged */
381 void
382 dnagenever(void)
383 {
384 	int i;
385 	DN *dp;
386 	RR *rp;
387 
388 	lock(&dnlock);
389 
390 	/* mark referenced domain names in NS RRs */
391 	for(i = 0; i < HTLEN; i++)
392 		for(dp = ht[i]; dp; dp = dp->next) {
393 //			MARK(dp);
394 			for(rp = dp->rr; rp; rp = rp->next){
395 				MARK(rp->owner);
396 				switch(rp->type){
397 				case Tns:
398 					MARK(rp->host);
399 					break;
400 				}
401 			}
402 		}
403 
404 	unlock(&dnlock);
405 
406 	dnslog("%ld initial domain names; target is %ld", dnvars.names, target);
407 	if(dnvars.names >= target)
408 		dnslog("more initial domain names (%ld) than target (%ld)",
409 			dnvars.names, target);
410 }
411 
412 #define REF(dp)	{ if (dp) (dp)->refs++; }
413 
414 /*
415  *  periodicly sweep for old records and remove unreferenced domain names
416  *
417  *  only called when all other threads are locked out
418  */
419 void
420 dnageall(int doit)
421 {
422 	DN *dp, **l;
423 	int i;
424 	RR *rp;
425 	static ulong nextage;
426 
427 	if(dnvars.names < target || (now < nextage && !doit)){
428 		dnvars.oldest = maxage;
429 		return;
430 	}
431 
432 	if(dnvars.names >= target) {
433 		dnslog("more names (%lud) than target (%lud)", dnvars.names,
434 			target);
435 		dnvars.oldest /= 2;
436 		if (dnvars.oldest < Minage)
437 			dnvars.oldest = Minage;		/* don't be silly */
438 	}
439 	if (agefreq > dnvars.oldest / 2)
440 		nextage = now + dnvars.oldest / 2;
441 	else
442 		nextage = now + agefreq;
443 
444 	lock(&dnlock);
445 
446 	/* time out all old entries (and set refs to 0) */
447 	for(i = 0; i < HTLEN; i++)
448 		for(dp = ht[i]; dp; dp = dp->next){
449 			dp->refs = 0;
450 			dnage(dp);
451 		}
452 
453 	/* mark all referenced domain names */
454 	for(i = 0; i < HTLEN; i++)
455 		for(dp = ht[i]; dp; dp = dp->next)
456 			for(rp = dp->rr; rp; rp = rp->next){
457 				REF(rp->owner);
458 				if(rp->negative){
459 					REF(rp->negsoaowner);
460 					continue;
461 				}
462 				switch(rp->type){
463 				case Thinfo:
464 					REF(rp->cpu);
465 					REF(rp->os);
466 					break;
467 				case Ttxt:
468 					break;
469 				case Tcname:
470 				case Tmb:
471 				case Tmd:
472 				case Tmf:
473 				case Tns:
474 				case Tmx:
475 				case Tsrv:
476 					REF(rp->host);
477 					break;
478 				case Tmg:
479 				case Tmr:
480 					REF(rp->mb);
481 					break;
482 				case Tminfo:
483 					REF(rp->rmb);
484 					REF(rp->mb);
485 					break;
486 				case Trp:
487 					REF(rp->rmb);
488 					REF(rp->rp);
489 					break;
490 				case Ta:
491 				case Taaaa:
492 					REF(rp->ip);
493 					break;
494 				case Tptr:
495 					REF(rp->ptr);
496 					break;
497 				case Tsoa:
498 					REF(rp->host);
499 					REF(rp->rmb);
500 					break;
501 				}
502 			}
503 
504 	/* sweep and remove unreferenced domain names */
505 	for(i = 0; i < HTLEN; i++){
506 		l = &ht[i];
507 		for(dp = *l; dp; dp = *l){
508 			if(dp->rr == 0 && dp->refs == 0 && !dp->keep){
509 				assert(dp->magic == DNmagic);
510 				*l = dp->next;
511 
512 				if(dp->name)
513 					free(dp->name);
514 				dp->magic = ~dp->magic;
515 				dnvars.names--;
516 				memset(dp, 0, sizeof *dp); /* cause trouble */
517 				free(dp);
518 
519 				continue;
520 			}
521 			l = &dp->next;
522 		}
523 	}
524 
525 	unlock(&dnlock);
526 }
527 
528 /*
529  *  timeout all database records (used when rereading db)
530  */
531 void
532 dnagedb(void)
533 {
534 	DN *dp;
535 	int i;
536 	RR *rp;
537 
538 	lock(&dnlock);
539 
540 	/* time out all database entries */
541 	for(i = 0; i < HTLEN; i++)
542 		for(dp = ht[i]; dp; dp = dp->next)
543 			for(rp = dp->rr; rp; rp = rp->next)
544 				if(rp->db)
545 					rp->expire = 0;
546 
547 	unlock(&dnlock);
548 }
549 
550 /*
551  *  mark all local db records about my area as authoritative,
552  *  time out any others
553  */
554 void
555 dnauthdb(void)
556 {
557 	int i;
558 	ulong minttl;
559 	Area *area;
560 	DN *dp;
561 	RR *rp;
562 
563 	lock(&dnlock);
564 
565 	/* time out all database entries */
566 	for(i = 0; i < HTLEN; i++)
567 		for(dp = ht[i]; dp; dp = dp->next){
568 			area = inmyarea(dp->name);
569 			for(rp = dp->rr; rp; rp = rp->next)
570 				if(rp->db){
571 					if(area){
572 						minttl = area->soarr->soa->minttl;
573 						if(rp->ttl < minttl)
574 							rp->ttl = minttl;
575 						rp->auth = 1;
576 					}
577 					if(rp->expire == 0){
578 						rp->db = 0;
579 						dp->referenced = now-Reserved-1;
580 					}
581 				}
582 		}
583 
584 	unlock(&dnlock);
585 }
586 
587 /*
588  *  keep track of other processes to know if we can
589  *  garbage collect.  block while garbage collecting.
590  */
591 int
592 getactivity(Request *req, int recursive)
593 {
594 	int rv;
595 
596 	if(traceactivity)
597 		dnslog("get: %d active by pid %d from %p",
598 			dnvars.active, getpid(), getcallerpc(&req));
599 	lock(&dnvars);
600 	/*
601 	 * can't block here if we're already holding one
602 	 * of the dnvars.active (recursive).  will deadlock.
603 	 */
604 	while(!recursive && dnvars.mutex){
605 		unlock(&dnvars);
606 		sleep(100);			/* tune; was 200 */
607 		lock(&dnvars);
608 	}
609 	rv = ++dnvars.active;
610 	now = time(nil);
611 	nowns = nsec();
612 	req->id = ++dnvars.id;
613 	unlock(&dnvars);
614 
615 	return rv;
616 }
617 void
618 putactivity(int recursive)
619 {
620 	static ulong lastclean;
621 
622 	if(traceactivity)
623 		dnslog("put: %d active by pid %d",
624 			dnvars.active, getpid());
625 	lock(&dnvars);
626 	dnvars.active--;
627 	assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */
628 
629 	/*
630 	 *  clean out old entries and check for new db periodicly
631 	 *  can't block here if being called to let go a "recursive" lock
632 	 *  or we'll deadlock waiting for ourselves to give up the dnvars.active.
633 	 */
634 	if (recursive || dnvars.mutex ||
635 	    (needrefresh == 0 && dnvars.active > 0)){
636 		unlock(&dnvars);
637 		return;
638 	}
639 
640 	/* wait till we're alone */
641 	dnvars.mutex = 1;
642 	while(dnvars.active > 0){
643 		unlock(&dnvars);
644 		sleep(100);		/* tune; was 100 */
645 		lock(&dnvars);
646 	}
647 	unlock(&dnvars);
648 
649 	db2cache(needrefresh);
650 	dnageall(0);
651 
652 	/* let others back in */
653 	lastclean = now;
654 	needrefresh = 0;
655 	dnvars.mutex = 0;
656 }
657 
658 int
659 rrlistlen(RR *rp)
660 {
661 	int n;
662 
663 	n = 0;
664 	for(; rp; rp = rp->next)
665 		++n;
666 	return n;
667 }
668 
669 /*
670  *  Attach a single resource record to a domain name (new->owner).
671  *	- Avoid duplicates with already present RR's
672  *	- Chain all RR's of the same type adjacent to one another
673  *	- chain authoritative RR's ahead of non-authoritative ones
674  *	- remove any expired RR's
675  *  If new is a stale duplicate, rrfree it.
676  *  Must be called with dnlock held.
677  */
678 static void
679 rrattach1(RR *new, int auth)
680 {
681 	RR **l;
682 	RR *rp;
683 	DN *dp;
684 
685 	assert(new->magic == RRmagic && !new->cached);
686 
687 //	dnslog("rrattach1: %s", new->owner->name);
688 	if(!new->db)
689 		new->expire = new->ttl;
690 	else
691 		new->expire = now + Year;
692 	dp = new->owner;
693 	assert(dp->magic == DNmagic);
694 	new->auth |= auth;
695 	new->next = 0;
696 
697 	/*
698 	 *  find first rr of the right type
699 	 */
700 	l = &dp->rr;
701 	for(rp = *l; rp; rp = *l){
702 		assert(rp->magic == RRmagic && rp->cached);
703 		if(rp->type == new->type)
704 			break;
705 		l = &rp->next;
706 	}
707 
708 	/*
709 	 *  negative entries replace positive entries
710 	 *  positive entries replace negative entries
711 	 *  newer entries replace older entries with the same fields
712 	 *
713 	 *  look farther ahead than just the next entry when looking
714 	 *  for duplicates; RRs of a given type can have different rdata
715 	 *  fields (e.g. multiple NS servers).
716 	 */
717 	while ((rp = *l) != nil){
718 		assert(rp->magic == RRmagic && rp->cached);
719 		if(rp->type != new->type)
720 			break;
721 
722 		if(rp->db == new->db && rp->auth == new->auth){
723 			/* negative drives out positive and vice versa */
724 			if(rp->negative != new->negative) {
725 				rrdelete(l, rp);
726 				continue;		/* *l == rp->next */
727 			}
728 			/* all things equal, pick the newer one */
729 			else if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
730 				/* new drives out old */
731 				if (new->ttl <= rp->ttl &&
732 				    new->expire <= rp->expire) {
733 					rrfree(new);
734 					return;
735 				}
736 				rrdelete(l, rp);
737 				continue;		/* *l == rp->next */
738 			}
739 			/*
740 			 *  Hack for pointer records.  This makes sure
741 			 *  the ordering in the list reflects the ordering
742 			 *  received or read from the database
743 			 */
744 			else if(rp->type == Tptr &&
745 			    !rp->negative && !new->negative &&
746 			    rp->ptr->ordinal > new->ptr->ordinal)
747 				break;
748 		}
749 		l = &rp->next;
750 	}
751 
752 	if (rronlist(new, *l)) {
753 		/* should not happen; duplicates were processed above */
754 		dnslog("adding duplicate %R to list of %R; aborting", new, *l);
755 		abort();
756 	}
757 	/*
758 	 *  add to chain
759 	 */
760 	new->cached = 1;
761 	new->next = *l;
762 	*l = new;
763 }
764 
765 /*
766  *  Attach a list of resource records to a domain name.
767  *  May rrfree any stale duplicate RRs; dismembers the list.
768  *  Upon return, every RR in the list will have been rrfree-d
769  *  or attached to its domain name.
770  *  See rrattach1 for properties preserved.
771  */
772 void
773 rrattach(RR *rp, int auth)
774 {
775 	RR *next;
776 	DN *dp;
777 
778 	lock(&dnlock);
779 	for(; rp; rp = next){
780 		next = rp->next;
781 		rp->next = nil;
782 		dp = rp->owner;
783 
784 		/* avoid any outside spoofing */
785 //		dnslog("rrattach: %s", rp->owner->name);
786 		if(cfg.cachedb && !rp->db && inmyarea(rp->owner->name))
787 			rrfree(rp);
788 		else {
789 			rrattach1(rp, auth);
790 			if (rrlistlen(dp->rr) % 100 == 0)
791 				dnslog("rrlookup(%s): rr list len is multiple"
792 					" of 100", dp->name);
793 		}
794 	}
795 	unlock(&dnlock);
796 }
797 
798 RR**
799 rrcopy(RR *rp, RR **last)
800 {
801 	Cert *cert;
802 	Key *key;
803 	Null *null;
804 	RR *nrp;
805 	SOA *soa;
806 	Sig *sig;
807 	Txt *t, *nt, **l;
808 
809 	nrp = rralloc(rp->type);
810 	setmalloctag(nrp, getcallerpc(&rp));
811 	switch(rp->type){
812 	case Ttxt:
813 		*nrp = *rp;
814 		l = &nrp->txt;
815 		*l = nil;
816 		for(t = rp->txt; t != nil; t = t->next){
817 			nt = emalloc(sizeof(*nt));
818 			nt->p = estrdup(t->p);
819 			nt->next = nil;
820 			*l = nt;
821 			l = &nt->next;
822 		}
823 		break;
824 	case Tsoa:
825 		soa = nrp->soa;
826 		*nrp = *rp;
827 		nrp->soa = soa;
828 		*nrp->soa = *rp->soa;
829 		nrp->soa->slaves = copyserverlist(rp->soa->slaves);
830 		break;
831 	case Tsrv:
832 		*nrp = *rp;
833 		nrp->srv = emalloc(sizeof *nrp->srv);
834 		*nrp->srv = *rp->srv;
835 		break;
836 	case Tkey:
837 		key = nrp->key;
838 		*nrp = *rp;
839 		nrp->key = key;
840 		*key = *rp->key;
841 		key->data = emalloc(key->dlen);
842 		memmove(key->data, rp->key->data, rp->key->dlen);
843 		break;
844 	case Tsig:
845 		sig = nrp->sig;
846 		*nrp = *rp;
847 		nrp->sig = sig;
848 		*sig = *rp->sig;
849 		sig->data = emalloc(sig->dlen);
850 		memmove(sig->data, rp->sig->data, rp->sig->dlen);
851 		break;
852 	case Tcert:
853 		cert = nrp->cert;
854 		*nrp = *rp;
855 		nrp->cert = cert;
856 		*cert = *rp->cert;
857 		cert->data = emalloc(cert->dlen);
858 		memmove(cert->data, rp->cert->data, rp->cert->dlen);
859 		break;
860 	case Tnull:
861 		null = nrp->null;
862 		*nrp = *rp;
863 		nrp->null = null;
864 		*null = *rp->null;
865 		null->data = emalloc(null->dlen);
866 		memmove(null->data, rp->null->data, rp->null->dlen);
867 		break;
868 	default:
869 		*nrp = *rp;
870 		break;
871 	}
872 	nrp->cached = 0;
873 	nrp->next = 0;
874 	*last = nrp;
875 	return &nrp->next;
876 }
877 
878 /*
879  *  lookup a resource record of a particular type and
880  *  class attached to a domain name.  Return copies.
881  *
882  *  Priority ordering is:
883  *	db authoritative
884  *	not timed out network authoritative
885  *	not timed out network unauthoritative
886  *	unauthoritative db
887  *
888  *  if flag NOneg is set, don't return negative cached entries.
889  *  return nothing instead.
890  */
891 RR*
892 rrlookup(DN *dp, int type, int flag)
893 {
894 	RR *rp, *first, **last;
895 
896 	assert(dp->magic == DNmagic);
897 
898 	first = 0;
899 	last = &first;
900 	lock(&dnlock);
901 
902 	/* try for an authoritative db entry */
903 	for(rp = dp->rr; rp; rp = rp->next){
904 		assert(rp->magic == RRmagic && rp->cached);
905 		if(rp->db)
906 		if(rp->auth)
907 		if(tsame(type, rp->type)) {
908 			last = rrcopy(rp, last);
909 			// setmalloctag(*last, getcallerpc(&dp));
910 		}
911 	}
912 	if(first)
913 		goto out;
914 
915 	/* try for a living authoritative network entry */
916 	for(rp = dp->rr; rp; rp = rp->next){
917 		if(!rp->db)
918 		if(rp->auth)
919 		if(rp->ttl + 60 > now)
920 		if(tsame(type, rp->type)){
921 			if(flag == NOneg && rp->negative)
922 				goto out;
923 			last = rrcopy(rp, last);
924 		}
925 	}
926 	if(first)
927 		goto out;
928 
929 	/* try for a living unauthoritative network entry */
930 	for(rp = dp->rr; rp; rp = rp->next){
931 		if(!rp->db)
932 		if(rp->ttl + 60 > now)
933 		if(tsame(type, rp->type)){
934 			if(flag == NOneg && rp->negative)
935 				goto out;
936 			last = rrcopy(rp, last);
937 		}
938 	}
939 	if(first)
940 		goto out;
941 
942 	/* try for an unauthoritative db entry */
943 	for(rp = dp->rr; rp; rp = rp->next){
944 		if(rp->db)
945 		if(tsame(type, rp->type))
946 			last = rrcopy(rp, last);
947 	}
948 	if(first)
949 		goto out;
950 
951 	/* otherwise, settle for anything we got (except for negative caches) */
952 	for(rp = dp->rr; rp; rp = rp->next)
953 		if(tsame(type, rp->type)){
954 			if(rp->negative)
955 				goto out;
956 			last = rrcopy(rp, last);
957 		}
958 
959 out:
960 	unlock(&dnlock);
961 	unique(first);
962 //	dnslog("rrlookup(%s) -> %#p\t# in-core only", dp->name, first);
963 //	if (first)
964 //		setmalloctag(first, getcallerpc(&dp));
965 	return first;
966 }
967 
968 /*
969  *  convert an ascii RR type name to its integer representation
970  */
971 int
972 rrtype(char *atype)
973 {
974 	int i;
975 
976 	for(i = 0; i <= Tall; i++)
977 		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
978 			return i;
979 
980 	/* make any a synonym for all */
981 	if(strcmp(atype, "any") == 0)
982 		return Tall;
983 	return atoi(atype);
984 }
985 
986 /*
987  *  return 0 if not a supported rr type
988  */
989 int
990 rrsupported(int type)
991 {
992 	if(type < 0 || type >Tall)
993 		return 0;
994 	return rrtname[type] != nil;
995 }
996 
997 /*
998  *  compare 2 types
999  */
1000 int
1001 tsame(int t1, int t2)
1002 {
1003 	return t1 == t2 || t1 == Tall;
1004 }
1005 
1006 /*
1007  *  Add resource records to a list, duplicate them if they are cached
1008  *  RR's since these are shared.
1009  */
1010 RR*
1011 rrcat(RR **start, RR *rp)
1012 {
1013 	RR *olp, *nlp;
1014 	RR **last;
1015 
1016 	/* check for duplicates */
1017 	for (olp = *start; 0 && olp; olp = olp->next)
1018 		for (nlp = rp; nlp; nlp = nlp->next)
1019 			if (rrsame(nlp, olp))
1020 				dnslog("rrcat: duplicate RR: %R", nlp);
1021 	USED(olp);
1022 
1023 	last = start;
1024 	while(*last != nil)
1025 		last = &(*last)->next;
1026 
1027 	*last = rp;
1028 	return *start;
1029 }
1030 
1031 /*
1032  *  remove negative cache rr's from an rr list
1033  */
1034 RR*
1035 rrremneg(RR **l)
1036 {
1037 	RR **nl, *rp;
1038 	RR *first;
1039 
1040 	first = nil;
1041 	nl = &first;
1042 	while(*l != nil){
1043 		rp = *l;
1044 		if(rp->negative){
1045 			*l = rp->next;
1046 			*nl = rp;
1047 			nl = &rp->next;
1048 			*nl = nil;
1049 		} else
1050 			l = &rp->next;
1051 	}
1052 
1053 	return first;
1054 }
1055 
1056 /*
1057  *  remove rr's of a particular type from an rr list
1058  */
1059 RR*
1060 rrremtype(RR **l, int type)
1061 {
1062 	RR *first, *rp;
1063 	RR **nl;
1064 
1065 	first = nil;
1066 	nl = &first;
1067 	while(*l != nil){
1068 		rp = *l;
1069 		if(rp->type == type){
1070 			*l = rp->next;
1071 			*nl = rp;
1072 			nl = &rp->next;
1073 			*nl = nil;
1074 		} else
1075 			l = &(*l)->next;
1076 	}
1077 
1078 	return first;
1079 }
1080 
1081 static char *
1082 dnname(DN *dn)
1083 {
1084 	return dn? dn->name: "<null>";
1085 }
1086 
1087 /*
1088  *  print conversion for rr records
1089  */
1090 int
1091 rrfmt(Fmt *f)
1092 {
1093 	int rv;
1094 	char *strp;
1095 	char buf[Domlen];
1096 	Fmt fstr;
1097 	RR *rp;
1098 	Server *s;
1099 	SOA *soa;
1100 	Srv *srv;
1101 	Txt *t;
1102 
1103 	fmtstrinit(&fstr);
1104 
1105 	rp = va_arg(f->args, RR*);
1106 	if(rp == nil){
1107 		fmtprint(&fstr, "<null>");
1108 		goto out;
1109 	}
1110 
1111 	fmtprint(&fstr, "%s %s", dnname(rp->owner),
1112 		rrname(rp->type, buf, sizeof buf));
1113 
1114 	if(rp->negative){
1115 		fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);
1116 		goto out;
1117 	}
1118 
1119 	switch(rp->type){
1120 	case Thinfo:
1121 		fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os));
1122 		break;
1123 	case Tcname:
1124 	case Tmb:
1125 	case Tmd:
1126 	case Tmf:
1127 	case Tns:
1128 		fmtprint(&fstr, "\t%s", dnname(rp->host));
1129 		break;
1130 	case Tmg:
1131 	case Tmr:
1132 		fmtprint(&fstr, "\t%s", dnname(rp->mb));
1133 		break;
1134 	case Tminfo:
1135 		fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb));
1136 		break;
1137 	case Tmx:
1138 		fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host));
1139 		break;
1140 	case Ta:
1141 	case Taaaa:
1142 		fmtprint(&fstr, "\t%s", dnname(rp->ip));
1143 		break;
1144 	case Tptr:
1145 //		fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr),
1146 //			rp->ptr? rp->ptr->ordinal: "<null>");
1147 		fmtprint(&fstr, "\t%s", dnname(rp->ptr));
1148 		break;
1149 	case Tsoa:
1150 		soa = rp->soa;
1151 		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud",
1152 			dnname(rp->host), dnname(rp->rmb),
1153 			(soa? soa->serial: 0),
1154 			(soa? soa->refresh: 0), (soa? soa->retry: 0),
1155 			(soa? soa->expire: 0), (soa? soa->minttl: 0));
1156 		if (soa)
1157 			for(s = soa->slaves; s != nil; s = s->next)
1158 				fmtprint(&fstr, " %s", s->name);
1159 		break;
1160 	case Tsrv:
1161 		srv = rp->srv;
1162 		fmtprint(&fstr, "\t%ud %ud %ud %s",
1163 			(srv? srv->pri: 0), (srv? srv->weight: 0),
1164 			rp->port, dnname(rp->host));
1165 		break;
1166 	case Tnull:
1167 		if (rp->null == nil)
1168 			fmtprint(&fstr, "\t<null>");
1169 		else
1170 			fmtprint(&fstr, "\t%.*H", rp->null->dlen,
1171 				rp->null->data);
1172 		break;
1173 	case Ttxt:
1174 		fmtprint(&fstr, "\t");
1175 		for(t = rp->txt; t != nil; t = t->next)
1176 			fmtprint(&fstr, "%s", t->p);
1177 		break;
1178 	case Trp:
1179 		fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp));
1180 		break;
1181 	case Tkey:
1182 		if (rp->key == nil)
1183 			fmtprint(&fstr, "\t<null> <null> <null>");
1184 		else
1185 			fmtprint(&fstr, "\t%d %d %d", rp->key->flags,
1186 				rp->key->proto, rp->key->alg);
1187 		break;
1188 	case Tsig:
1189 		if (rp->sig == nil)
1190 			fmtprint(&fstr,
1191 		   "\t<null> <null> <null> <null> <null> <null> <null> <null>");
1192 		else
1193 			fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
1194 				rp->sig->type, rp->sig->alg, rp->sig->labels,
1195 				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
1196 				rp->sig->tag, dnname(rp->sig->signer));
1197 		break;
1198 	case Tcert:
1199 		if (rp->cert == nil)
1200 			fmtprint(&fstr, "\t<null> <null> <null>");
1201 		else
1202 			fmtprint(&fstr, "\t%d %d %d",
1203 				rp->cert->type, rp->cert->tag, rp->cert->alg);
1204 		break;
1205 	}
1206 out:
1207 	strp = fmtstrflush(&fstr);
1208 	rv = fmtstrcpy(f, strp);
1209 	free(strp);
1210 	return rv;
1211 }
1212 
1213 /*
1214  *  print conversion for rr records in attribute value form
1215  */
1216 int
1217 rravfmt(Fmt *f)
1218 {
1219 	int rv, quote;
1220 	char *strp;
1221 	Fmt fstr;
1222 	RR *rp;
1223 	Server *s;
1224 	SOA *soa;
1225 	Srv *srv;
1226 	Txt *t;
1227 
1228 	fmtstrinit(&fstr);
1229 
1230 	rp = va_arg(f->args, RR*);
1231 	if(rp == nil){
1232 		fmtprint(&fstr, "<null>");
1233 		goto out;
1234 	}
1235 
1236 	if(rp->type == Tptr)
1237 		fmtprint(&fstr, "ptr=%s", dnname(rp->owner));
1238 	else
1239 		fmtprint(&fstr, "dom=%s", dnname(rp->owner));
1240 
1241 	switch(rp->type){
1242 	case Thinfo:
1243 		fmtprint(&fstr, " cpu=%s os=%s",
1244 			dnname(rp->cpu), dnname(rp->os));
1245 		break;
1246 	case Tcname:
1247 		fmtprint(&fstr, " cname=%s", dnname(rp->host));
1248 		break;
1249 	case Tmb:
1250 	case Tmd:
1251 	case Tmf:
1252 		fmtprint(&fstr, " mbox=%s", dnname(rp->host));
1253 		break;
1254 	case Tns:
1255 		fmtprint(&fstr,  " ns=%s", dnname(rp->host));
1256 		break;
1257 	case Tmg:
1258 	case Tmr:
1259 		fmtprint(&fstr, " mbox=%s", dnname(rp->mb));
1260 		break;
1261 	case Tminfo:
1262 		fmtprint(&fstr, " mbox=%s mbox=%s",
1263 			dnname(rp->mb), dnname(rp->rmb));
1264 		break;
1265 	case Tmx:
1266 		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host));
1267 		break;
1268 	case Ta:
1269 	case Taaaa:
1270 		fmtprint(&fstr, " ip=%s", dnname(rp->ip));
1271 		break;
1272 	case Tptr:
1273 		fmtprint(&fstr, " dom=%s", dnname(rp->ptr));
1274 		break;
1275 	case Tsoa:
1276 		soa = rp->soa;
1277 		fmtprint(&fstr,
1278 " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
1279 			dnname(rp->host), dnname(rp->rmb),
1280 			(soa? soa->serial: 0),
1281 			(soa? soa->refresh: 0), (soa? soa->retry: 0),
1282 			(soa? soa->expire: 0), (soa? soa->minttl: 0));
1283 		for(s = soa->slaves; s != nil; s = s->next)
1284 			fmtprint(&fstr, " dnsslave=%s", s->name);
1285 		break;
1286 	case Tsrv:
1287 		srv = rp->srv;
1288 		fmtprint(&fstr, " pri=%ud weight=%ud port=%ud target=%s",
1289 			(srv? srv->pri: 0), (srv? srv->weight: 0),
1290 			rp->port, dnname(rp->host));
1291 		break;
1292 	case Tnull:
1293 		if (rp->null == nil)
1294 			fmtprint(&fstr, " null=<null>");
1295 		else
1296 			fmtprint(&fstr, " null=%.*H", rp->null->dlen,
1297 				rp->null->data);
1298 		break;
1299 	case Ttxt:
1300 		fmtprint(&fstr, " txt=");
1301 		quote = 0;
1302 		for(t = rp->txt; t != nil; t = t->next)
1303 			if(strchr(t->p, ' '))
1304 				quote = 1;
1305 		if(quote)
1306 			fmtprint(&fstr, "\"");
1307 		for(t = rp->txt; t != nil; t = t->next)
1308 			fmtprint(&fstr, "%s", t->p);
1309 		if(quote)
1310 			fmtprint(&fstr, "\"");
1311 		break;
1312 	case Trp:
1313 		fmtprint(&fstr, " rp=%s txt=%s",
1314 			dnname(rp->rmb), dnname(rp->rp));
1315 		break;
1316 	case Tkey:
1317 		if (rp->key == nil)
1318 			fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>");
1319 		else
1320 			fmtprint(&fstr, " flags=%d proto=%d alg=%d",
1321 				rp->key->flags, rp->key->proto, rp->key->alg);
1322 		break;
1323 	case Tsig:
1324 		if (rp->sig == nil)
1325 			fmtprint(&fstr,
1326 " type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>");
1327 		else
1328 			fmtprint(&fstr,
1329 " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
1330 				rp->sig->type, rp->sig->alg, rp->sig->labels,
1331 				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
1332 				rp->sig->tag, dnname(rp->sig->signer));
1333 		break;
1334 	case Tcert:
1335 		if (rp->cert == nil)
1336 			fmtprint(&fstr, " type=<null> tag=<null> alg=<null>");
1337 		else
1338 			fmtprint(&fstr, " type=%d tag=%d alg=%d",
1339 				rp->cert->type, rp->cert->tag, rp->cert->alg);
1340 		break;
1341 	}
1342 out:
1343 	strp = fmtstrflush(&fstr);
1344 	rv = fmtstrcpy(f, strp);
1345 	free(strp);
1346 	return rv;
1347 }
1348 
1349 void
1350 warning(char *fmt, ...)
1351 {
1352 	char dnserr[256];
1353 	va_list arg;
1354 
1355 	va_start(arg, fmt);
1356 	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
1357 	va_end(arg);
1358 	syslog(1, logfile, dnserr);		/* on console too */
1359 }
1360 
1361 void
1362 dnslog(char *fmt, ...)
1363 {
1364 	char dnserr[256];
1365 	va_list arg;
1366 
1367 	va_start(arg, fmt);
1368 	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
1369 	va_end(arg);
1370 	syslog(0, logfile, dnserr);
1371 }
1372 
1373 /*
1374  * based on libthread's threadsetname, but drags in less library code.
1375  * actually just sets the arguments displayed.
1376  */
1377 void
1378 procsetname(char *fmt, ...)
1379 {
1380 	int fd;
1381 	char *cmdname;
1382 	char buf[128];
1383 	va_list arg;
1384 
1385 	va_start(arg, fmt);
1386 	cmdname = vsmprint(fmt, arg);
1387 	va_end(arg);
1388 	if (cmdname == nil)
1389 		return;
1390 	snprint(buf, sizeof buf, "#p/%d/args", getpid());
1391 	if((fd = open(buf, OWRITE)) >= 0){
1392 		write(fd, cmdname, strlen(cmdname)+1);
1393 		close(fd);
1394 	}
1395 	free(cmdname);
1396 }
1397 
1398 /*
1399  *  create a slave process to handle a request to avoid one request blocking
1400  *  another
1401  */
1402 void
1403 slave(Request *req)
1404 {
1405 	int ppid, procs;
1406 
1407 	if(req->isslave)
1408 		return;		/* we're already a slave process */
1409 
1410 	/*
1411 	 * These calls to putactivity cannot block.
1412 	 * After getactivity(), the current process is counted
1413 	 * twice in dnvars.active (one will pass to the child).
1414 	 * If putactivity tries to wait for dnvars.active == 0,
1415 	 * it will never happen.
1416 	 */
1417 
1418 	/* limit parallelism */
1419 	procs = getactivity(req, 1);
1420 	if (procs > stats.slavehiwat)
1421 		stats.slavehiwat = procs;
1422 	if(procs > Maxactive){
1423 		if(traceactivity)
1424 			dnslog("[%d] too much activity", getpid());
1425 		putactivity(1);
1426 		return;
1427 	}
1428 
1429 	/*
1430 	 * parent returns to main loop, child does the work.
1431 	 * don't change note group.
1432 	 */
1433 	ppid = getpid();
1434 	switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
1435 	case -1:
1436 		putactivity(1);
1437 		break;
1438 	case 0:
1439 		procsetname("request slave of pid %d", ppid);
1440  		if(traceactivity)
1441 			dnslog("[%d] take activity from %d", getpid(), ppid);
1442 		req->isslave = 1;	/* why not `= getpid()'? */
1443 		break;
1444 	default:
1445 		/*
1446 		 * this relies on rfork producing separate, initially-identical
1447 		 * stacks, thus giving us two copies of `req', one in each
1448 		 * process.
1449 		 */
1450 		alarm(0);
1451 		longjmp(req->mret, 1);
1452 	}
1453 }
1454 
1455 /*
1456  *  chasing down double free's
1457  */
1458 void
1459 dncheck(void *p, int dolock)
1460 {
1461 	int i;
1462 	DN *dp;
1463 	RR *rp;
1464 
1465 	if(p != nil){
1466 		dp = p;
1467 		assert(dp->magic == DNmagic);
1468 	}
1469 
1470 	if(!testing)
1471 		return;
1472 
1473 	if(dolock)
1474 		lock(&dnlock);
1475 	poolcheck(mainmem);
1476 	for(i = 0; i < HTLEN; i++)
1477 		for(dp = ht[i]; dp; dp = dp->next){
1478 			assert(dp != p);
1479 			assert(dp->magic == DNmagic);
1480 			for(rp = dp->rr; rp; rp = rp->next){
1481 				assert(rp->magic == RRmagic);
1482 				assert(rp->cached);
1483 				assert(rp->owner == dp);
1484 				/* also check for duplicate rrs */
1485 				if (dolock && rronlist(rp, rp->next)) {
1486 					dnslog("%R duplicates its next chain "
1487 						"(%R); aborting", rp, rp->next);
1488 					abort();
1489 				}
1490 			}
1491 		}
1492 	if(dolock)
1493 		unlock(&dnlock);
1494 }
1495 
1496 static int
1497 rrequiv(RR *r1, RR *r2)
1498 {
1499 	return r1->owner == r2->owner
1500 		&& r1->type == r2->type
1501 		&& r1->arg0 == r2->arg0
1502 		&& r1->arg1 == r2->arg1;
1503 }
1504 
1505 void
1506 unique(RR *rp)
1507 {
1508 	RR **l, *nrp;
1509 
1510 	for(; rp; rp = rp->next){
1511 		l = &rp->next;
1512 		for(nrp = *l; nrp; nrp = *l)
1513 			if(rrequiv(rp, nrp)){
1514 				*l = nrp->next;
1515 				rrfree(nrp);
1516 			} else
1517 				l = &nrp->next;
1518 	}
1519 }
1520 
1521 /*
1522  *  true if second domain is subsumed by the first
1523  */
1524 int
1525 subsume(char *higher, char *lower)
1526 {
1527 	int hn, ln;
1528 
1529 	ln = strlen(lower);
1530 	hn = strlen(higher);
1531 	if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 ||
1532 	    ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
1533 		return 0;
1534 	return 1;
1535 }
1536 
1537 /*
1538  *  randomize the order we return items to provide some
1539  *  load balancing for servers.
1540  *
1541  *  only randomize the first class of entries
1542  */
1543 RR*
1544 randomize(RR *rp)
1545 {
1546 	RR *first, *last, *x, *base;
1547 	ulong n;
1548 
1549 	if(rp == nil || rp->next == nil)
1550 		return rp;
1551 
1552 	/* just randomize addresses, mx's and ns's */
1553 	for(x = rp; x; x = x->next)
1554 		if(x->type != Ta && x->type != Taaaa &&
1555 		    x->type != Tmx && x->type != Tns)
1556 			return rp;
1557 
1558 	base = rp;
1559 
1560 	n = rand();
1561 	last = first = nil;
1562 	while(rp != nil){
1563 		/* stop randomizing if we've moved past our class */
1564 		if(base->auth != rp->auth || base->db != rp->db){
1565 			last->next = rp;
1566 			break;
1567 		}
1568 
1569 		/* unchain */
1570 		x = rp;
1571 		rp = x->next;
1572 		x->next = nil;
1573 
1574 		if(n&1){
1575 			/* add to tail */
1576 			if(last == nil)
1577 				first = x;
1578 			else
1579 				last->next = x;
1580 			last = x;
1581 		} else {
1582 			/* add to head */
1583 			if(last == nil)
1584 				last = x;
1585 			x->next = first;
1586 			first = x;
1587 		}
1588 
1589 		/* reroll the dice */
1590 		n >>= 1;
1591 	}
1592 
1593 	return first;
1594 }
1595 
1596 static int
1597 sencodefmt(Fmt *f)
1598 {
1599 	int i, len, ilen, rv;
1600 	char *out, *buf;
1601 	uchar *b;
1602 	char obuf[64];		/* rsc optimization */
1603 
1604 	if(!(f->flags&FmtPrec) || f->prec < 1)
1605 		goto error;
1606 
1607 	b = va_arg(f->args, uchar*);
1608 	if(b == nil)
1609 		goto error;
1610 
1611 	/* if it's a printable, go for it */
1612 	len = f->prec;
1613 	for(i = 0; i < len; i++)
1614 		if(!isprint(b[i]))
1615 			break;
1616 	if(i == len){
1617 		if(len >= sizeof obuf)
1618 			len = sizeof(obuf)-1;
1619 		memmove(obuf, b, len);
1620 		obuf[len] = 0;
1621 		fmtstrcpy(f, obuf);
1622 		return 0;
1623 	}
1624 
1625 	ilen = f->prec;
1626 	f->prec = 0;
1627 	f->flags &= ~FmtPrec;
1628 	switch(f->r){
1629 	case '<':
1630 		len = (8*ilen+4)/5 + 3;
1631 		break;
1632 	case '[':
1633 		len = (8*ilen+5)/6 + 4;
1634 		break;
1635 	case 'H':
1636 		len = 2*ilen + 1;
1637 		break;
1638 	default:
1639 		goto error;
1640 	}
1641 
1642 	if(len > sizeof(obuf)){
1643 		buf = malloc(len);
1644 		if(buf == nil)
1645 			goto error;
1646 	} else
1647 		buf = obuf;
1648 
1649 	/* convert */
1650 	out = buf;
1651 	switch(f->r){
1652 	case '<':
1653 		rv = enc32(out, len, b, ilen);
1654 		break;
1655 	case '[':
1656 		rv = enc64(out, len, b, ilen);
1657 		break;
1658 	case 'H':
1659 		rv = enc16(out, len, b, ilen);
1660 		break;
1661 	default:
1662 		rv = -1;
1663 		break;
1664 	}
1665 	if(rv < 0)
1666 		goto error;
1667 
1668 	fmtstrcpy(f, buf);
1669 	if(buf != obuf)
1670 		free(buf);
1671 	return 0;
1672 
1673 error:
1674 	return fmtstrcpy(f, "<encodefmt>");
1675 }
1676 
1677 void*
1678 emalloc(int size)
1679 {
1680 	char *x;
1681 
1682 	x = mallocz(size, 1);
1683 	if(x == nil)
1684 		abort();
1685 	setmalloctag(x, getcallerpc(&size));
1686 	return x;
1687 }
1688 
1689 char*
1690 estrdup(char *s)
1691 {
1692 	int size;
1693 	char *p;
1694 
1695 	size = strlen(s)+1;
1696 	p = mallocz(size, 0);
1697 	if(p == nil)
1698 		abort();
1699 	memmove(p, s, size);
1700 	setmalloctag(p, getcallerpc(&s));
1701 	return p;
1702 }
1703 
1704 /*
1705  *  create a pointer record
1706  */
1707 static RR*
1708 mkptr(DN *dp, char *ptr, ulong ttl)
1709 {
1710 	DN *ipdp;
1711 	RR *rp;
1712 
1713 	ipdp = dnlookup(ptr, Cin, 1);
1714 
1715 	rp = rralloc(Tptr);
1716 	rp->ptr = dp;
1717 	rp->owner = ipdp;
1718 	rp->db = 1;
1719 	if(ttl)
1720 		rp->ttl = ttl;
1721 	return rp;
1722 }
1723 
1724 void	bytes2nibbles(uchar *nibbles, uchar *bytes, int nbytes);
1725 
1726 /*
1727  *  look for all ip addresses in this network and make
1728  *  pointer records for them.
1729  */
1730 void
1731 dnptr(uchar *net, uchar *mask, char *dom, int forwtype, int subdoms, int ttl)
1732 {
1733 	int i, j, len;
1734 	char *p, *e;
1735 	char ptr[Domlen];
1736 	uchar *ipp;
1737 	uchar ip[IPaddrlen], nnet[IPaddrlen];
1738 	uchar nibip[IPaddrlen*2];
1739 	DN *dp;
1740 	RR *rp, *nrp, *first, **l;
1741 
1742 	l = &first;
1743 	first = nil;
1744 	for(i = 0; i < HTLEN; i++)
1745 		for(dp = ht[i]; dp; dp = dp->next)
1746 			for(rp = dp->rr; rp; rp = rp->next){
1747 				if(rp->type != forwtype || rp->negative)
1748 					continue;
1749 				parseip(ip, rp->ip->name);
1750 				maskip(ip, mask, nnet);
1751 				if(ipcmp(net, nnet) != 0)
1752 					continue;
1753 
1754 				ipp = ip;
1755 				len = IPaddrlen;
1756 				if (forwtype == Taaaa) {
1757 					bytes2nibbles(nibip, ip, IPaddrlen);
1758 					ipp = nibip;
1759 					len = 2*IPaddrlen;
1760 				}
1761 
1762 				p = ptr;
1763 				e = ptr+sizeof(ptr);
1764 				for(j = len - 1; j >= len - subdoms; j--)
1765 					p = seprint(p, e, (forwtype == Ta?
1766 						"%d.": "%x."), ipp[j]);
1767 				seprint(p, e, "%s", dom);
1768 
1769 				nrp = mkptr(dp, ptr, ttl);
1770 				*l = nrp;
1771 				l = &nrp->next;
1772 			}
1773 
1774 	for(rp = first; rp != nil; rp = nrp){
1775 		nrp = rp->next;
1776 		rp->next = nil;
1777 		rrattach(rp, Authoritative);
1778 	}
1779 }
1780 
1781 void
1782 addserver(Server **l, char *name)
1783 {
1784 	Server *s;
1785 
1786 	while(*l)
1787 		l = &(*l)->next;
1788 	s = malloc(sizeof(Server)+strlen(name)+1);
1789 	if(s == nil)
1790 		return;
1791 	s->name = (char*)(s+1);
1792 	strcpy(s->name, name);
1793 	s->next = nil;
1794 	*l = s;
1795 }
1796 
1797 Server*
1798 copyserverlist(Server *s)
1799 {
1800 	Server *ns;
1801 
1802 	for(ns = nil; s != nil; s = s->next)
1803 		addserver(&ns, s->name);
1804 	return ns;
1805 }
1806 
1807 
1808 /* from here down is copied to ip/snoopy/dns.c periodically to update it */
1809 
1810 /*
1811  *  convert an integer RR type to it's ascii name
1812  */
1813 char*
1814 rrname(int type, char *buf, int len)
1815 {
1816 	char *t;
1817 
1818 	t = nil;
1819 	if(type >= 0 && type <= Tall)
1820 		t = rrtname[type];
1821 	if(t==nil){
1822 		snprint(buf, len, "%d", type);
1823 		t = buf;
1824 	}
1825 	return t;
1826 }
1827 
1828 /*
1829  *  free a list of resource records and any related structs
1830  */
1831 void
1832 rrfreelist(RR *rp)
1833 {
1834 	RR *next;
1835 
1836 	for(; rp; rp = next){
1837 		next = rp->next;
1838 		rrfree(rp);
1839 	}
1840 }
1841 
1842 void
1843 freeserverlist(Server *s)
1844 {
1845 	Server *next;
1846 
1847 	for(; s != nil; s = next){
1848 		next = s->next;
1849 		free(s);
1850 	}
1851 }
1852 
1853 /*
1854  *  allocate a resource record of a given type
1855  */
1856 RR*
1857 rralloc(int type)
1858 {
1859 	RR *rp;
1860 
1861 	rp = emalloc(sizeof(*rp));
1862 	rp->magic = RRmagic;
1863 	rp->pc = getcallerpc(&type);
1864 	rp->type = type;
1865 	if (rp->type != type)
1866 		dnslog("rralloc: bogus type %d", type);
1867 	setmalloctag(rp, rp->pc);
1868 	switch(type){
1869 	case Tsoa:
1870 		rp->soa = emalloc(sizeof(*rp->soa));
1871 		rp->soa->slaves = nil;
1872 		setmalloctag(rp->soa, rp->pc);
1873 		break;
1874 	case Tsrv:
1875 		rp->srv = emalloc(sizeof(*rp->srv));
1876 		setmalloctag(rp->srv, rp->pc);
1877 		break;
1878 	case Tkey:
1879 		rp->key = emalloc(sizeof(*rp->key));
1880 		setmalloctag(rp->key, rp->pc);
1881 		break;
1882 	case Tcert:
1883 		rp->cert = emalloc(sizeof(*rp->cert));
1884 		setmalloctag(rp->cert, rp->pc);
1885 		break;
1886 	case Tsig:
1887 		rp->sig = emalloc(sizeof(*rp->sig));
1888 		setmalloctag(rp->sig, rp->pc);
1889 		break;
1890 	case Tnull:
1891 		rp->null = emalloc(sizeof(*rp->null));
1892 		setmalloctag(rp->null, rp->pc);
1893 		break;
1894 	}
1895 	rp->ttl = 0;
1896 	rp->expire = 0;
1897 	rp->next = 0;
1898 	return rp;
1899 }
1900 
1901 /*
1902  *  free a resource record and any related structs
1903  */
1904 void
1905 rrfree(RR *rp)
1906 {
1907 	DN *dp;
1908 	RR *nrp;
1909 	Txt *t;
1910 
1911 	assert(rp->magic = RRmagic);
1912 	assert(!rp->cached);
1913 
1914 	dp = rp->owner;
1915 	if(dp){
1916 		assert(dp->magic == DNmagic);
1917 		for(nrp = dp->rr; nrp; nrp = nrp->next)
1918 			assert(nrp != rp);	/* "rrfree of live rr" */
1919 	}
1920 
1921 	switch(rp->type){
1922 	case Tsoa:
1923 		freeserverlist(rp->soa->slaves);
1924 		memset(rp->soa, 0, sizeof *rp->soa);	/* cause trouble */
1925 		free(rp->soa);
1926 		break;
1927 	case Tsrv:
1928 		memset(rp->srv, 0, sizeof *rp->srv);	/* cause trouble */
1929 		free(rp->srv);
1930 		break;
1931 	case Tkey:
1932 		free(rp->key->data);
1933 		memset(rp->key, 0, sizeof *rp->key);	/* cause trouble */
1934 		free(rp->key);
1935 		break;
1936 	case Tcert:
1937 		free(rp->cert->data);
1938 		memset(rp->cert, 0, sizeof *rp->cert);	/* cause trouble */
1939 		free(rp->cert);
1940 		break;
1941 	case Tsig:
1942 		free(rp->sig->data);
1943 		memset(rp->sig, 0, sizeof *rp->sig);	/* cause trouble */
1944 		free(rp->sig);
1945 		break;
1946 	case Tnull:
1947 		free(rp->null->data);
1948 		memset(rp->null, 0, sizeof *rp->null);	/* cause trouble */
1949 		free(rp->null);
1950 		break;
1951 	case Ttxt:
1952 		while(rp->txt != nil){
1953 			t = rp->txt;
1954 			rp->txt = t->next;
1955 			free(t->p);
1956 			memset(t, 0, sizeof *t);	/* cause trouble */
1957 			free(t);
1958 		}
1959 		break;
1960 	}
1961 
1962 	rp->magic = ~rp->magic;
1963 	memset(rp, 0, sizeof *rp);		/* cause trouble */
1964 	free(rp);
1965 }
1966