123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <netinet/in.h>
- #include <dns/message.h>
- #include <dns/rcode.h>
- #include <asiolink/asiolink.h>
- #include <dns/tests/unittest_util.h>
- #include <testutils/dnsmessage_test.h>
- #include <testutils/srv_test.h>
- using namespace isc::dns;
- using namespace asiolink;
- namespace isc {
- namespace testutils {
- const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
- SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
- parse_message(new Message(Message::PARSE)),
- response_message(new Message(Message::RENDER)),
- default_qid(0x1035),
- opcode(Opcode(Opcode::QUERY())),
- qname("www.example.com"),
- qclass(RRClass::IN()),
- qtype(RRType::A()), io_sock(NULL),
- io_message(NULL), endpoint(NULL),
- request_obuffer(0),
- request_renderer(request_obuffer),
- response_obuffer(new OutputBuffer(0))
- {}
- SrvTestBase::~SrvTestBase() {
- delete io_message;
- delete endpoint;
- }
- void
- SrvTestBase::createDataFromFile(const char* const datafile,
- const int protocol)
- {
- delete io_message;
- data.clear();
- delete endpoint;
- endpoint = IOEndpoint::create(protocol,
- IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
- UnitTestUtil::readWireData(datafile, data);
- io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
- &IOSocket::getDummyTCPSocket();
- io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
- }
- void
- SrvTestBase::createRequestPacket(Message& message,
- const int protocol)
- {
- message.toWire(request_renderer);
- delete io_message;
- endpoint = IOEndpoint::create(protocol,
- IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
- io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
- &IOSocket::getDummyTCPSocket();
- io_message = new IOMessage(request_renderer.getData(),
- request_renderer.getLength(),
- *io_sock, *endpoint);
- }
- // Unsupported requests. Should result in NOTIMP.
- void
- SrvTestBase::unsupportedRequest() {
- for (unsigned int i = 0; i < 16; ++i) {
- // set Opcode to 'i', which iterators over all possible codes except
- // the standard query and notify
- if (i == isc::dns::Opcode::QUERY().getCode() ||
- i == isc::dns::Opcode::NOTIFY().getCode()) {
- continue;
- }
- createDataFromFile("simplequery_fromWire.wire");
- data[2] = ((i << 3) & 0xff);
- parse_message->clear(isc::dns::Message::PARSE);
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::NOTIMP(), i,
- QR_FLAG, 0, 0, 0, 0);
- }
- }
- // Multiple questions. Should result in FORMERR.
- void
- SrvTestBase::multiQuestion() {
- createDataFromFile("multiquestion_fromWire.wire");
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
- opcode.getCode(), QR_FLAG, 2, 0, 0, 0);
- isc::dns::QuestionIterator qit = parse_message->beginQuestion();
- EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
- EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
- EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
- ++qit;
- EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
- EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
- EXPECT_EQ(isc::dns::RRType::AAAA(), (*qit)->getType());
- ++qit;
- EXPECT_TRUE(qit == parse_message->endQuestion());
- }
- // Incoming data doesn't even contain the complete header. Must be silently
- // dropped.
- void
- SrvTestBase::shortMessage() {
- createDataFromFile("shortmessage_fromWire");
- processMessage();
- EXPECT_FALSE(dnsserv.hasAnswer());
- }
- // Response messages. Must be silently dropped, whether it's a valid response
- // or malformed or could otherwise cause a protocol error.
- void
- SrvTestBase::response() {
- // A valid (although unusual) response
- createDataFromFile("simpleresponse_fromWire.wire");
- processMessage();
- EXPECT_FALSE(dnsserv.hasAnswer());
- // A response with a broken question section. must be dropped rather than
- //returning FORMERR.
- createDataFromFile("shortresponse_fromWire");
- processMessage();
- EXPECT_FALSE(dnsserv.hasAnswer());
- // A response to iquery. must be dropped rather than returning NOTIMP.
- createDataFromFile("iqueryresponse_fromWire.wire");
- processMessage();
- EXPECT_FALSE(dnsserv.hasAnswer());
- }
- // Query with a broken question
- void
- SrvTestBase::shortQuestion() {
- createDataFromFile("shortquestion_fromWire");
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- // Since the query's question is broken, the question section of the
- // response should be empty.
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
- opcode.getCode(), QR_FLAG, 0, 0, 0, 0);
- }
- // Query with a broken answer section
- void
- SrvTestBase::shortAnswer() {
- createDataFromFile("shortanswer_fromWire.wire");
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- // This is a bogus query, but question section is valid. So the response
- // should copy the question section.
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
- opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
- isc::dns::QuestionIterator qit = parse_message->beginQuestion();
- EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
- EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
- EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
- ++qit;
- EXPECT_TRUE(qit == parse_message->endQuestion());
- }
- // Query with unsupported version of EDNS.
- void
- SrvTestBase::ednsBadVers() {
- createDataFromFile("queryBadEDNS_fromWire.wire");
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- // The response must have an EDNS OPT RR in the additional section,
- // it will be added automatically at the render time.
- // Note that the DNSSEC DO bit is cleared even if this bit in the query
- // is set. This is a limitation of the current implementation.
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::BADVERS(),
- opcode.getCode(), QR_FLAG, 1, 0, 0, 1);
- EXPECT_FALSE(parse_message->getEDNS()); // EDNS isn't added at this point
- isc::dns::InputBuffer ib(response_obuffer->getData(),
- response_obuffer->getLength());
- isc::dns::Message parsed(isc::dns::Message::PARSE);
- parsed.fromWire(ib);
- EXPECT_EQ(isc::dns::Rcode::BADVERS(), parsed.getRcode());
- isc::dns::ConstEDNSPtr edns(parsed.getEDNS());
- ASSERT_TRUE(edns);
- EXPECT_FALSE(edns->getDNSSECAwareness());
- }
- void
- SrvTestBase::axfrOverUDP() {
- // AXFR over UDP is invalid and should result in FORMERR.
- UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
- isc::dns::Name("example.com"),
- isc::dns::RRClass::IN(),
- isc::dns::RRType::AXFR());
- createRequestPacket(request_message, IPPROTO_UDP);
- processMessage();
- EXPECT_TRUE(dnsserv.hasAnswer());
- headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
- opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
- }
- } // end of namespace testutils
- } // end of namespace isc
- // Local Variables:
- // mode: c++
- // End:
|