dblookup.c (18040B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <ndb.h> 5 #include <ip.h> 6 #include "dns.h" 7 8 static Ndb *db; 9 10 static RR* dblookup1(char*, int, int, int); 11 static RR* addrrr(Ndbtuple*, Ndbtuple*); 12 static RR* nsrr(Ndbtuple*, Ndbtuple*); 13 static RR* cnamerr(Ndbtuple*, Ndbtuple*); 14 static RR* mxrr(Ndbtuple*, Ndbtuple*); 15 static RR* soarr(Ndbtuple*, Ndbtuple*); 16 static RR* ptrrr(Ndbtuple*, Ndbtuple*); 17 static Ndbtuple* look(Ndbtuple*, Ndbtuple*, char*); 18 static RR* doaxfr(Ndb*, char*); 19 static RR* nullrr(Ndbtuple *entry, Ndbtuple *pair); 20 static RR* txtrr(Ndbtuple *entry, Ndbtuple *pair); 21 static Lock dblock; 22 static void createptrs(void); 23 24 static int implemented[Tall] = 25 { 26 0, 27 /* Ta */ 1, 28 /* Tns */ 1, 29 0, 30 0, 31 /* Tcname */ 1, 32 /* Tsoa */ 1, 33 0, 34 0, 35 0, 36 /* Tnull */ 1, 37 0, 38 /* Tptr */ 1, 39 0, 40 0, 41 /* Tmx */ 1, 42 /* Ttxt */ 1 43 }; 44 45 static void 46 nstrcpy(char *to, char *from, int len) 47 { 48 strncpy(to, from, len); 49 to[len-1] = 0; 50 } 51 52 int 53 opendatabase(void) 54 { 55 char buf[256]; 56 Ndb *xdb; 57 58 if(db == nil){ 59 snprint(buf, sizeof(buf), "%s/ndb", mntpt); 60 xdb = ndbopen(dbfile); 61 if(xdb != nil) 62 xdb->nohash = 1; 63 db = ndbcat(ndbopen(buf), xdb); 64 } 65 if(db == nil) 66 return -1; 67 else 68 return 0; 69 } 70 71 /* 72 * lookup an RR in the network database, look for matches 73 * against both the domain name and the wildcarded domain name. 74 * 75 * the lock makes sure only one process can be accessing the data 76 * base at a time. This is important since there's a lot of 77 * shared state there. 78 * 79 * e.g. for x.research.bell-labs.com, first look for a match against 80 * the x.research.bell-labs.com. If nothing matches, try *.research.bell-labs.com. 81 */ 82 RR* 83 dblookup(char *name, int class, int type, int auth, int ttl) 84 { 85 RR *rp, *tp; 86 char buf[256]; 87 char *wild, *cp; 88 DN *dp, *ndp; 89 int err; 90 91 /* so far only internet lookups are implemented */ 92 if(class != Cin) 93 return 0; 94 95 err = Rname; 96 97 if(type == Tall){ 98 rp = 0; 99 for (type = Ta; type < Tall; type++) 100 if(implemented[type]) 101 rrcat(&rp, dblookup(name, class, type, auth, ttl)); 102 return rp; 103 } 104 105 lock(&dblock); 106 rp = nil; 107 dp = dnlookup(name, class, 1); 108 if(opendatabase() < 0) 109 goto out; 110 if(dp->rr) 111 err = 0; 112 113 /* first try the given name */ 114 rp = 0; 115 if(cachedb) 116 rp = rrlookup(dp, type, NOneg); 117 else 118 rp = dblookup1(name, type, auth, ttl); 119 if(rp) 120 goto out; 121 122 /* try lower case version */ 123 for(cp = name; *cp; cp++) 124 *cp = tolower((uchar)*cp); 125 if(cachedb) 126 rp = rrlookup(dp, type, NOneg); 127 else 128 rp = dblookup1(name, type, auth, ttl); 129 if(rp) 130 goto out; 131 132 /* walk the domain name trying the wildcard '*' at each position */ 133 for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){ 134 snprint(buf, sizeof(buf), "*%s", wild); 135 ndp = dnlookup(buf, class, 1); 136 if(ndp->rr) 137 err = 0; 138 if(cachedb) 139 rp = rrlookup(ndp, type, NOneg); 140 else 141 rp = dblookup1(buf, type, auth, ttl); 142 if(rp) 143 break; 144 } 145 out: 146 /* add owner to uncached records */ 147 if(rp){ 148 for(tp = rp; tp; tp = tp->next) 149 tp->owner = dp; 150 } else { 151 /* don't call it non-existent if it's not ours */ 152 if(err == Rname && !inmyarea(name)) 153 err = Rserver; 154 dp->nonexistent = err; 155 } 156 157 unlock(&dblock); 158 return rp; 159 } 160 161 /* 162 * lookup an RR in the network database 163 */ 164 static RR* 165 dblookup1(char *name, int type, int auth, int ttl) 166 { 167 Ndbtuple *t, *nt; 168 RR *rp, *list, **l; 169 Ndbs s; 170 char dname[Domlen]; 171 char *attr; 172 DN *dp; 173 RR *(*f)(Ndbtuple*, Ndbtuple*); 174 int found, x; 175 176 dp = 0; 177 switch(type){ 178 case Tptr: 179 attr = "ptr"; 180 f = ptrrr; 181 break; 182 case Ta: 183 attr = "ip"; 184 f = addrrr; 185 break; 186 case Tnull: 187 attr = "nullrr"; 188 f = nullrr; 189 break; 190 case Tns: 191 attr = "ns"; 192 f = nsrr; 193 break; 194 case Tsoa: 195 attr = "soa"; 196 f = soarr; 197 break; 198 case Tmx: 199 attr = "mx"; 200 f = mxrr; 201 break; 202 case Tcname: 203 attr = "cname"; 204 f = cnamerr; 205 break; 206 case Taxfr: 207 case Tixfr: 208 return doaxfr(db, name); 209 default: 210 return nil; 211 } 212 213 /* 214 * find a matching entry in the database 215 */ 216 free(ndbgetvalue(db, &s, "dom", name, attr, &t)); 217 218 /* 219 * hack for local names 220 */ 221 if(t == 0 && strchr(name, '.') == 0) 222 free(ndbgetvalue(db, &s, "sys", name, attr, &t)); 223 if(t == 0) 224 return nil; 225 226 /* search whole entry for default domain name */ 227 strncpy(dname, name, sizeof dname); 228 for(nt = t; nt; nt = nt->entry) 229 if(strcmp(nt->attr, "dom") == 0){ 230 nstrcpy(dname, nt->val, sizeof dname); 231 break; 232 } 233 234 /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */ 235 nt = look(t, s.t, "ttl"); 236 if(nt){ 237 x = atoi(nt->val); 238 if(x > ttl) 239 ttl = x; 240 } 241 242 /* default ttl is one day */ 243 if(ttl < 0) 244 ttl = DEFTTL; 245 246 /* 247 * The database has 2 levels of precedence; line and entry. 248 * Pairs on the same line bind tighter than pairs in the 249 * same entry, so we search the line first. 250 */ 251 found = 0; 252 list = 0; 253 l = &list; 254 for(nt = s.t;; ){ 255 if(found == 0 && strcmp(nt->attr, "dom") == 0){ 256 nstrcpy(dname, nt->val, sizeof dname); 257 found = 1; 258 } 259 if(cistrcmp(attr, nt->attr) == 0){ 260 rp = (*f)(t, nt); 261 rp->auth = auth; 262 rp->db = 1; 263 if(ttl) 264 rp->ttl = ttl; 265 if(dp == 0) 266 dp = dnlookup(dname, Cin, 1); 267 rp->owner = dp; 268 *l = rp; 269 l = &rp->next; 270 nt->ptr = 1; 271 } 272 nt = nt->line; 273 if(nt == s.t) 274 break; 275 } 276 277 /* search whole entry */ 278 for(nt = t; nt; nt = nt->entry) 279 if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){ 280 rp = (*f)(t, nt); 281 rp->db = 1; 282 if(ttl) 283 rp->ttl = ttl; 284 rp->auth = auth; 285 if(dp == 0) 286 dp = dnlookup(dname, Cin, 1); 287 rp->owner = dp; 288 *l = rp; 289 l = &rp->next; 290 } 291 ndbfree(t); 292 293 return list; 294 } 295 296 /* 297 * make various types of resource records from a database entry 298 */ 299 static RR* 300 addrrr(Ndbtuple *entry, Ndbtuple *pair) 301 { 302 RR *rp; 303 uchar addr[IPaddrlen]; 304 305 USED(entry); 306 parseip(addr, pair->val); 307 if(isv4(addr)) 308 rp = rralloc(Ta); 309 else 310 rp = rralloc(Taaaa); 311 rp->ip = dnlookup(pair->val, Cin, 1); 312 return rp; 313 } 314 static RR* 315 nullrr(Ndbtuple *entry, Ndbtuple *pair) 316 { 317 RR *rp; 318 319 USED(entry); 320 rp = rralloc(Tnull); 321 rp->null->data = (uchar*)estrdup(pair->val); 322 rp->null->dlen = strlen((char*)rp->null->data); 323 return rp; 324 } 325 /* 326 * txt rr strings are at most 255 bytes long. one 327 * can represent longer strings by multiple concatenated 328 * <= 255 byte ones. 329 */ 330 static RR* 331 txtrr(Ndbtuple *entry, Ndbtuple *pair) 332 { 333 RR *rp; 334 Txt *t, **l; 335 int i, len, sofar; 336 337 USED(entry); 338 rp = rralloc(Ttxt); 339 l = &rp->txt; 340 rp->txt = nil; 341 len = strlen(pair->val); 342 sofar = 0; 343 while(len > sofar){ 344 t = emalloc(sizeof(*t)); 345 t->next = nil; 346 347 i = len-sofar; 348 if(i > 255) 349 i = 255; 350 351 t->p = emalloc(i+1); 352 memmove(t->p, pair->val+sofar, i); 353 t->p[i] = 0; 354 sofar += i; 355 356 *l = t; 357 l = &t->next; 358 } 359 return rp; 360 } 361 static RR* 362 cnamerr(Ndbtuple *entry, Ndbtuple *pair) 363 { 364 RR *rp; 365 366 USED(entry); 367 rp = rralloc(Tcname); 368 rp->host = dnlookup(pair->val, Cin, 1); 369 return rp; 370 } 371 static RR* 372 mxrr(Ndbtuple *entry, Ndbtuple *pair) 373 { 374 RR * rp; 375 376 rp = rralloc(Tmx); 377 rp->host = dnlookup(pair->val, Cin, 1); 378 pair = look(entry, pair, "pref"); 379 if(pair) 380 rp->pref = atoi(pair->val); 381 else 382 rp->pref = 1; 383 return rp; 384 } 385 static RR* 386 nsrr(Ndbtuple *entry, Ndbtuple *pair) 387 { 388 RR *rp; 389 Ndbtuple *t; 390 391 rp = rralloc(Tns); 392 rp->host = dnlookup(pair->val, Cin, 1); 393 t = look(entry, pair, "soa"); 394 if(t && t->val[0] == 0) 395 rp->local = 1; 396 return rp; 397 } 398 static RR* 399 ptrrr(Ndbtuple *entry, Ndbtuple *pair) 400 { 401 RR *rp; 402 403 USED(entry); 404 rp = rralloc(Tns); 405 rp->ptr = dnlookup(pair->val, Cin, 1); 406 return rp; 407 } 408 static RR* 409 soarr(Ndbtuple *entry, Ndbtuple *pair) 410 { 411 RR *rp; 412 Ndbtuple *ns, *mb, *t; 413 char mailbox[Domlen]; 414 Ndb *ndb; 415 char *p; 416 417 rp = rralloc(Tsoa); 418 rp->soa->serial = 1; 419 for(ndb = db; ndb; ndb = ndb->next) 420 if(ndb->mtime > rp->soa->serial) 421 rp->soa->serial = ndb->mtime; 422 rp->soa->refresh = Day; 423 rp->soa->retry = Hour; 424 rp->soa->expire = Day; 425 rp->soa->minttl = Day; 426 t = look(entry, pair, "ttl"); 427 if(t) 428 rp->soa->minttl = atoi(t->val); 429 t = look(entry, pair, "refresh"); 430 if(t) 431 rp->soa->refresh = atoi(t->val); 432 t = look(entry, pair, "serial"); 433 if(t) 434 rp->soa->serial = strtoul(t->val, 0, 10); 435 436 ns = look(entry, pair, "ns"); 437 if(ns == 0) 438 ns = look(entry, pair, "dom"); 439 rp->host = dnlookup(ns->val, Cin, 1); 440 441 /* accept all of: 442 * mbox=person 443 * mbox=person@machine.dom 444 * mbox=person.machine.dom 445 */ 446 mb = look(entry, pair, "mbox"); 447 if(mb == nil) 448 mb = look(entry, pair, "mb"); 449 if(mb){ 450 if(strchr(mb->val, '.')) { 451 p = strchr(mb->val, '@'); 452 if(p != nil) 453 *p = '.'; 454 rp->rmb = dnlookup(mb->val, Cin, 1); 455 } else { 456 snprint(mailbox, sizeof(mailbox), "%s.%s", 457 mb->val, ns->val); 458 rp->rmb = dnlookup(mailbox, Cin, 1); 459 } 460 } else { 461 snprint(mailbox, sizeof(mailbox), "postmaster.%s", 462 ns->val); 463 rp->rmb = dnlookup(mailbox, Cin, 1); 464 } 465 466 /* hang dns slaves off of the soa. this is 467 * for managing the area. 468 */ 469 for(t = entry; t != nil; t = t->entry) 470 if(strcmp(t->attr, "dnsslave") == 0) 471 addserver(&rp->soa->slaves, t->val); 472 473 return rp; 474 } 475 476 /* 477 * Look for a pair with the given attribute. look first on the same line, 478 * then in the whole entry. 479 */ 480 static Ndbtuple* 481 look(Ndbtuple *entry, Ndbtuple *line, char *attr) 482 { 483 Ndbtuple *nt; 484 485 /* first look on same line (closer binding) */ 486 for(nt = line;;){ 487 if(cistrcmp(attr, nt->attr) == 0) 488 return nt; 489 nt = nt->line; 490 if(nt == line) 491 break; 492 } 493 /* search whole tuple */ 494 for(nt = entry; nt; nt = nt->entry) 495 if(cistrcmp(attr, nt->attr) == 0) 496 return nt; 497 return 0; 498 } 499 500 /* these are answered specially by the tcp version */ 501 static RR* 502 doaxfr(Ndb *db, char *name) 503 { 504 USED(db); 505 USED(name); 506 return 0; 507 } 508 509 510 /* 511 * read the all the soa's from the database to determine area's. 512 * this is only used when we're not caching the database. 513 */ 514 static void 515 dbfile2area(Ndb *db) 516 { 517 Ndbtuple *t; 518 519 if(debug) 520 syslog(0, logfile, "rereading %s", db->file); 521 Bseek(&db->b, 0, 0); 522 while(t = ndbparse(db)){ 523 ndbfree(t); 524 } 525 } 526 527 /* 528 * read the database into the cache 529 */ 530 static void 531 dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair) 532 { 533 RR *rp; 534 Ndbtuple *t; 535 static ulong ord; 536 537 rp = 0; 538 if(cistrcmp(pair->attr, "ip") == 0){ 539 dp->ordinal = ord++; 540 rp = addrrr(entry, pair); 541 } else if(cistrcmp(pair->attr, "ns") == 0){ 542 rp = nsrr(entry, pair); 543 } else if(cistrcmp(pair->attr, "soa") == 0){ 544 rp = soarr(entry, pair); 545 addarea(dp, rp, pair); 546 } else if(cistrcmp(pair->attr, "mx") == 0){ 547 rp = mxrr(entry, pair); 548 } else if(cistrcmp(pair->attr, "cname") == 0){ 549 rp = cnamerr(entry, pair); 550 } else if(cistrcmp(pair->attr, "nullrr") == 0){ 551 rp = nullrr(entry, pair); 552 } else if(cistrcmp(pair->attr, "txtrr") == 0){ 553 rp = txtrr(entry, pair); 554 } 555 556 if(rp == 0) 557 return; 558 559 rp->owner = dp; 560 rp->db = 1; 561 t = look(entry, pair, "ttl"); 562 if(t) 563 rp->ttl = atoi(t->val); 564 rrattach(rp, 0); 565 } 566 static void 567 dbtuple2cache(Ndbtuple *t) 568 { 569 Ndbtuple *et, *nt; 570 DN *dp; 571 572 for(et = t; et; et = et->entry){ 573 if(strcmp(et->attr, "dom") == 0){ 574 dp = dnlookup(et->val, Cin, 1); 575 576 /* first same line */ 577 for(nt = et->line; nt != et; nt = nt->line){ 578 dbpair2cache(dp, t, nt); 579 nt->ptr = 1; 580 } 581 582 /* then rest of entry */ 583 for(nt = t; nt; nt = nt->entry){ 584 if(nt->ptr == 0) 585 dbpair2cache(dp, t, nt); 586 nt->ptr = 0; 587 } 588 } 589 } 590 } 591 static void 592 dbfile2cache(Ndb *db) 593 { 594 Ndbtuple *t; 595 596 if(debug) 597 syslog(0, logfile, "rereading %s", db->file); 598 Bseek(&db->b, 0, 0); 599 while(t = ndbparse(db)){ 600 dbtuple2cache(t); 601 ndbfree(t); 602 } 603 } 604 void 605 db2cache(int doit) 606 { 607 Ndb *ndb; 608 Dir *d; 609 ulong youngest, temp; 610 static ulong lastcheck; 611 static ulong lastyoungest; 612 613 /* no faster than once every 2 minutes */ 614 if(now < lastcheck + 2*Min && !doit) 615 return; 616 617 refresh_areas(owned); 618 619 lock(&dblock); 620 621 if(opendatabase() < 0){ 622 unlock(&dblock); 623 return; 624 } 625 626 /* 627 * file may be changing as we are reading it, so loop till 628 * mod times are consistent. 629 * 630 * we don't use the times in the ndb records because they may 631 * change outside of refreshing our cached knowledge. 632 */ 633 for(;;){ 634 lastcheck = now; 635 youngest = 0; 636 for(ndb = db; ndb; ndb = ndb->next){ 637 /* the dirfstat avoids walking the mount table each time */ 638 if((d = dirfstat(Bfildes(&ndb->b))) != nil || 639 (d = dirstat(ndb->file)) != nil){ 640 temp = d->mtime; /* ulong vs int crap */ 641 if(temp > youngest) 642 youngest = temp; 643 free(d); 644 } 645 } 646 if(!doit && youngest == lastyoungest){ 647 unlock(&dblock); 648 return; 649 } 650 651 /* forget our area definition */ 652 freearea(&owned); 653 freearea(&delegated); 654 655 /* reopen all the files (to get oldest for time stamp) */ 656 for(ndb = db; ndb; ndb = ndb->next) 657 ndbreopen(ndb); 658 659 if(cachedb){ 660 /* mark all db records as timed out */ 661 dnagedb(); 662 663 /* read in new entries */ 664 for(ndb = db; ndb; ndb = ndb->next) 665 dbfile2cache(ndb); 666 667 /* mark as authentic anything in our domain */ 668 dnauthdb(); 669 670 /* remove old entries */ 671 dnageall(1); 672 } else { 673 /* read all the soa's to get database defaults */ 674 for(ndb = db; ndb; ndb = ndb->next) 675 dbfile2area(ndb); 676 } 677 678 doit = 0; 679 lastyoungest = youngest; 680 createptrs(); 681 } 682 683 unlock(&dblock); 684 } 685 686 extern uchar ipaddr[IPaddrlen]; 687 688 /* 689 * get all my xxx 690 */ 691 Ndbtuple* 692 lookupinfo(char *attr) 693 { 694 char buf[64]; 695 char *a[2]; 696 static Ndbtuple *t; 697 698 snprint(buf, sizeof buf, "%I", ipaddr); 699 a[0] = attr; 700 701 lock(&dblock); 702 if(opendatabase() < 0){ 703 unlock(&dblock); 704 return nil; 705 } 706 t = ndbipinfo(db, "ip", buf, a, 1); 707 unlock(&dblock); 708 return t; 709 } 710 711 char *localservers = "local#dns#servers"; 712 char *localserverprefix = "local#dns#server"; 713 714 /* 715 * return non-zero is this is a bad delegation 716 */ 717 int 718 baddelegation(RR *rp, RR *nsrp, uchar *addr) 719 { 720 Ndbtuple *nt; 721 static Ndbtuple *t; 722 723 if(t == nil) 724 t = lookupinfo("dom"); 725 if(t == nil) 726 return 0; 727 728 for(; rp; rp = rp->next){ 729 if(rp->type != Tns) 730 continue; 731 732 /* see if delegation is looping */ 733 if(nsrp) 734 if(rp->owner != nsrp->owner) 735 if(subsume(rp->owner->name, nsrp->owner->name) && 736 strcmp(nsrp->owner->name, localservers) != 0){ 737 syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr); 738 return 1; 739 } 740 741 /* see if delegating to us what we don't own */ 742 for(nt = t; nt != nil; nt = nt->entry) 743 if(rp->host && cistrcmp(rp->host->name, nt->val) == 0) 744 break; 745 if(nt != nil && !inmyarea(rp->owner->name)){ 746 syslog(0, logfile, "bad delegation %R from %I", rp, addr); 747 return 1; 748 } 749 } 750 751 return 0; 752 } 753 754 static void 755 addlocaldnsserver(DN *dp, int class, char *ipaddr, int i) 756 { 757 DN *nsdp; 758 RR *rp; 759 char buf[32]; 760 761 /* ns record for name server, make up an impossible name */ 762 rp = rralloc(Tns); 763 snprint(buf, sizeof(buf), "%s%d", localserverprefix, i); 764 nsdp = dnlookup(buf, class, 1); 765 rp->host = nsdp; 766 rp->owner = dp; 767 rp->local = 1; 768 rp->db = 1; 769 rp->ttl = 10*Min; 770 rrattach(rp, 1); 771 772 print("dns %s\n", ipaddr); 773 /* A record */ 774 rp = rralloc(Ta); 775 rp->ip = dnlookup(ipaddr, class, 1); 776 rp->owner = nsdp; 777 rp->local = 1; 778 rp->db = 1; 779 rp->ttl = 10*Min; 780 rrattach(rp, 1); 781 } 782 783 /* 784 * return list of dns server addresses to use when 785 * acting just as a resolver. 786 */ 787 RR* 788 dnsservers(int class) 789 { 790 Ndbtuple *t, *nt; 791 RR *nsrp; 792 DN *dp; 793 char *p; 794 int i, n; 795 char *buf, *args[5]; 796 797 dp = dnlookup(localservers, class, 1); 798 nsrp = rrlookup(dp, Tns, NOneg); 799 if(nsrp != nil) 800 return nsrp; 801 802 p = getenv("DNSSERVER"); 803 if(p != nil){ 804 buf = estrdup(p); 805 n = tokenize(buf, args, nelem(args)); 806 for(i = 0; i < n; i++) 807 addlocaldnsserver(dp, class, args[i], i); 808 free(buf); 809 } else { 810 t = lookupinfo("@dns"); 811 if(t == nil) 812 return nil; 813 i = 0; 814 for(nt = t; nt != nil; nt = nt->entry){ 815 addlocaldnsserver(dp, class, nt->val, i); 816 i++; 817 } 818 ndbfree(t); 819 } 820 821 return rrlookup(dp, Tns, NOneg); 822 } 823 824 static void 825 addlocaldnsdomain(DN *dp, int class, char *domain) 826 { 827 RR *rp; 828 829 /* A record */ 830 rp = rralloc(Tptr); 831 rp->ptr = dnlookup(domain, class, 1); 832 rp->owner = dp; 833 rp->db = 1; 834 rp->ttl = 10*Min; 835 rrattach(rp, 1); 836 } 837 838 /* 839 * return list of domains to use when resolving names without '.'s 840 */ 841 RR* 842 domainlist(int class) 843 { 844 Ndbtuple *t, *nt; 845 RR *rp; 846 DN *dp; 847 848 dp = dnlookup("local#dns#domains", class, 1); 849 rp = rrlookup(dp, Tptr, NOneg); 850 if(rp != nil) 851 return rp; 852 853 t = lookupinfo("dnsdomain"); 854 if(t == nil) 855 return nil; 856 for(nt = t; nt != nil; nt = nt->entry) 857 addlocaldnsdomain(dp, class, nt->val); 858 ndbfree(t); 859 860 return rrlookup(dp, Tptr, NOneg); 861 } 862 863 char *v4ptrdom = ".in-addr.arpa"; 864 char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */ 865 866 char *attribs[] = { 867 "ipmask", 868 0 869 }; 870 871 /* 872 * create ptrs that are in our areas 873 */ 874 static void 875 createptrs(void) 876 { 877 int len, dlen, n; 878 Area *s; 879 char *f[40]; 880 char buf[Domlen+1]; 881 uchar net[IPaddrlen]; 882 uchar mask[IPaddrlen]; 883 char ipa[48]; 884 Ndbtuple *t, *nt; 885 886 dlen = strlen(v4ptrdom); 887 for(s = owned; s; s = s->next){ 888 len = strlen(s->soarr->owner->name); 889 if(len <= dlen) 890 continue; 891 if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0) 892 continue; 893 894 /* get mask and net value */ 895 strncpy(buf, s->soarr->owner->name, sizeof(buf)); 896 buf[sizeof(buf)-1] = 0; 897 n = getfields(buf, f, nelem(f), 0, "."); 898 memset(mask, 0xff, IPaddrlen); 899 ipmove(net, v4prefix); 900 switch(n){ 901 case 3: /* /8 */ 902 net[IPv4off] = atoi(f[0]); 903 mask[IPv4off+1] = 0; 904 mask[IPv4off+2] = 0; 905 mask[IPv4off+3] = 0; 906 break; 907 case 4: /* /16 */ 908 net[IPv4off] = atoi(f[1]); 909 net[IPv4off+1] = atoi(f[0]); 910 mask[IPv4off+2] = 0; 911 mask[IPv4off+3] = 0; 912 break; 913 case 5: /* /24 */ 914 net[IPv4off] = atoi(f[2]); 915 net[IPv4off+1] = atoi(f[1]); 916 net[IPv4off+2] = atoi(f[0]); 917 mask[IPv4off+3] = 0; 918 break; 919 case 6: /* rfc2317 */ 920 net[IPv4off] = atoi(f[3]); 921 net[IPv4off+1] = atoi(f[2]); 922 net[IPv4off+2] = atoi(f[1]); 923 net[IPv4off+3] = atoi(f[0]); 924 sprint(ipa, "%I", net); 925 t = ndbipinfo(db, "ip", ipa, attribs, 1); 926 if(t == nil) /* could be a reverse with no forward */ 927 continue; 928 nt = look(t, t, "ipmask"); 929 if(nt == nil){ /* we're confused */ 930 ndbfree(t); 931 continue; 932 } 933 parseipmask(mask, nt->val); 934 n = 5; 935 break; 936 default: 937 continue; 938 } 939 940 /* go through all domain entries looking for RR's in this network and create ptrs */ 941 dnptr(net, mask, s->soarr->owner->name, 6-n, 0); 942 } 943 }