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