85 lines
2.4 KiB
C++
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;
|
|
}
|
|
}
|