Commit 6e4c7c07 authored by Jelte Jansen's avatar Jelte Jansen

ends0 fix and message argument rename

renamed the original MessaPtr message argument in the various process()
calls to query_message, to better reflect the content
Also fixed EDNS0 responses; fill in our own value (currently hardcoded
to 4096, we should make this configurable at some point)
added a new constant DEFAULT_MAX_EDNS0_UDPSIZE to lib/dns/message.h for
that purpose
parent e9c8b140
......@@ -106,7 +106,6 @@ public:
}
void processNormalQuery(const Question& question,
MessagePtr message,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server);
......@@ -211,13 +210,13 @@ public:
// \brief Handle the DNS Lookup
virtual void operator()(const IOMessage& io_message,
MessagePtr message,
MessagePtr query_message,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server) const
{
server_->processMessage(io_message, message, answer_message,
buffer, server);
server_->processMessage(io_message, query_message,
answer_message, buffer, server);
}
private:
Resolver* server_;
......@@ -230,17 +229,17 @@ private:
class MessageAnswer : public DNSAnswer {
public:
virtual void operator()(const IOMessage& io_message,
MessagePtr message,
MessagePtr query_message,
MessagePtr answer_message,
OutputBufferPtr buffer) const
{
const qid_t qid = message->getQid();
const bool rd = message->getHeaderFlag(Message::HEADERFLAG_RD);
const bool cd = message->getHeaderFlag(Message::HEADERFLAG_CD);
const Opcode& opcode = message->getOpcode();
const Rcode& rcode = message->getRcode();
const qid_t qid = query_message->getQid();
const bool rd = query_message->getHeaderFlag(Message::HEADERFLAG_RD);
const bool cd = query_message->getHeaderFlag(Message::HEADERFLAG_CD);
const Opcode& opcode = query_message->getOpcode();
const Rcode& rcode = query_message->getRcode();
vector<QuestionPtr> questions;
questions.assign(message->beginQuestion(), message->endQuestion());
questions.assign(query_message->beginQuestion(), query_message->endQuestion());
// Fill in the final details of the answer message
//message->clear(Message::RENDER);
......@@ -261,10 +260,23 @@ public:
buffer->clear();
MessageRenderer renderer(*buffer);
ConstEDNSPtr edns(query_message->getEDNS());
const bool dnssec_ok = edns && edns->getDNSSECAwareness();
if (edns) {
EDNSPtr edns_response(new EDNS());
edns_response->setDNSSECAwareness(dnssec_ok);
// TODO: We should make our own edns bufsize length configurable
edns_response->setUDPSize(Message::DEFAULT_MAX_EDNS0_UDPSIZE);
answer_message->setEDNS(edns_response);
}
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
ConstEDNSPtr edns(message->getEDNS());
renderer.setLengthLimit(edns ? edns->getUDPSize() :
Message::DEFAULT_MAX_UDPSIZE);
if (edns) {
renderer.setLengthLimit(edns->getUDPSize());
} else {
renderer.setLengthLimit(Message::DEFAULT_MAX_UDPSIZE);
}
} else {
renderer.setLengthLimit(65535);
}
......@@ -273,7 +285,7 @@ public:
dlog(string("sending a response (") +
boost::lexical_cast<string>(renderer.getLength()) + "bytes): \n" +
message->toText());
answer_message->toText());
}
};
......@@ -326,7 +338,7 @@ Resolver::getConfigSession() const {
void
Resolver::processMessage(const IOMessage& io_message,
MessagePtr message,
MessagePtr query_message,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server)
......@@ -336,10 +348,10 @@ Resolver::processMessage(const IOMessage& io_message,
// First, check the header part. If we fail even for the base header,
// just drop the message.
try {
message->parseHeader(request_buffer);
query_message->parseHeader(request_buffer);
// Ignore all responses.
if (message->getHeaderFlag(Message::HEADERFLAG_QR)) {
if (query_message->getHeaderFlag(Message::HEADERFLAG_QR)) {
dlog("Received unexpected response, ignoring");
server->resume(false);
return;
......@@ -352,53 +364,53 @@ Resolver::processMessage(const IOMessage& io_message,
// Parse the message. On failure, return an appropriate error.
try {
message->fromWire(request_buffer);
query_message->fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
dlog(string("returning ") + error.getRcode().toText() + ": " +
error.what());
makeErrorMessage(message, buffer, error.getRcode());
makeErrorMessage(query_message, buffer, error.getRcode());
server->resume(true);
return;
} catch (const Exception& ex) {
dlog(string("returning SERVFAIL: ") + ex.what());
makeErrorMessage(message, buffer, Rcode::SERVFAIL());
makeErrorMessage(query_message, buffer, Rcode::SERVFAIL());
server->resume(true);
return;
} // other exceptions will be handled at a higher layer.
dlog("received a message:\n" + message->toText());
dlog("received a message:\n" + query_message->toText());
// Perform further protocol-level validation.
bool sendAnswer = true;
if (message->getOpcode() == Opcode::NOTIFY()) {
makeErrorMessage(message, buffer, Rcode::NOTAUTH());
if (query_message->getOpcode() == Opcode::NOTIFY()) {
makeErrorMessage(query_message, buffer, Rcode::NOTAUTH());
dlog("Notify arrived, but we are not authoritative");
} else if (message->getOpcode() != Opcode::QUERY()) {
dlog("Unsupported opcode (got: " + message->getOpcode().toText() +
} else if (query_message->getOpcode() != Opcode::QUERY()) {
dlog("Unsupported opcode (got: " + query_message->getOpcode().toText() +
", expected: " + Opcode::QUERY().toText());
makeErrorMessage(message, buffer, Rcode::NOTIMP());
} else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
} else if (query_message->getRRCount(Message::SECTION_QUESTION) != 1) {
dlog("The query contained " +
boost::lexical_cast<string>(message->getRRCount(
boost::lexical_cast<string>(query_message->getRRCount(
Message::SECTION_QUESTION) + " questions, exactly one expected"));
makeErrorMessage(message, buffer, Rcode::FORMERR());
makeErrorMessage(query_message, buffer, Rcode::FORMERR());
} else {
ConstQuestionPtr question = *message->beginQuestion();
ConstQuestionPtr question = *query_message->beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
makeErrorMessage(message, buffer, Rcode::FORMERR());
makeErrorMessage(query_message, buffer, Rcode::FORMERR());
} else {
makeErrorMessage(message, buffer, Rcode::NOTIMP());
makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
}
} else if (qtype == RRType::IXFR()) {
makeErrorMessage(message, buffer, Rcode::NOTIMP());
makeErrorMessage(query_message, buffer, Rcode::NOTIMP());
} else {
// The RecursiveQuery object will post the "resume" event to the
// DNSServer when an answer arrives, so we don't have to do it now.
sendAnswer = false;
impl_->processNormalQuery(*question, message,
answer_message, buffer, server);
impl_->processNormalQuery(*question, answer_message,
buffer, server);
}
}
......@@ -409,27 +421,12 @@ Resolver::processMessage(const IOMessage& io_message,
void
ResolverImpl::processNormalQuery(const Question& question,
MessagePtr message,
MessagePtr answer_message,
OutputBufferPtr buffer,
DNSServer* server)
{
dlog("Processing normal query");
ConstEDNSPtr edns(message->getEDNS());
const bool dnssec_ok = edns && edns->getDNSSECAwareness();
message->makeResponse();
message->setHeaderFlag(Message::HEADERFLAG_RA);
message->setRcode(Rcode::NOERROR());
if (edns) {
EDNSPtr edns_response(new EDNS());
edns_response->setDNSSECAwareness(dnssec_ok);
edns_response->setUDPSize(ResolverImpl::DEFAULT_LOCAL_UDPSIZE);
message->setEDNS(edns_response);
}
dlog("[XX] calling sendQuery()");
rec_query_->sendQuery(question, answer_message, buffer, server);
dlog("[XX] done processing normal query");
}
namespace {
......
......@@ -65,7 +65,7 @@ public:
/// \param buffer Pointer to an \c OutputBuffer for the resposne
/// \param server Pointer to the \c DNSServer
void processMessage(const asiolink::IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::MessagePtr query_message,
isc::dns::MessagePtr answer_message,
isc::dns::OutputBufferPtr buffer,
asiolink::DNSServer* server);
......
......@@ -428,7 +428,6 @@ public:
InputBuffer ibuf(buffer_->getData(), buffer_->getLength());
incoming.fromWire(ibuf);
std::cout << "[XX] received answer: " << incoming.toText() << std::endl;
//
if (incoming.getRcode() == Rcode::NOERROR()) {
if (incoming.getRRCount(Message::SECTION_ANSWER) > 0) {
......
......@@ -197,7 +197,7 @@ private:
// \c IOMessage and \c Message objects to be passed to the
// DNS lookup and answer providers
boost::shared_ptr<asiolink::IOMessage> io_message_;
isc::dns::MessagePtr message_;
isc::dns::MessagePtr query_message_;
isc::dns::MessagePtr answer_message_;
// The buffer into which the query packet is written
......
......@@ -210,7 +210,11 @@ private:
// \c IOMessage and \c Message objects to be passed to the
// DNS lookup and answer providers
boost::shared_ptr<asiolink::IOMessage> io_message_;
isc::dns::MessagePtr message_;
// The original query as sent by the client
isc::dns::MessagePtr query_message_;
// The response message we are building
isc::dns::MessagePtr answer_message_;
// The buffer into which the response is written
......
......@@ -144,7 +144,7 @@ TCPServer::operator()(error_code ec, size_t length) {
// Reset or instantiate objects that will be needed by the
// DNS lookup and the write call.
respbuf_.reset(new OutputBuffer(0));
message_.reset(new Message(Message::PARSE));
query_message_.reset(new Message(Message::PARSE));
answer_message_.reset(new Message(Message::RENDER));
// Schedule a DNS lookup, and yield. When the lookup is
......@@ -160,7 +160,8 @@ TCPServer::operator()(error_code ec, size_t length) {
// Call the DNS answer provider to render the answer into
// wire format
(*answer_callback_)(*io_message_, message_, answer_message_, respbuf_);
(*answer_callback_)(*io_message_, query_message_,
answer_message_, respbuf_);
// Set up the response, beginning with two length bytes.
lenbuf.writeUint16(respbuf_->getLength());
......@@ -179,7 +180,8 @@ TCPServer::operator()(error_code ec, size_t length) {
/// AsyncLookup<TCPServer> handler.)
void
TCPServer::asyncLookup() {
(*lookup_callback_)(*io_message_, message_, answer_message_, respbuf_, this);
(*lookup_callback_)(*io_message_, query_message_,
answer_message_, respbuf_, this);
}
/// Post this coroutine on the ASIO service queue so that it will
......
......@@ -132,7 +132,7 @@ UDPServer::operator()(error_code ec, size_t length) {
// Instantiate objects that will be needed by the
// asynchronous DNS lookup and/or by the send call.
respbuf_.reset(new OutputBuffer(0));
message_.reset(new Message(Message::PARSE));
query_message_.reset(new Message(Message::PARSE));
answer_message_.reset(new Message(Message::RENDER));
// Schedule a DNS lookup, and yield. When the lookup is
......@@ -150,7 +150,8 @@ UDPServer::operator()(error_code ec, size_t length) {
// Call the DNS answer provider to render the answer into
// wire format
(*answer_callback_)(*io_message_, message_, answer_message_, respbuf_);
(*answer_callback_)(*io_message_, query_message_,
answer_message_, respbuf_);
// Begin an asynchronous send, and then yield. When the
// send completes, we will resume immediately after this point
......@@ -166,7 +167,8 @@ UDPServer::operator()(error_code ec, size_t length) {
/// AsyncLookup<UDPServer> handler.)
void
UDPServer::asyncLookup() {
(*lookup_callback_)(*io_message_, message_, answer_message_, respbuf_, this);
(*lookup_callback_)(*io_message_, query_message_, answer_message_,
respbuf_, this);
}
/// Post this coroutine on the ASIO service queue so that it will
......
......@@ -511,6 +511,7 @@ public:
///
/// With EDNS the maximum size can be increased per message.
static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
static const uint16_t DEFAULT_MAX_EDNS0_UDPSIZE = 4096;
//@}
private:
......
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