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
ding(void *,char * msg)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
dninit(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
dnhash(char * name)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*
dnlookup(char * name,int class,int enter)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
rrsame(RR * rr1,RR * rr2)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
rronlist(RR * rp,RR * lp)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
dnstats(char * file)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
dndump(char * file)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
dnpurge(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
rrdelhead(RR ** l)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
dnage(DN * dp)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
dnagenever(DN * dp,int dolock)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
dnageallnever(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
dnageall(int doit)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
dnagedb(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
dnauthdb(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
getactivity(Request * req,int recursive)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
putactivity(int recursive)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
rrlistlen(RR * rp)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
rrattach1(RR * new,int auth)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
rrattach(RR * rp,int auth)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**
rrcopy(RR * rp,RR ** last)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*
rrlookup(DN * dp,int type,int flag)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
rrtype(char * atype)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
rrsupported(int type)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
tsame(int t1,int t2)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*
rrcat(RR ** start,RR * rp)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*
rrremneg(RR ** l)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*
rrremtype(RR ** l,int type)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 *
dnname(DN * dn)1195 dnname(DN *dn)
1196 {
1197 return dn? dn->name: "<null>";
1198 }
1199
1200 /*
1201 * print conversion for rr records
1202 */
1203 int
rrfmt(Fmt * f)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
rravfmt(Fmt * f)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
warning(char * fmt,...)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
dnslog(char * fmt,...)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
procsetname(char * fmt,...)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
slave(Request * req)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
dncheck(void * p,int dolock)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
rrequiv(RR * r1,RR * r2)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
unique(RR * rp)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
subsume(char * higher,char * lower)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*
randomize(RR * rp)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
sencodefmt(Fmt * f)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*
emalloc(int size)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*
estrdup(char * s)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*
mkptr(DN * dp,char * ptr,ulong ttl)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
dnptr(uchar * net,uchar * mask,char * dom,int forwtype,int subdoms,int ttl)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
addserver(Server ** l,char * name)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*
copyserverlist(Server * s)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*
rrname(int type,char * buf,int len)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
rrfreelist(RR * rp)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
freeserverlist(Server * s)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*
rralloc(int type)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
rrfree(RR * rp)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 }
2085