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