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