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