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