Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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