WebDNS/server/src/handler.cpp

85 lines
2.4 KiB
C++

#include "./handler.h"
#include "./server.h"
#include "./net.h"
#include <iostream>
#include <teadns/parser.h>
#include <teadns/builder.h>
using namespace ts::dns;
using namespace ts::dns::builder;
void WebDNSHandler::handle_message(const std::shared_ptr<DNSServerBinding>& binding, const sockaddr_storage &address, void *buffer, size_t size) {
std::cout << "Received DNS request from " << net::to_string(address) << ":\n";
DNSParser parser{0, nullptr, buffer, size};
std::string error;
if(!parser.parse(error)) {
std::cout << " Failed to parse request: " << error << "\n";
return;
}
std::cout << " Query type: " << (uint32_t) parser.header().query_type() << "\n";
std::cout << " Queries (" << parser.queries().size() << "):\n";
for(auto& query : parser.queries())
std::cout << " " << query->qname() << " (" << rrclass::name(query->qclass()) << "::" << rrtype::name(query->qtype()) << ")\n";
std::cout << " Sending response.\n";
{
DNSBuilder response{};
response.header().id(*(uint16_t*) buffer);
response.header().set_answer(true);
response.header().set_response_code(rcode::NOERROR);
response.header().set_query_type(parser.header().query_type());
for(auto& query : parser.queries()) {
auto& q = response.push_query();
q.set_qclass(query->qclass());
q.set_qname(query->qname());
q.set_qtype(query->qtype());
if(query->qclass() == rrclass::IN && query->qtype() == rrtype::A) {
auto dn = query->qname();
uint8_t resp[4];
{
size_t index = 0;
size_t aindex = 0;
do {
auto found = dn.find('.', index);
auto length = index == -1 ? dn.length() - index : found - index;
try {
resp[aindex] = std::stoul(dn.substr(index, length));
} catch(std::exception& ex) {
break;
}
aindex++;
index = found;
} while(index++ && aindex < 4);
if(aindex != 4)
continue;
}
std::cout << " Adding answer ";
for(size_t index = 0; index < 4; index++)
std::cout << (uint32_t) resp[index] << (index == 3 ? "\n" : ".");
auto& a = response.push_answer(query->qname());
a.set_class(query->qclass());
a.set_type(query->qtype());
a.set_ttl(120);
a.builder<rrbuilder::A>().set_address(resp);
}
}
char rbuffer[1024];
auto len = response.build(rbuffer, 1024, error);
if(!len) {
std::cout << " Failed to build response: " << error << "\n";
return;
}
binding->send(address, rbuffer, len);
return;
}
}