| | 439 | typedef map<pair<string, QType>, set<DNSResourceRecord>, TCacheComp > tcache_t; |
| | 440 | tcache_t tcache; |
| | 441 | |
| | 442 | struct { |
| | 443 | vector<DNSResourceRecord> d_result; |
| | 444 | bool d_aabit; |
| | 445 | int d_rcode; |
| | 446 | } lwr; |
| | 447 | DNSResourceRecord rr; |
| | 448 | for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { |
| | 449 | DNSResourceRecord rr; |
| | 450 | rr.qtype=i->first.d_type; |
| | 451 | rr.qname=i->first.d_label; |
| | 452 | |
| | 453 | rr.ttl=i->first.d_ttl; |
| | 454 | rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form |
| | 455 | rr.d_place=(DNSResourceRecord::Place) i->first.d_place; |
| | 456 | lwr.d_result.push_back(rr); |
| | 457 | } |
| | 458 | |
| | 459 | |
| | 460 | |
| | 461 | |
| | 462 | // reap all answers from this packet that are acceptable |
| | 463 | for(vector<DNSResourceRecord>::iterator i=lwr.d_result.begin();i != lwr.d_result.end();++i) { |
| | 464 | if(i->qtype.getCode() == QType::OPT) { |
| | 465 | // <<prefix<<qname<<": skipping OPT answer '"<<i->qname<<"' from '"<<auth<<"' nameservers" <<endl; |
| | 466 | continue; |
| | 467 | } |
| | 468 | // LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? "; |
| | 469 | if(i->qtype.getCode()==QType::ANY) { |
| | 470 | // LOG<<"NO! - we don't accept 'ANY' data"<<endl; |
| | 471 | continue; |
| | 472 | } |
| | 473 | string auth("."); |
| | 474 | if(dottedEndsOn(i->qname, auth)) { |
| | 475 | if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && 0) { |
| | 476 | // LOG<<"NO! Is from delegation-only zone"<<endl; |
| | 477 | // s_nodelegated++; |
| | 478 | return; // RCode::NXDomain; |
| | 479 | } |
| | 480 | else { |
| | 481 | // LOG<<"YES!"<<endl; |
| | 482 | |
| | 483 | // i->ttl=min(s_maxcachettl, i->ttl); |
| | 484 | |
| | 485 | DNSResourceRecord rr=*i; |
| | 486 | rr.d_place=DNSResourceRecord::ANSWER; |
| | 487 | |
| | 488 | // rr.ttl += d_now.tv_sec; |
| | 489 | |
| | 490 | if(rr.qtype.getCode() == QType::NS) // people fiddle with the case |
| | 491 | rr.content=toLower(rr.content); // this must stay! (the cache can't be case-insensitive on the RHS of records) |
| | 492 | tcache[make_pair(i->qname,i->qtype)].insert(rr); |
| | 493 | } |
| | 494 | } |
| | 495 | else |
| | 496 | ; // LOG<<"NO!"<<endl; |
| | 497 | } |
| | 498 | |
| | 499 | // supplant |
| | 500 | for(tcache_t::iterator i=tcache.begin();i!=tcache.end();++i) { |
| | 501 | if(i->second.size() > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2) |
| | 502 | uint32_t lowestTTL=numeric_limits<uint32_t>::max(); |
| | 503 | for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j) |
| | 504 | lowestTTL=min(lowestTTL, j->ttl); |
| | 505 | |
| | 506 | for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j) |
| | 507 | ((tcache_t::value_type::second_type::value_type*)&(*j))->ttl=lowestTTL; |
| | 508 | } |
| | 509 | |
| | 510 | // RC.replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit); |
| | 511 | } |
| | 512 | set<string, CIStringCompare> nsset; |
| | 513 | // LOG<<prefix<<qname<<": determining status after receiving this packet"<<endl; |
| | 514 | |
| | 515 | bool done=false, realreferral=false, negindic=false; |
| | 516 | string newauth, soaname, newtarget; |
| | 517 | string qname("."); |
| | 518 | vector<DNSResourceRecord> ret; |
| | 519 | QType qtype(QType::A); |
| | 520 | string auth("."); |
| | 521 | |
| | 522 | for(vector<DNSResourceRecord>::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) { |
| | 523 | if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && |
| | 524 | lwr.d_rcode==RCode::NXDomain) { |
| | 525 | // LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"'"<<endl; |
| | 526 | ret.push_back(*i); |
| | 527 | |
| | 528 | NegCacheEntry ne; |
| | 529 | |
| | 530 | ne.d_qname=i->qname; |
| | 531 | ne.d_ttd=d_now.tv_sec + min(i->ttl, 3600U); // controversial |
| | 532 | ne.d_name=qname; |
| | 533 | ne.d_qtype=QType(0); // this encodes 'whole record' |
| | 534 | |
| | 535 | { |
| | 536 | // Lock l(&s_negcachelock); |
| | 537 | // replacing_insert(s_negcache, ne); |
| | 538 | } |
| | 539 | negindic=true; |
| | 540 | } |
| | 541 | else if(i->d_place==DNSResourceRecord::ANSWER && iequals(i->qname, qname) && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) { |
| | 542 | ret.push_back(*i); |
| | 543 | newtarget=i->content; |
| | 544 | } |
| | 545 | // for ANY answers we *must* have an authoritive answer |
| | 546 | else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && |
| | 547 | ( |
| | 548 | i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) ) |
| | 549 | ) |
| | 550 | ) |
| | 551 | { |
| | 552 | |
| | 553 | // LOG<<prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl; |
| | 554 | |
| | 555 | done=true; |
| | 556 | ret.push_back(*i); |
| | 557 | } |
| | 558 | else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { |
| | 559 | if(moreSpecificThan(i->qname,auth)) { |
| | 560 | newauth=i->qname; |
| | 561 | // LOG<<prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl; |
| | 562 | realreferral=true; |
| | 563 | } |
| | 564 | else |
| | 565 | ;// // LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl; |
| | 566 | nsset.insert(i->content); |
| | 567 | } |
| | 568 | else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && |
| | 569 | lwr.d_rcode==RCode::NoError) { |
| | 570 | // LOG<<prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+i->qtype.getName()+"'") <<endl; |
| | 571 | ret.push_back(*i); |
| | 572 | |
| | 573 | NegCacheEntry ne; |
| | 574 | ne.d_qname=i->qname; |
| | 575 | ne.d_ttd=d_now.tv_sec + i->ttl; |
| | 576 | ne.d_name=qname; |
| | 577 | ne.d_qtype=qtype; |
| | 578 | if(qtype.getCode()) { // prevents us from blacking out a whole domain |
| | 579 | // Lock l(&s_negcachelock); |
| | 580 | // replacing_insert(s_negcache, ne); |
| | 581 | } |
| | 582 | negindic=true; |
| | 583 | } |
| | 584 | } |
| | 585 | |