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