Commit aeb98ed8 authored by Jeremy C. Reed's avatar Jeremy C. Reed
Browse files
parents 9179014f 8bec2eca
......@@ -12,6 +12,9 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <vector>
#include <boost/foreach.hpp>
#include <dns/message.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
......@@ -37,6 +40,15 @@ Query::getAdditional(const Zone& zone, const RRset& rrset) const {
const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
findAddrs(zone, ns.getNSName(), Zone::FIND_GLUE_OK);
}
} else if (rrset.getType() == RRType::MX()) {
RdataIteratorPtr rdata_iterator = rrset.getRdataIterator();
for (RdataIteratorPtr rdata_iterator(rrset.getRdataIterator());
!rdata_iterator->isLast(); rdata_iterator->next())
{
const Rdata& rdata(rdata_iterator->getCurrent());
const generic::MX& mx(dynamic_cast<const generic::MX&>(rdata));
findAddrs(zone, mx.getMXName());
}
}
}
......@@ -140,6 +152,7 @@ Query::process() const {
response_.addRRset(Message::SECTION_ANSWER,
boost::const_pointer_cast<RRset>(db_result.rrset));
getAuthAdditional(*result.zone);
getAdditional(*result.zone, *db_result.rrset);
break;
case Zone::DELEGATION:
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
......@@ -165,5 +178,6 @@ Query::process() const {
}
}
}
}
}
......@@ -49,13 +49,13 @@ RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
RRClass::IN(), RRType::A(),
RRTTL(3600))));
RRsetPtr delegated_mx_a_rrset(RRsetPtr(new RRset(
Name("mx.delegation.example.com"), RRClass::IN(), RRType::A(),
RRTTL(3600))));
// This is a mock Zone class for testing.
// It is a derived class of Zone, and simply hardcode the results of find()
// return SUCCESS for "www.example.com",
// return NXDOMAIN for "nxdomain.example.com",
// return NXRRSET for "nxrrset.example.com",
// return CNAME for "cname.example.com",
// otherwise return DNAME
// It is a derived class of Zone, and simply hardcodes the results of find()
// See the find() implementation if you want to know its content.
class MockZone : public Zone {
public:
MockZone(bool has_SOA = true, bool has_apex_NS = true) :
......@@ -70,7 +70,11 @@ public:
RRTTL(3600)))),
auth_ns_rrset(RRsetPtr(new RRset(Name("example.com"),
RRClass::IN(), RRType::NS(),
RRTTL(3600))))
RRTTL(3600)))),
mx_cname_rrset_(new RRset(Name("cnamemailer.example.com"),
RRClass::IN(), RRType::CNAME(), RRTTL(3600))),
mx_rrset_(new RRset(Name("mx.example.com"), RRClass::IN(),
RRType::MX(), RRTTL(3600)))
{
delegation_rrset->addRdata(rdata::generic::NS(
Name("glue.ns.example.com")));
......@@ -88,6 +92,14 @@ public:
Name("noglue.example.com")));
auth_ns_rrset->addRdata(rdata::generic::NS(
Name("example.net")));
mx_rrset_->addRdata(isc::dns::rdata::generic::MX(10,
Name("www.example.com")));
mx_rrset_->addRdata(isc::dns::rdata::generic::MX(20,
Name("mailer.example.org")));
mx_rrset_->addRdata(isc::dns::rdata::generic::MX(30,
Name("mx.delegation.example.com")));
mx_cname_rrset_->addRdata(rdata::generic::CNAME(
Name("mx.example.com")));
}
virtual const isc::dns::Name& getOrigin() const;
virtual const isc::dns::RRClass& getClass() const;
......@@ -103,6 +115,8 @@ private:
RRsetPtr delegation_rrset;
RRsetPtr cname_rrset;
RRsetPtr auth_ns_rrset;
RRsetPtr mx_cname_rrset_;
RRsetPtr mx_rrset_;
};
const Name&
......@@ -120,16 +134,18 @@ MockZone::find(const Name& name, const RRType& type,
const FindOptions options) const
{
// hardcode the find results
if (name == Name("www.example.com")) {
if (name == Name("www.example.com") && type == RRType::A()) {
return (FindResult(SUCCESS, a_rrset));
} else if (name == Name("www.example.com")) {
return (FindResult(NXRRSET, RRsetPtr()));
} else if (name == Name("glue.ns.example.com") && type == RRType::A() &&
options == FIND_GLUE_OK) {
(options & FIND_GLUE_OK) != 0) {
return (FindResult(SUCCESS, glue_a_rrset));
} else if (name == Name("noglue.example.com") && (type == RRType::A() ||
type == RRType::ANY())) {
return (FindResult(SUCCESS, noglue_a_rrset));
} else if (name == Name("glue.ns.example.com") && type == RRType::AAAA() &&
options == FIND_GLUE_OK) {
(options & FIND_GLUE_OK) != 0) {
return (FindResult(SUCCESS, glue_aaaa_rrset));
} else if (name == Name("example.com") && type == RRType::SOA() &&
has_SOA_)
......@@ -139,7 +155,14 @@ MockZone::find(const Name& name, const RRType& type,
has_apex_NS_)
{
return (FindResult(SUCCESS, auth_ns_rrset));
} else if (name == Name("delegation.example.com")) {
} else if (name == Name("mx.delegation.example.com") &&
type == RRType::A() && (options & FIND_GLUE_OK) != 0)
{
return (FindResult(SUCCESS, delegated_mx_a_rrset));
} else if (name == Name("delegation.example.com") ||
name.compare(Name("delegation.example.com")).getRelation() ==
NameComparisonResult::SUBDOMAIN)
{
return (FindResult(DELEGATION, delegation_rrset));
} else if (name == Name("ns.example.com")) {
return (FindResult(DELEGATION, ns_rrset));
......@@ -149,6 +172,10 @@ MockZone::find(const Name& name, const RRType& type,
return (FindResult(NXRRSET, RRsetPtr()));
} else if ((name == Name("cname.example.com"))) {
return (FindResult(CNAME, cname_rrset));
} else if (name == Name("cnamemailer.example.com")) {
return (FindResult(CNAME, mx_cname_rrset_));
} else if (name == Name("mx.example.com")) {
return (FindResult(SUCCESS, mx_rrset_));
} else {
return (FindResult(DNAME, RRsetPtr()));
}
......@@ -353,4 +380,83 @@ TEST_F(QueryTest, noMatchZone) {
EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
}
/*
* Test MX additional processing.
*
* The MX RRset has two RRs, one pointing to a known domain with
* A record, other to unknown out of zone one.
*/
TEST_F(QueryTest, MX) {
memory_datasrc.addZone(ZonePtr(new MockZone()));
Name qname("mx.example.com");
Query mx_query(memory_datasrc, qname, RRType::MX(), response);
EXPECT_NO_THROW(mx_query.process());
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
Name("mx.example.com"), RRClass::IN(), RRType::MX()));
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("www.example.com"), RRClass::IN(), RRType::A()));
// We want to skip the additional ones related to authoritative
RRsetPtr ns;
for (SectionIterator<RRsetPtr> ai(response.beginSection(
Message::SECTION_AUTHORITY)); ai != response.endSection(
Message::SECTION_AUTHORITY); ++ai)
{
if ((*ai)->getName() == Name("example.com") && (*ai)->getType() ==
RRType::NS())
{
ns = *ai;
break;
}
}
/*
* In fact, the MX RRset mentions three names, but we don't know anything
* about one of them and one is under a zone cut, so we should have just
* one RRset (A for www.example.com)
*/
// We can't use getRRCount, as it counts RRs, not RRsets
unsigned additional_count(0);
for (SectionIterator<RRsetPtr> ai(response.beginSection(
Message::SECTION_ADDITIONAL)); ai != response.endSection(
Message::SECTION_ADDITIONAL); ++ai)
{
// Skip the ones for the NS record
if (ns) {
for (RdataIteratorPtr nsi(ns->getRdataIterator()); !nsi->isLast();
nsi->next())
{
if ((*ai)->getName() ==
dynamic_cast<const isc::dns::rdata::generic::NS&>(
nsi->getCurrent()).getNSName())
{
goto NS_ADDITIONAL_DATA;
}
}
}
// It is not related to the NS, then it must be related to the MX
++additional_count;
EXPECT_EQ(Name("www.example.com"), (*ai)->getName());
EXPECT_EQ(RRType::A(), (*ai)->getType());
NS_ADDITIONAL_DATA:;
}
EXPECT_EQ(1, additional_count);
}
/*
* Test when we ask for MX and encounter an alias (CNAME in this case).
*
* This should not trigger the additional processing.
*/
TEST_F(QueryTest, MXAlias) {
memory_datasrc.addZone(ZonePtr(new MockZone()));
Name qname("cnamemailer.example.com");
Query mx_query(memory_datasrc, qname, RRType::MX(), response);
EXPECT_NO_THROW(mx_query.process());
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
// We should not have the IP address in additional section
// Currently, the section should be completely empty
EXPECT_TRUE(response.beginSection(Message::SECTION_ADDITIONAL) ==
response.endSection(Message::SECTION_ADDITIONAL));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment