dn.c (27596B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 #include <ctype.h> 5 #include <bio.h> 6 #include <ndb.h> 7 #include <thread.h> 8 #include "dns.h" 9 10 /* 11 * Hash table for domain names. The hash is based only on the 12 * first element of the domain name. 13 */ 14 DN *ht[HTLEN]; 15 16 17 static struct 18 { 19 Lock lk; 20 ulong names; /* names allocated */ 21 ulong oldest; /* longest we'll leave a name around */ 22 int active; 23 int mutex; 24 int id; 25 } dnvars; 26 27 /* names of RR types */ 28 char *rrtname[Tall+2] = 29 { 30 nil, 31 "ip", 32 "ns", 33 "md", 34 "mf", 35 "cname", 36 "soa", 37 "mb", 38 "mg", 39 "mr", 40 "null", 41 "wks", 42 "ptr", 43 "hinfo", 44 "minfo", 45 "mx", 46 "txt", 47 "rp", 48 nil, 49 nil, 50 nil, 51 nil, 52 nil, 53 nil, 54 "sig", 55 "key", 56 nil, 57 nil, 58 "aaaa", 59 nil, 60 nil, 61 nil, 62 nil, 63 nil, 64 nil, 65 nil, 66 nil, 67 "cert", 68 nil, 69 nil, 70 71 /* 40 */ nil, nil, nil, nil, nil, nil, nil, nil, 72 /* 48 */ nil, nil, nil, nil, nil, nil, nil, nil, 73 /* 56 */ nil, nil, nil, nil, nil, nil, nil, nil, 74 /* 64 */ nil, nil, nil, nil, nil, nil, nil, nil, 75 /* 72 */ nil, nil, nil, nil, nil, nil, nil, nil, 76 /* 80 */ nil, nil, nil, nil, nil, nil, nil, nil, 77 /* 88 */ nil, nil, nil, nil, nil, nil, nil, nil, 78 /* 96 */ nil, nil, nil, nil, nil, nil, nil, nil, 79 /* 104 */ nil, nil, nil, nil, nil, nil, nil, nil, 80 /* 112 */ nil, nil, nil, nil, nil, nil, nil, nil, 81 /* 120 */ nil, nil, nil, nil, nil, nil, nil, nil, 82 /* 128 */ nil, nil, nil, nil, nil, nil, nil, nil, 83 /* 136 */ nil, nil, nil, nil, nil, nil, nil, nil, 84 /* 144 */ nil, nil, nil, nil, nil, nil, nil, nil, 85 /* 152 */ nil, nil, nil, nil, nil, nil, nil, nil, 86 /* 160 */ nil, nil, nil, nil, nil, nil, nil, nil, 87 /* 168 */ nil, nil, nil, nil, nil, nil, nil, nil, 88 /* 176 */ nil, nil, nil, nil, nil, nil, nil, nil, 89 /* 184 */ nil, nil, nil, nil, nil, nil, nil, nil, 90 /* 192 */ nil, nil, nil, nil, nil, nil, nil, nil, 91 /* 200 */ nil, nil, nil, nil, nil, nil, nil, nil, 92 /* 208 */ nil, nil, nil, nil, nil, nil, nil, nil, 93 /* 216 */ nil, nil, nil, nil, nil, nil, nil, nil, 94 /* 224 */ nil, nil, nil, nil, nil, nil, nil, nil, 95 /* 232 */ nil, nil, nil, nil, nil, nil, nil, nil, 96 /* 240 */ nil, nil, nil, nil, nil, nil, nil, nil, 97 /* 248 */ nil, nil, nil, 98 99 "ixfr", 100 "axfr", 101 "mailb", 102 nil, 103 "all", 104 nil 105 }; 106 107 /* names of response codes */ 108 char *rname[Rmask+1] = 109 { 110 "ok", 111 "format error", 112 "server failure", 113 "bad name", 114 "unimplemented", 115 "we don't like you" 116 }; 117 118 Lock dnlock; 119 120 static int sencodefmt(Fmt*); 121 122 /* 123 * set up a pipe to use as a lock 124 */ 125 void 126 dninit(void) 127 { 128 fmtinstall('E', eipfmt); 129 fmtinstall('I', eipfmt); 130 fmtinstall('V', eipfmt); 131 fmtinstall('R', rrfmt); 132 fmtinstall('Q', rravfmt); 133 fmtinstall('H', sencodefmt); 134 135 dnvars.oldest = maxage; 136 dnvars.names = 0; 137 } 138 139 /* 140 * hash for a domain name 141 */ 142 static ulong 143 dnhash(char *name) 144 { 145 ulong hash; 146 uchar *val = (uchar*)name; 147 148 for(hash = 0; *val; val++) 149 hash = (hash*13) + tolower(*val)-'a'; 150 return hash % HTLEN; 151 } 152 153 /* 154 * lookup a symbol. if enter is not zero and the name is 155 * not found, create it. 156 */ 157 DN* 158 dnlookup(char *name, int class, int enter) 159 { 160 DN **l; 161 DN *dp; 162 163 l = &ht[dnhash(name)]; 164 lock(&dnlock); 165 for(dp = *l; dp; dp = dp->next) { 166 assert(dp->magic == DNmagic); 167 if(dp->class == class && cistrcmp(dp->name, name) == 0){ 168 dp->referenced = now; 169 unlock(&dnlock); 170 return dp; 171 } 172 l = &dp->next; 173 } 174 if(enter == 0){ 175 unlock(&dnlock); 176 return 0; 177 } 178 dnvars.names++; 179 dp = emalloc(sizeof(*dp)); 180 dp->magic = DNmagic; 181 dp->name = estrdup(name); 182 assert(dp->name != 0); 183 dp->class = class; 184 dp->rr = 0; 185 dp->next = 0; 186 dp->referenced = now; 187 *l = dp; 188 unlock(&dnlock); 189 190 return dp; 191 } 192 193 /* 194 * dump the cache 195 */ 196 void 197 dndump(char *file) 198 { 199 DN *dp; 200 int i, fd; 201 RR *rp; 202 203 fd = open(file, OWRITE|OTRUNC); 204 if(fd < 0) 205 return; 206 lock(&dnlock); 207 for(i = 0; i < HTLEN; i++){ 208 for(dp = ht[i]; dp; dp = dp->next){ 209 fprint(fd, "%s\n", dp->name); 210 for(rp = dp->rr; rp; rp = rp->next) 211 fprint(fd, " %R %c%c %lud/%lud\n", rp, rp->auth?'A':'U', 212 rp->db?'D':'N', rp->expire, rp->ttl); 213 } 214 } 215 unlock(&dnlock); 216 close(fd); 217 } 218 219 /* 220 * purge all records 221 */ 222 void 223 dnpurge(void) 224 { 225 DN *dp; 226 RR *rp, *srp; 227 int i; 228 229 lock(&dnlock); 230 231 for(i = 0; i < HTLEN; i++) 232 for(dp = ht[i]; dp; dp = dp->next){ 233 srp = rp = dp->rr; 234 dp->rr = nil; 235 for(; rp != nil; rp = rp->next) 236 rp->cached = 0; 237 rrfreelist(srp); 238 } 239 240 unlock(&dnlock); 241 } 242 243 /* 244 * check the age of resource records, free any that have timed out 245 */ 246 void 247 dnage(DN *dp) 248 { 249 RR **l; 250 RR *rp, *next; 251 ulong diff; 252 253 diff = now - dp->referenced; 254 if(diff < Reserved) 255 return; 256 257 l = &dp->rr; 258 for(rp = dp->rr; rp; rp = next){ 259 assert(rp->magic == RRmagic && rp->cached); 260 next = rp->next; 261 if(!rp->db) 262 if(rp->expire < now || diff > dnvars.oldest){ 263 *l = next; 264 rp->cached = 0; 265 rrfree(rp); 266 continue; 267 } 268 l = &rp->next; 269 } 270 } 271 272 #define REF(x) if(x) x->refs++ 273 274 /* 275 * our target is 4000 names cached, this should be larger on large servers 276 */ 277 #define TARGET 4000 278 279 /* 280 * periodicly sweep for old records and remove unreferenced domain names 281 * 282 * only called when all other threads are locked out 283 */ 284 void 285 dnageall(int doit) 286 { 287 DN *dp, **l; 288 int i; 289 RR *rp; 290 static ulong nextage; 291 292 if(dnvars.names < TARGET && now < nextage && !doit){ 293 dnvars.oldest = maxage; 294 return; 295 } 296 297 if(dnvars.names > TARGET) 298 dnvars.oldest /= 2; 299 nextage = now + maxage; 300 301 lock(&dnlock); 302 303 /* time out all old entries (and set refs to 0) */ 304 for(i = 0; i < HTLEN; i++) 305 for(dp = ht[i]; dp; dp = dp->next){ 306 dp->refs = 0; 307 dnage(dp); 308 } 309 310 /* mark all referenced domain names */ 311 for(i = 0; i < HTLEN; i++) 312 for(dp = ht[i]; dp; dp = dp->next) 313 for(rp = dp->rr; rp; rp = rp->next){ 314 REF(rp->owner); 315 if(rp->negative){ 316 REF(rp->negsoaowner); 317 continue; 318 } 319 switch(rp->type){ 320 case Thinfo: 321 REF(rp->cpu); 322 REF(rp->os); 323 break; 324 case Ttxt: 325 break; 326 case Tcname: 327 case Tmb: 328 case Tmd: 329 case Tmf: 330 case Tns: 331 REF(rp->host); 332 break; 333 case Tmg: 334 case Tmr: 335 REF(rp->mb); 336 break; 337 case Tminfo: 338 REF(rp->rmb); 339 REF(rp->mb); 340 break; 341 case Trp: 342 REF(rp->rmb); 343 REF(rp->rp); 344 break; 345 case Tmx: 346 REF(rp->host); 347 break; 348 case Ta: 349 case Taaaa: 350 REF(rp->ip); 351 break; 352 case Tptr: 353 REF(rp->ptr); 354 break; 355 case Tsoa: 356 REF(rp->host); 357 REF(rp->rmb); 358 break; 359 } 360 } 361 362 /* sweep and remove unreferenced domain names */ 363 for(i = 0; i < HTLEN; i++){ 364 l = &ht[i]; 365 for(dp = *l; dp; dp = *l){ 366 if(dp->rr == 0 && dp->refs == 0){ 367 assert(dp->magic == DNmagic); 368 *l = dp->next; 369 if(dp->name) 370 free(dp->name); 371 dp->magic = ~dp->magic; 372 dnvars.names--; 373 free(dp); 374 continue; 375 } 376 l = &dp->next; 377 } 378 } 379 380 unlock(&dnlock); 381 } 382 383 /* 384 * timeout all database records (used when rereading db) 385 */ 386 void 387 dnagedb(void) 388 { 389 DN *dp; 390 int i; 391 RR *rp; 392 393 lock(&dnlock); 394 395 /* time out all database entries */ 396 for(i = 0; i < HTLEN; i++) 397 for(dp = ht[i]; dp; dp = dp->next) 398 for(rp = dp->rr; rp; rp = rp->next) 399 if(rp->db) 400 rp->expire = 0; 401 402 unlock(&dnlock); 403 } 404 405 /* 406 * mark all local db records about my area as authoritative, time out any others 407 */ 408 void 409 dnauthdb(void) 410 { 411 DN *dp; 412 int i; 413 Area *area; 414 RR *rp; 415 416 lock(&dnlock); 417 418 /* time out all database entries */ 419 for(i = 0; i < HTLEN; i++) 420 for(dp = ht[i]; dp; dp = dp->next){ 421 area = inmyarea(dp->name); 422 for(rp = dp->rr; rp; rp = rp->next) 423 if(rp->db){ 424 if(area){ 425 if(rp->ttl < area->soarr->soa->minttl) 426 rp->ttl = area->soarr->soa->minttl; 427 rp->auth = 1; 428 } 429 if(rp->expire == 0){ 430 rp->db = 0; 431 dp->referenced = now - Reserved - 1; 432 } 433 } 434 } 435 436 unlock(&dnlock); 437 } 438 439 /* 440 * keep track of other processes to know if we can 441 * garbage collect. block while garbage collecting. 442 */ 443 int 444 getactivity(Request *req) 445 { 446 int rv; 447 448 if(traceactivity) syslog(0, "dns", "get %d by %d.%d", dnvars.active, getpid(), threadid()); 449 lock(&dnvars.lk); 450 while(dnvars.mutex){ 451 unlock(&dnvars.lk); 452 sleep(200); 453 lock(&dnvars.lk); 454 } 455 rv = ++dnvars.active; 456 now = time(0); 457 req->id = ++dnvars.id; 458 unlock(&dnvars.lk); 459 460 return rv; 461 } 462 void 463 putactivity(void) 464 { 465 if(traceactivity) syslog(0, "dns", "put %d by %d.%d", dnvars.active, getpid(), threadid()); 466 lock(&dnvars.lk); 467 dnvars.active--; 468 assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */; 469 470 /* 471 * clean out old entries and check for new db periodicly 472 */ 473 if(dnvars.mutex || (needrefresh == 0 && dnvars.active > 0)){ 474 unlock(&dnvars.lk); 475 return; 476 } 477 478 /* wait till we're alone */ 479 dnvars.mutex = 1; 480 while(dnvars.active > 0){ 481 unlock(&dnvars.lk); 482 sleep(100); 483 lock(&dnvars.lk); 484 } 485 unlock(&dnvars.lk); 486 487 db2cache(needrefresh); 488 dnageall(0); 489 490 /* let others back in */ 491 needrefresh = 0; 492 dnvars.mutex = 0; 493 } 494 495 /* 496 * Attach a single resource record to a domain name. 497 * - Avoid duplicates with already present RR's 498 * - Chain all RR's of the same type adjacent to one another 499 * - chain authoritative RR's ahead of non-authoritative ones 500 */ 501 static void 502 rrattach1(RR *new, int auth) 503 { 504 RR **l; 505 RR *rp; 506 DN *dp; 507 508 assert(new->magic == RRmagic && !new->cached); 509 510 if(!new->db) 511 new->expire = new->ttl; 512 else 513 new->expire = now + Year; 514 dp = new->owner; 515 assert(dp->magic == DNmagic); 516 new->auth |= auth; 517 new->next = 0; 518 519 /* 520 * find first rr of the right type 521 */ 522 l = &dp->rr; 523 for(rp = *l; rp; rp = *l){ 524 assert(rp->magic == RRmagic && rp->cached); 525 if(rp->type == new->type) 526 break; 527 l = &rp->next; 528 } 529 530 /* 531 * negative entries replace positive entries 532 * positive entries replace negative entries 533 * newer entries replace older entries with the same fields 534 */ 535 for(rp = *l; rp; rp = *l){ 536 assert(rp->magic == RRmagic && rp->cached); 537 if(rp->type != new->type) 538 break; 539 540 if(rp->db == new->db && rp->auth == new->auth){ 541 /* negative drives out positive and vice versa */ 542 if(rp->negative != new->negative){ 543 *l = rp->next; 544 rp->cached = 0; 545 rrfree(rp); 546 continue; 547 } 548 549 /* all things equal, pick the newer one */ 550 if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){ 551 /* new drives out old */ 552 if(new->ttl > rp->ttl || new->expire > rp->expire){ 553 *l = rp->next; 554 rp->cached = 0; 555 rrfree(rp); 556 continue; 557 } else { 558 rrfree(new); 559 return; 560 } 561 } 562 563 /* Hack for pointer records. This makes sure 564 * the ordering in the list reflects the ordering 565 * received or read from the database 566 */ 567 if(rp->type == Tptr){ 568 if(!rp->negative && !new->negative 569 && rp->ptr->ordinal > new->ptr->ordinal) 570 break; 571 } 572 } 573 l = &rp->next; 574 } 575 576 /* 577 * add to chain 578 */ 579 new->cached = 1; 580 new->next = *l; 581 *l = new; 582 } 583 584 /* 585 * Attach a list of resource records to a domain name. 586 * - Avoid duplicates with already present RR's 587 * - Chain all RR's of the same type adjacent to one another 588 * - chain authoritative RR's ahead of non-authoritative ones 589 * - remove any expired RR's 590 */ 591 void 592 rrattach(RR *rp, int auth) 593 { 594 RR *next; 595 596 lock(&dnlock); 597 for(; rp; rp = next){ 598 next = rp->next; 599 rp->next = 0; 600 601 /* avoid any outside spoofing */ 602 if(cachedb && !rp->db && inmyarea(rp->owner->name)) 603 rrfree(rp); 604 else 605 rrattach1(rp, auth); 606 } 607 unlock(&dnlock); 608 } 609 610 /* 611 * allocate a resource record of a given type 612 */ 613 RR* 614 rralloc(int type) 615 { 616 RR *rp; 617 618 rp = emalloc(sizeof(*rp)); 619 rp->magic = RRmagic; 620 rp->pc = getcallerpc(&type); 621 rp->type = type; 622 switch(type){ 623 case Tsoa: 624 rp->soa = emalloc(sizeof(*rp->soa)); 625 rp->soa->slaves = nil; 626 break; 627 case Tkey: 628 rp->key = emalloc(sizeof(*rp->key)); 629 break; 630 case Tcert: 631 rp->cert = emalloc(sizeof(*rp->cert)); 632 break; 633 case Tsig: 634 rp->sig = emalloc(sizeof(*rp->sig)); 635 break; 636 case Tnull: 637 rp->null = emalloc(sizeof(*rp->null)); 638 break; 639 } 640 rp->ttl = 0; 641 rp->expire = 0; 642 rp->next = 0; 643 return rp; 644 } 645 646 /* 647 * free a resource record and any related structs 648 */ 649 void 650 rrfree(RR *rp) 651 { 652 DN *dp; 653 RR *nrp; 654 Txt *t; 655 656 assert(rp->magic = RRmagic); 657 assert(!rp->cached); 658 659 dp = rp->owner; 660 if(dp){ 661 assert(dp->magic == DNmagic); 662 for(nrp = dp->rr; nrp; nrp = nrp->next) 663 assert(nrp != rp); /* "rrfree of live rr" */; 664 } 665 666 switch(rp->type){ 667 case Tsoa: 668 freeserverlist(rp->soa->slaves); 669 free(rp->soa); 670 break; 671 case Tkey: 672 free(rp->key->data); 673 free(rp->key); 674 break; 675 case Tcert: 676 free(rp->cert->data); 677 free(rp->cert); 678 break; 679 case Tsig: 680 free(rp->sig->data); 681 free(rp->sig); 682 break; 683 case Tnull: 684 free(rp->null->data); 685 free(rp->null); 686 break; 687 case Ttxt: 688 while(rp->txt != nil){ 689 t = rp->txt; 690 rp->txt = t->next; 691 free(t->p); 692 free(t); 693 } 694 break; 695 } 696 697 rp->magic = ~rp->magic; 698 free(rp); 699 } 700 701 /* 702 * free a list of resource records and any related structs 703 */ 704 void 705 rrfreelist(RR *rp) 706 { 707 RR *next; 708 709 for(; rp; rp = next){ 710 next = rp->next; 711 rrfree(rp); 712 } 713 } 714 715 extern RR** 716 rrcopy(RR *rp, RR **last) 717 { 718 RR *nrp; 719 SOA *soa; 720 Key *key; 721 Cert *cert; 722 Sig *sig; 723 Null *null; 724 Txt *t, *nt, **l; 725 726 nrp = rralloc(rp->type); 727 switch(rp->type){ 728 case Ttxt: 729 *nrp = *rp; 730 l = &nrp->txt; 731 *l = nil; 732 for(t = rp->txt; t != nil; t = t->next){ 733 nt = emalloc(sizeof(*nt)); 734 nt->p = estrdup(t->p); 735 nt->next = nil; 736 *l = nt; 737 l = &nt->next; 738 } 739 break; 740 case Tsoa: 741 soa = nrp->soa; 742 *nrp = *rp; 743 nrp->soa = soa; 744 *nrp->soa = *rp->soa; 745 nrp->soa->slaves = copyserverlist(rp->soa->slaves); 746 break; 747 case Tkey: 748 key = nrp->key; 749 *nrp = *rp; 750 nrp->key = key; 751 *key = *rp->key; 752 key->data = emalloc(key->dlen); 753 memmove(key->data, rp->key->data, rp->key->dlen); 754 break; 755 case Tsig: 756 sig = nrp->sig; 757 *nrp = *rp; 758 nrp->sig = sig; 759 *sig = *rp->sig; 760 sig->data = emalloc(sig->dlen); 761 memmove(sig->data, rp->sig->data, rp->sig->dlen); 762 break; 763 case Tcert: 764 cert = nrp->cert; 765 *nrp = *rp; 766 nrp->cert = cert; 767 *cert = *rp->cert; 768 cert->data = emalloc(cert->dlen); 769 memmove(cert->data, rp->cert->data, rp->cert->dlen); 770 break; 771 case Tnull: 772 null = nrp->null; 773 *nrp = *rp; 774 nrp->null = null; 775 *null = *rp->null; 776 null->data = emalloc(null->dlen); 777 memmove(null->data, rp->null->data, rp->null->dlen); 778 break; 779 default: 780 *nrp = *rp; 781 break; 782 } 783 nrp->cached = 0; 784 nrp->next = 0; 785 *last = nrp; 786 return &nrp->next; 787 } 788 789 /* 790 * lookup a resource record of a particular type and 791 * class attached to a domain name. Return copies. 792 * 793 * Priority ordering is: 794 * db authoritative 795 * not timed out network authoritative 796 * not timed out network unauthoritative 797 * unauthoritative db 798 * 799 * if flag NOneg is set, don't return negative cached entries. 800 * return nothing instead. 801 */ 802 RR* 803 rrlookup(DN *dp, int type, int flag) 804 { 805 RR *rp, *first, **last; 806 807 assert(dp->magic == DNmagic); 808 809 first = 0; 810 last = &first; 811 lock(&dnlock); 812 813 /* try for an authoritative db entry */ 814 for(rp = dp->rr; rp; rp = rp->next){ 815 assert(rp->magic == RRmagic && rp->cached); 816 if(rp->db) 817 if(rp->auth) 818 if(tsame(type, rp->type)) 819 last = rrcopy(rp, last); 820 } 821 if(first) 822 goto out; 823 824 /* try for an living authoritative network entry */ 825 for(rp = dp->rr; rp; rp = rp->next){ 826 if(!rp->db) 827 if(rp->auth) 828 if(rp->ttl + 60 > now) 829 if(tsame(type, rp->type)){ 830 if(flag == NOneg && rp->negative) 831 goto out; 832 last = rrcopy(rp, last); 833 } 834 } 835 if(first) 836 goto out; 837 838 /* try for an living unauthoritative network entry */ 839 for(rp = dp->rr; rp; rp = rp->next){ 840 if(!rp->db) 841 if(rp->ttl + 60 > now) 842 if(tsame(type, rp->type)){ 843 if(flag == NOneg && rp->negative) 844 goto out; 845 last = rrcopy(rp, last); 846 } 847 } 848 if(first) 849 goto out; 850 851 /* try for an unauthoritative db entry */ 852 for(rp = dp->rr; rp; rp = rp->next){ 853 if(rp->db) 854 if(tsame(type, rp->type)) 855 last = rrcopy(rp, last); 856 } 857 if(first) 858 goto out; 859 860 /* otherwise, settle for anything we got (except for negative caches) */ 861 for(rp = dp->rr; rp; rp = rp->next){ 862 if(tsame(type, rp->type)){ 863 if(rp->negative) 864 goto out; 865 last = rrcopy(rp, last); 866 } 867 } 868 869 out: 870 unlock(&dnlock); 871 unique(first); 872 return first; 873 } 874 875 /* 876 * convert an ascii RR type name to its integer representation 877 */ 878 int 879 rrtype(char *atype) 880 { 881 int i; 882 883 for(i = 0; i <= Tall; i++) 884 if(rrtname[i] && strcmp(rrtname[i], atype) == 0) 885 return i; 886 887 /* make any a synonym for all */ 888 if(strcmp(atype, "any") == 0) 889 return Tall; 890 return atoi(atype); 891 } 892 893 /* 894 * convert an integer RR type to it's ascii name 895 */ 896 char* 897 rrname(int type, char *buf, int len) 898 { 899 char *t; 900 901 t = 0; 902 if(type <= Tall) 903 t = rrtname[type]; 904 if(t==0){ 905 snprint(buf, len, "%d", type); 906 t = buf; 907 } 908 return t; 909 } 910 911 /* 912 * return 0 if not a supported rr type 913 */ 914 int 915 rrsupported(int type) 916 { 917 if(type < 0 || type >Tall) 918 return 0; 919 return rrtname[type] != 0; 920 } 921 922 /* 923 * compare 2 types 924 */ 925 int 926 tsame(int t1, int t2) 927 { 928 return t1 == t2 || t1 == Tall; 929 } 930 931 /* 932 * Add resource records to a list, duplicate them if they are cached 933 * RR's since these are shared. 934 */ 935 RR* 936 rrcat(RR **start, RR *rp) 937 { 938 RR **last; 939 940 last = start; 941 while(*last != 0) 942 last = &(*last)->next; 943 944 *last = rp; 945 return *start; 946 } 947 948 /* 949 * remove negative cache rr's from an rr list 950 */ 951 RR* 952 rrremneg(RR **l) 953 { 954 RR **nl, *rp; 955 RR *first; 956 957 first = nil; 958 nl = &first; 959 while(*l != nil){ 960 rp = *l; 961 if(rp->negative){ 962 *l = rp->next; 963 *nl = rp; 964 nl = &rp->next; 965 *nl = nil; 966 } else 967 l = &rp->next; 968 } 969 970 return first; 971 } 972 973 /* 974 * remove rr's of a particular type from an rr list 975 */ 976 RR* 977 rrremtype(RR **l, int type) 978 { 979 RR **nl, *rp; 980 RR *first; 981 982 first = nil; 983 nl = &first; 984 while(*l != nil){ 985 rp = *l; 986 if(rp->type == type){ 987 *l = rp->next; 988 *nl = rp; 989 nl = &rp->next; 990 *nl = nil; 991 } else 992 l = &(*l)->next; 993 } 994 995 return first; 996 } 997 998 /* 999 * print conversion for rr records 1000 */ 1001 int 1002 rrfmt(Fmt *f) 1003 { 1004 RR *rp; 1005 char *strp; 1006 Fmt fstr; 1007 int rv; 1008 char buf[Domlen]; 1009 Server *s; 1010 Txt *t; 1011 1012 fmtstrinit(&fstr); 1013 1014 rp = va_arg(f->args, RR*); 1015 if(rp == 0){ 1016 fmtprint(&fstr, "<null>"); 1017 goto out; 1018 } 1019 1020 fmtprint(&fstr, "%s %s", rp->owner->name, 1021 rrname(rp->type, buf, sizeof buf)); 1022 1023 if(rp->negative){ 1024 fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode); 1025 goto out; 1026 } 1027 1028 switch(rp->type){ 1029 case Thinfo: 1030 fmtprint(&fstr, "\t%s %s", rp->cpu->name, rp->os->name); 1031 break; 1032 case Tcname: 1033 case Tmb: 1034 case Tmd: 1035 case Tmf: 1036 case Tns: 1037 fmtprint(&fstr, "\t%s", rp->host->name); 1038 break; 1039 case Tmg: 1040 case Tmr: 1041 fmtprint(&fstr, "\t%s", rp->mb->name); 1042 break; 1043 case Tminfo: 1044 fmtprint(&fstr, "\t%s %s", rp->mb->name, rp->rmb->name); 1045 break; 1046 case Tmx: 1047 fmtprint(&fstr, "\t%lud %s", rp->pref, rp->host->name); 1048 break; 1049 case Ta: 1050 case Taaaa: 1051 fmtprint(&fstr, "\t%s", rp->ip->name); 1052 break; 1053 case Tptr: 1054 /* fmtprint(&fstr, "\t%s(%lud)", rp->ptr->name, rp->ptr->ordinal); */ 1055 fmtprint(&fstr, "\t%s", rp->ptr->name); 1056 break; 1057 case Tsoa: 1058 fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name, 1059 rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry, 1060 rp->soa->expire, rp->soa->minttl); 1061 for(s = rp->soa->slaves; s != nil; s = s->next) 1062 fmtprint(&fstr, " %s", s->name); 1063 break; 1064 case Tnull: 1065 fmtprint(&fstr, "\t%.*H", rp->null->dlen, rp->null->data); 1066 break; 1067 case Ttxt: 1068 fmtprint(&fstr, "\t"); 1069 for(t = rp->txt; t != nil; t = t->next) 1070 fmtprint(&fstr, "%s", t->p); 1071 break; 1072 case Trp: 1073 fmtprint(&fstr, "\t%s %s", rp->rmb->name, rp->rp->name); 1074 break; 1075 case Tkey: 1076 fmtprint(&fstr, "\t%d %d %d", rp->key->flags, rp->key->proto, 1077 rp->key->alg); 1078 break; 1079 case Tsig: 1080 fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s", 1081 rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl, 1082 rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name); 1083 break; 1084 case Tcert: 1085 fmtprint(&fstr, "\t%d %d %d", 1086 rp->sig->type, rp->sig->tag, rp->sig->alg); 1087 break; 1088 default: 1089 break; 1090 } 1091 out: 1092 strp = fmtstrflush(&fstr); 1093 rv = fmtstrcpy(f, strp); 1094 free(strp); 1095 return rv; 1096 } 1097 1098 /* 1099 * print conversion for rr records in attribute value form 1100 */ 1101 int 1102 rravfmt(Fmt *f) 1103 { 1104 RR *rp; 1105 char *strp; 1106 Fmt fstr; 1107 int rv; 1108 Server *s; 1109 Txt *t; 1110 int quote; 1111 1112 fmtstrinit(&fstr); 1113 1114 rp = va_arg(f->args, RR*); 1115 if(rp == 0){ 1116 fmtprint(&fstr, "<null>"); 1117 goto out; 1118 } 1119 1120 if(rp->type == Tptr) 1121 fmtprint(&fstr, "ptr=%s", rp->owner->name); 1122 else 1123 fmtprint(&fstr, "dom=%s", rp->owner->name); 1124 1125 switch(rp->type){ 1126 case Thinfo: 1127 fmtprint(&fstr, " cpu=%s os=%s", rp->cpu->name, rp->os->name); 1128 break; 1129 case Tcname: 1130 fmtprint(&fstr, " cname=%s", rp->host->name); 1131 break; 1132 case Tmb: 1133 case Tmd: 1134 case Tmf: 1135 fmtprint(&fstr, " mbox=%s", rp->host->name); 1136 break; 1137 case Tns: 1138 fmtprint(&fstr, " ns=%s", rp->host->name); 1139 break; 1140 case Tmg: 1141 case Tmr: 1142 fmtprint(&fstr, " mbox=%s", rp->mb->name); 1143 break; 1144 case Tminfo: 1145 fmtprint(&fstr, " mbox=%s mbox=%s", rp->mb->name, rp->rmb->name); 1146 break; 1147 case Tmx: 1148 fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, rp->host->name); 1149 break; 1150 case Ta: 1151 case Taaaa: 1152 fmtprint(&fstr, " ip=%s", rp->ip->name); 1153 break; 1154 case Tptr: 1155 fmtprint(&fstr, " dom=%s", rp->ptr->name); 1156 break; 1157 case Tsoa: 1158 fmtprint(&fstr, " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud", 1159 rp->host->name, rp->rmb->name, rp->soa->serial, 1160 rp->soa->refresh, rp->soa->retry, 1161 rp->soa->expire, rp->soa->minttl); 1162 for(s = rp->soa->slaves; s != nil; s = s->next) 1163 fmtprint(&fstr, " dnsslave=%s", s->name); 1164 break; 1165 case Tnull: 1166 fmtprint(&fstr, " null=%.*H", rp->null->dlen, rp->null->data); 1167 break; 1168 case Ttxt: 1169 fmtprint(&fstr, " txt="); 1170 quote = 0; 1171 for(t = rp->txt; t != nil; t = t->next) 1172 if(strchr(t->p, ' ')) 1173 quote = 1; 1174 if(quote) 1175 fmtprint(&fstr, "\""); 1176 for(t = rp->txt; t != nil; t = t->next) 1177 fmtprint(&fstr, "%s", t->p); 1178 if(quote) 1179 fmtprint(&fstr, "\""); 1180 break; 1181 case Trp: 1182 fmtprint(&fstr, " rp=%s txt=%s", rp->rmb->name, rp->rp->name); 1183 break; 1184 case Tkey: 1185 fmtprint(&fstr, " flags=%d proto=%d alg=%d", 1186 rp->key->flags, rp->key->proto, rp->key->alg); 1187 break; 1188 case Tsig: 1189 fmtprint(&fstr, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s", 1190 rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl, 1191 rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name); 1192 break; 1193 case Tcert: 1194 fmtprint(&fstr, " type=%d tag=%d alg=%d", 1195 rp->sig->type, rp->sig->tag, rp->sig->alg); 1196 break; 1197 default: 1198 break; 1199 } 1200 out: 1201 strp = fmtstrflush(&fstr); 1202 rv = fmtstrcpy(f, strp); 1203 free(strp); 1204 return rv; 1205 } 1206 1207 void 1208 warning(char *fmt, ...) 1209 { 1210 char dnserr[128]; 1211 va_list arg; 1212 1213 va_start(arg, fmt); 1214 vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg); 1215 va_end(arg); 1216 syslog(1, "dns", dnserr); 1217 } 1218 1219 /* 1220 * chasing down double free's 1221 */ 1222 void 1223 dncheck(void *p, int dolock) 1224 { 1225 DN *dp; 1226 int i; 1227 RR *rp; 1228 1229 if(p != nil){ 1230 dp = p; 1231 assert(dp->magic == DNmagic); 1232 } 1233 1234 if(!testing) 1235 return; 1236 1237 if(dolock) 1238 lock(&dnlock); 1239 for(i = 0; i < HTLEN; i++) 1240 for(dp = ht[i]; dp; dp = dp->next){ 1241 assert(dp != p); 1242 assert(dp->magic == DNmagic); 1243 for(rp = dp->rr; rp; rp = rp->next){ 1244 assert(rp->magic == RRmagic); 1245 assert(rp->cached); 1246 assert(rp->owner == dp); 1247 } 1248 } 1249 if(dolock) 1250 unlock(&dnlock); 1251 } 1252 1253 static int 1254 rrequiv(RR *r1, RR *r2) 1255 { 1256 return r1->owner == r2->owner 1257 && r1->type == r2->type 1258 && r1->arg0 == r2->arg0 1259 && r1->arg1 == r2->arg1; 1260 } 1261 1262 void 1263 unique(RR *rp) 1264 { 1265 RR **l, *nrp; 1266 1267 for(; rp; rp = rp->next){ 1268 l = &rp->next; 1269 for(nrp = *l; nrp; nrp = *l){ 1270 if(rrequiv(rp, nrp)){ 1271 *l = nrp->next; 1272 rrfree(nrp); 1273 } else 1274 l = &nrp->next; 1275 } 1276 } 1277 } 1278 1279 /* 1280 * true if second domain is subsumed by the first 1281 */ 1282 int 1283 subsume(char *higher, char *lower) 1284 { 1285 int hn, ln; 1286 1287 ln = strlen(lower); 1288 hn = strlen(higher); 1289 if(ln < hn) 1290 return 0; 1291 1292 if(cistrcmp(lower + ln - hn, higher) != 0) 1293 return 0; 1294 1295 if(ln > hn && hn != 0 && lower[ln - hn - 1] != '.') 1296 return 0; 1297 1298 return 1; 1299 } 1300 1301 /* 1302 * randomize the order we return items to provide some 1303 * load balancing for servers. 1304 * 1305 * only randomize the first class of entries 1306 */ 1307 RR* 1308 randomize(RR *rp) 1309 { 1310 RR *first, *last, *x, *base; 1311 ulong n; 1312 1313 if(rp == nil || rp->next == nil) 1314 return rp; 1315 1316 /* just randomize addresses and mx's */ 1317 for(x = rp; x; x = x->next) 1318 if(x->type != Ta && x->type != Tmx && x->type != Tns) 1319 return rp; 1320 1321 base = rp; 1322 1323 n = rand(); 1324 last = first = nil; 1325 while(rp != nil){ 1326 /* stop randomizing if we've moved past our class */ 1327 if(base->auth != rp->auth || base->db != rp->db){ 1328 last->next = rp; 1329 break; 1330 } 1331 1332 /* unchain */ 1333 x = rp; 1334 rp = x->next; 1335 x->next = nil; 1336 1337 if(n&1){ 1338 /* add to tail */ 1339 if(last == nil) 1340 first = x; 1341 else 1342 last->next = x; 1343 last = x; 1344 } else { 1345 /* add to head */ 1346 if(last == nil) 1347 last = x; 1348 x->next = first; 1349 first = x; 1350 } 1351 1352 /* reroll the dice */ 1353 n >>= 1; 1354 } 1355 return first; 1356 } 1357 1358 static int 1359 sencodefmt(Fmt *f) 1360 { 1361 char *out; 1362 char *buf; 1363 int i, len; 1364 int ilen; 1365 int rv; 1366 uchar *b; 1367 char obuf[64]; /* rsc optimization */ 1368 1369 if(!(f->flags&FmtPrec) || f->prec < 1) 1370 goto error; 1371 1372 b = va_arg(f->args, uchar*); 1373 if(b == nil) 1374 goto error; 1375 1376 /* if it's a printable, go for it */ 1377 len = f->prec; 1378 for(i = 0; i < len; i++) 1379 if(!isprint(b[i])) 1380 break; 1381 if(i == len){ 1382 if(len >= sizeof obuf) 1383 len = sizeof(obuf)-1; 1384 memmove(obuf, b, len); 1385 obuf[len] = 0; 1386 fmtstrcpy(f, obuf); 1387 return 0; 1388 } 1389 1390 ilen = f->prec; 1391 f->prec = 0; 1392 f->flags &= ~FmtPrec; 1393 switch(f->r){ 1394 case '<': 1395 len = (8*ilen+4)/5 + 3; 1396 break; 1397 case '[': 1398 len = (8*ilen+5)/6 + 4; 1399 break; 1400 case 'H': 1401 len = 2*ilen + 1; 1402 break; 1403 default: 1404 goto error; 1405 } 1406 1407 if(len > sizeof(obuf)){ 1408 buf = malloc(len); 1409 if(buf == nil) 1410 goto error; 1411 } else 1412 buf = obuf; 1413 1414 /* convert */ 1415 out = buf; 1416 switch(f->r){ 1417 case '<': 1418 rv = enc32(out, len, b, ilen); 1419 break; 1420 case '[': 1421 rv = enc64(out, len, b, ilen); 1422 break; 1423 case 'H': 1424 rv = enc16(out, len, b, ilen); 1425 break; 1426 default: 1427 rv = -1; 1428 break; 1429 } 1430 if(rv < 0) 1431 goto error; 1432 1433 fmtstrcpy(f, buf); 1434 if(buf != obuf) 1435 free(buf); 1436 return 0; 1437 1438 error: 1439 return fmtstrcpy(f, "<encodefmt>"); 1440 1441 } 1442 1443 void* 1444 emalloc(int size) 1445 { 1446 char *x; 1447 1448 x = mallocz(size, 1); 1449 if(x == nil) 1450 abort(); 1451 setmalloctag(x, getcallerpc(&size)); 1452 return x; 1453 } 1454 1455 char* 1456 estrdup(char *s) 1457 { 1458 int size; 1459 char *p; 1460 1461 size = strlen(s)+1; 1462 p = mallocz(size, 0); 1463 if(p == nil) 1464 abort(); 1465 memmove(p, s, size); 1466 setmalloctag(p, getcallerpc(&s)); 1467 return p; 1468 } 1469 1470 /* 1471 * create a pointer record 1472 */ 1473 static RR* 1474 mkptr(DN *dp, char *ptr, ulong ttl) 1475 { 1476 DN *ipdp; 1477 RR *rp; 1478 1479 ipdp = dnlookup(ptr, Cin, 1); 1480 1481 rp = rralloc(Tptr); 1482 rp->ptr = dp; 1483 rp->owner = ipdp; 1484 rp->db = 1; 1485 if(ttl) 1486 rp->ttl = ttl; 1487 return rp; 1488 } 1489 1490 /* 1491 * look for all ip addresses in this network and make 1492 * pointer records for them. 1493 */ 1494 void 1495 dnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl) 1496 { 1497 int i, j; 1498 DN *dp; 1499 RR *rp, *nrp, *first, **l; 1500 uchar ip[IPaddrlen]; 1501 uchar nnet[IPaddrlen]; 1502 char ptr[Domlen]; 1503 char *p, *e; 1504 1505 l = &first; 1506 first = nil; 1507 for(i = 0; i < HTLEN; i++){ 1508 for(dp = ht[i]; dp; dp = dp->next){ 1509 for(rp = dp->rr; rp; rp = rp->next){ 1510 if(rp->type != Ta || rp->negative) 1511 continue; 1512 parseip(ip, rp->ip->name); 1513 maskip(ip, mask, nnet); 1514 if(ipcmp(net, nnet) != 0) 1515 continue; 1516 p = ptr; 1517 e = ptr+sizeof(ptr); 1518 for(j = IPaddrlen-1; j >= IPaddrlen-bytes; j--) 1519 p = seprint(p, e, "%d.", ip[j]); 1520 seprint(p, e, "%s", dom); 1521 nrp = mkptr(dp, ptr, ttl); 1522 *l = nrp; 1523 l = &nrp->next; 1524 } 1525 } 1526 } 1527 1528 for(rp = first; rp != nil; rp = nrp){ 1529 nrp = rp->next; 1530 rp->next = nil; 1531 rrattach(rp, 1); 1532 } 1533 } 1534 1535 void 1536 freeserverlist(Server *s) 1537 { 1538 Server *next; 1539 1540 for(; s != nil; s = next){ 1541 next = s->next; 1542 free(s); 1543 } 1544 } 1545 1546 void 1547 addserver(Server **l, char *name) 1548 { 1549 Server *s; 1550 1551 while(*l) 1552 l = &(*l)->next; 1553 s = malloc(sizeof(Server)+strlen(name)+1); 1554 if(s == nil) 1555 return; 1556 s->name = (char*)(s+1); 1557 strcpy(s->name, name); 1558 s->next = nil; 1559 *l = s; 1560 } 1561 1562 Server* 1563 copyserverlist(Server *s) 1564 { 1565 Server *ns; 1566 1567 1568 for(ns = nil; s != nil; s = s->next) 1569 addserver(&ns, s->name); 1570 return ns; 1571 }