misc.cc misc.hh \
nameserver.cc nameserver.hh \
namespaces.hh \
+ noinitvector.hh \
nsecrecords.cc \
opensslsigners.cc opensslsigners.hh \
packetcache.hh \
throw std::runtime_error("No inactive certificate found with this serial");
}
-bool DNSCryptQuery::parsePlaintextQuery(const std::vector<uint8_t>& packet)
+bool DNSCryptQuery::parsePlaintextQuery(const PacketBuffer& packet)
{
assert(d_ctx != nullptr);
return true;
}
-void DNSCryptContext::getCertificateResponse(time_t now, const DNSName& qname, uint16_t qid, std::vector<uint8_t>& response)
+void DNSCryptContext::getCertificateResponse(time_t now, const DNSName& qname, uint16_t qid, PacketBuffer& response)
{
- DNSPacketWriter pw(response, qname, QType::TXT, QClass::IN, Opcode::Query);
+ GenericDNSPacketWriter<PacketBuffer> pw(response, qname, QType::TXT, QClass::IN, Opcode::Query);
struct dnsheader * dh = pw.getHeader();
dh->id = qid;
dh->qr = true;
return false;
}
-bool DNSCryptQuery::isEncryptedQuery(const std::vector<uint8_t>& packet, bool tcp, time_t now)
+bool DNSCryptQuery::isEncryptedQuery(const PacketBuffer& packet, bool tcp, time_t now)
{
assert(d_ctx != nullptr);
return true;
}
-void DNSCryptQuery::getDecrypted(bool tcp, std::vector<uint8_t>& packet)
+void DNSCryptQuery::getDecrypted(bool tcp, PacketBuffer& packet)
{
assert(d_encrypted);
assert(d_pair != nullptr);
d_valid = true;
}
-void DNSCryptQuery::getCertificateResponse(time_t now, std::vector<uint8_t>& response) const
+void DNSCryptQuery::getCertificateResponse(time_t now, PacketBuffer& response) const
{
assert(d_ctx != nullptr);
d_ctx->getCertificateResponse(now, d_qname, d_id, response);
}
-void DNSCryptQuery::parsePacket(std::vector<uint8_t>& packet, bool tcp, time_t now)
+void DNSCryptQuery::parsePacket(PacketBuffer& packet, bool tcp, time_t now)
{
d_valid = false;
return result;
}
-int DNSCryptQuery::encryptResponse(std::vector<uint8_t>& response, size_t maxResponseSize, bool tcp)
+int DNSCryptQuery::encryptResponse(PacketBuffer& response, size_t maxResponseSize, bool tcp)
{
struct DNSCryptResponseHeader responseHeader;
assert(response.size() > 0);
return res;
}
-int DNSCryptContext::encryptQuery(std::vector<uint8_t>& packet, size_t maximumSize, const unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE], const DNSCryptPrivateKey& clientPrivateKey, const unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2], bool tcp, const std::shared_ptr<DNSCryptCert>& cert) const
+int DNSCryptContext::encryptQuery(PacketBuffer& packet, size_t maximumSize, const unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE], const DNSCryptPrivateKey& clientPrivateKey, const unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2], bool tcp, const std::shared_ptr<DNSCryptCert>& cert) const
{
assert(packet.size() > 0);
assert(cert != nullptr);
#include "dnsname.hh"
#include "lock.hh"
+#include "noinitvector.hh"
#define DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE (crypto_sign_ed25519_PUBLICKEYBYTES)
#define DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE (crypto_sign_ed25519_SECRETKEYBYTES)
d_pair = pair;
}
- void parsePacket(std::vector<uint8_t>& packet, bool tcp, time_t now);
- void getDecrypted(bool tcp, std::vector<uint8_t>& packet);
- void getCertificateResponse(time_t now, std::vector<uint8_t>& response) const;
- int encryptResponse(std::vector<uint8_t>& response, size_t maxResponseSize, bool tcp);
+ void parsePacket(PacketBuffer& packet, bool tcp, time_t now);
+ void getDecrypted(bool tcp, PacketBuffer& packet);
+ void getCertificateResponse(time_t now, PacketBuffer& response) const;
+ int encryptResponse(PacketBuffer& response, size_t maxResponseSize, bool tcp);
static const size_t s_minUDPLength = 256;
#endif /* HAVE_CRYPTO_BOX_EASY_AFTERNM */
void fillServerNonce(unsigned char* dest) const;
uint16_t computePaddingSize(uint16_t unpaddedLen, size_t maxLen) const;
- bool parsePlaintextQuery(const std::vector<uint8_t>& packet);
- bool isEncryptedQuery(const std::vector<uint8_t>& packet, bool tcp, time_t now);
+ bool parsePlaintextQuery(const PacketBuffer& packet);
+ bool isEncryptedQuery(const PacketBuffer& packet, bool tcp, time_t now);
DNSCryptQueryHeader d_header;
#ifdef HAVE_CRYPTO_BOX_EASY_AFTERNM
std::vector<std::shared_ptr<DNSCryptCertificatePair>> getCertificates() { return d_certs; };
const DNSName& getProviderName() const { return providerName; }
- int encryptQuery(std::vector<uint8_t>& query, size_t maximumSize, const unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE], const DNSCryptPrivateKey& clientPrivateKey, const unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2], bool tcp, const std::shared_ptr<DNSCryptCert>& cert) const;
+ int encryptQuery(PacketBuffer& query, size_t maximumSize, const unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE], const DNSCryptPrivateKey& clientPrivateKey, const unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2], bool tcp, const std::shared_ptr<DNSCryptCert>& cert) const;
bool magicMatchesAPublicKey(DNSCryptQuery& query, time_t now);
- void getCertificateResponse(time_t now, const DNSName& qname, uint16_t qid, std::vector<uint8_t>& response);
+ void getCertificateResponse(time_t now, const DNSName& qname, uint16_t qid, PacketBuffer& response);
private:
static void computePublicKeyFromPrivate(const DNSCryptPrivateKey& privK, unsigned char pubK[DNSCRYPT_PUBLIC_KEY_SIZE]);
}
}
-bool DNSDistPacketCache::getClientSubnet(const std::vector<uint8_t>& packet, size_t qnameWireLength, boost::optional<Netmask>& subnet)
+bool DNSDistPacketCache::getClientSubnet(const PacketBuffer& packet, size_t qnameWireLength, boost::optional<Netmask>& subnet)
{
uint16_t optRDPosition;
size_t remaining = 0;
value = newValue;
}
-void DNSDistPacketCache::insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector<uint8_t>& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL)
+void DNSDistPacketCache::insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL)
{
if (response.size() < sizeof(dnsheader)) {
return;
return getDNSPacketMinTTL(packet, length, seenNoDataSOA);
}
-uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qnameWireLength, const std::vector<uint8_t>& packet, bool tcp)
+uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool tcp)
{
uint32_t result = 0;
/* skip the query ID */
#include "iputils.hh"
#include "lock.hh"
+#include "noinitvector.hh"
struct DNSQuestion;
DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t maxNegativeTTL=3600, uint32_t staleTTL=60, bool dontAge=false, uint32_t shards=1, bool deferrableInsertLock=true, bool parseECS=false);
~DNSDistPacketCache();
- void insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector<uint8_t>& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL);
+ void insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL);
bool get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional<Netmask>& subnet, bool dnssecOK, uint32_t allowExpired = 0, bool skipAging = false);
size_t purgeExpired(size_t upTo=0);
size_t expunge(size_t upTo=0);
d_parseECS = enabled;
}
- uint32_t getKey(const DNSName::string_t& qname, size_t qnameWireLength, const std::vector<uint8_t>& packet, bool tcp);
+ uint32_t getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool tcp);
static uint32_t getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA);
- static bool getClientSubnet(const std::vector<uint8_t>& packet, size_t qnameWireLength, boost::optional<Netmask>& subnet);
+ static bool getClientSubnet(const PacketBuffer& packet, size_t qnameWireLength, boost::optional<Netmask>& subnet);
private:
#include "dnscrypt.hh"
#ifdef HAVE_DNSCRYPT
-int handleDNSCryptQuery(std::vector<uint8_t>& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, std::vector<uint8_t>& response)
+int handleDNSCryptQuery(PacketBuffer& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, PacketBuffer& response)
{
query->parsePacket(packet, tcp, now);
bool g_ECSOverride{false};
bool g_addEDNSToSelfGeneratedResponses{true};
-int rewriteResponseWithoutEDNS(const std::vector<uint8_t>& initialPacket, vector<uint8_t>& newContent)
+int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent)
{
assert(initialPacket.size() >= sizeof(dnsheader));
const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
if (ntohs(dh->qdcount) == 0)
return ENOENT;
- GenericPacketReader<std::vector<uint8_t>> pr(initialPacket);
+ PacketReader pr(pdns_string_view(reinterpret_cast<const char*>(initialPacket.data()), initialPacket.size()));
size_t idx = 0;
DNSName rrname;
rrtype = pr.get16BitInt();
rrclass = pr.get16BitInt();
- DNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode);
+ GenericDNSPacketWriter<PacketBuffer> pw(newContent, rrname, rrtype, rrclass, dh->opcode);
pw.getHeader()->id=dh->id;
pw.getHeader()->qr=dh->qr;
pw.getHeader()->aa=dh->aa;
return true;
}
-static bool slowRewriteQueryWithExistingEDNS(const std::vector<uint8_t>& initialPacket, vector<uint8_t>& newContent, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption)
+static bool slowRewriteQueryWithExistingEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption)
{
assert(initialPacket.size() >= sizeof(dnsheader));
const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
throw std::runtime_error("slowRewriteQueryWithExistingEDNS() should not be called for queries that have no EDNS");
}
- GenericPacketReader<std::vector<uint8_t>> pr(initialPacket);
+ PacketReader pr(pdns_string_view(reinterpret_cast<const char*>(initialPacket.data()), initialPacket.size()));
size_t idx = 0;
DNSName rrname;
rrtype = pr.get16BitInt();
rrclass = pr.get16BitInt();
- DNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode);
+ GenericDNSPacketWriter<PacketBuffer> pw(newContent, rrname, rrtype, rrclass, dh->opcode);
pw.getHeader()->id=dh->id;
pw.getHeader()->qr=dh->qr;
pw.getHeader()->aa=dh->aa;
return true;
}
-static bool slowParseEDNSOptions(const std::vector<uint8_t>& packet, std::shared_ptr<std::map<uint16_t, EDNSOptionView> >& options)
+static bool slowParseEDNSOptions(const PacketBuffer& packet, std::shared_ptr<std::map<uint16_t, EDNSOptionView> >& options)
{
if (packet.size() < sizeof(dnsheader)) {
return false;
return true;
}
-int locateEDNSOptRR(const std::vector<uint8_t>& packet, uint16_t * optStart, size_t * optLen, bool * last)
+int locateEDNSOptRR(const PacketBuffer& packet, uint16_t * optStart, size_t * optLen, bool * last)
{
assert(optStart != NULL);
assert(optLen != NULL);
if (ntohs(dh->arcount) == 0)
return ENOENT;
- GenericPacketReader<std::vector<uint8_t>> pr(packet);
+ PacketReader pr(pdns_string_view(reinterpret_cast<const char*>(packet.data()), packet.size()));
size_t idx = 0;
DNSName rrname;
}
/* extract the start of the OPT RR in a QUERY packet if any */
-int getEDNSOptionsStart(const std::vector<uint8_t>& packet, const size_t offset, uint16_t* optRDPosition, size_t* remaining)
+int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_t* optRDPosition, size_t* remaining)
{
assert(optRDPosition != nullptr);
assert(remaining != nullptr);
generateEDNSOption(EDNSOptionCode::ECS, payload, res);
}
-bool generateOptRR(const std::string& optRData, std::vector<uint8_t>& res, size_t maximumSize, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK)
+bool generateOptRR(const std::string& optRData, PacketBuffer& res, size_t maximumSize, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK)
{
const uint8_t name = 0;
dnsrecordheader dh;
return true;
}
-static bool replaceEDNSClientSubnetOption(std::vector<uint8_t>& packet, size_t maximumSize, size_t const oldEcsOptionStartPosition, size_t const oldEcsOptionSize, size_t const optRDLenPosition, const string& newECSOption)
+static bool replaceEDNSClientSubnetOption(PacketBuffer& packet, size_t maximumSize, size_t const oldEcsOptionStartPosition, size_t const oldEcsOptionSize, size_t const optRDLenPosition, const string& newECSOption)
{
assert(oldEcsOptionStartPosition < packet.size());
assert(optRDLenPosition < packet.size());
return false;
}
-static bool addECSToExistingOPT(std::vector<uint8_t>& packet, size_t maximumSize, const string& newECSOption, size_t optRDLenPosition, bool& ecsAdded)
+static bool addECSToExistingOPT(PacketBuffer& packet, size_t maximumSize, const string& newECSOption, size_t optRDLenPosition, bool& ecsAdded)
{
/* we need to add one EDNS0 ECS option, fixing the size of EDNS0 RDLENGTH */
/* getEDNSOptionsStart has already checked that there is exactly one AR,
return true;
}
-static bool addEDNSWithECS(std::vector<uint8_t>& packet, size_t maximumSize, const string& newECSOption, bool& ednsAdded, bool& ecsAdded)
+static bool addEDNSWithECS(PacketBuffer& packet, size_t maximumSize, const string& newECSOption, bool& ednsAdded, bool& ecsAdded)
{
if (!generateOptRR(newECSOption, packet, maximumSize, g_EdnsUDPPayloadSize, 0, false)) {
return false;
return true;
}
-bool handleEDNSClientSubnet(std::vector<uint8_t>& packet, const size_t maximumSize, const size_t qnameWireLength, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption)
+bool handleEDNSClientSubnet(PacketBuffer& packet, const size_t maximumSize, const size_t qnameWireLength, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption)
{
assert(qnameWireLength <= packet.size());
const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.data());
if (ntohs(dh->ancount) != 0 || ntohs(dh->nscount) != 0 || (ntohs(dh->arcount) != 0 && ntohs(dh->arcount) != 1)) {
- vector<uint8_t> newContent;
+ PacketBuffer newContent;
newContent.reserve(packet.size());
if (!slowRewriteQueryWithExistingEDNS(packet, newContent, ednsAdded, ecsAdded, overrideExisting, newECSOption)) {
return 0;
}
-bool isEDNSOptionInOpt(const std::vector<uint8_t>& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart, uint16_t* optContentLen)
+bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart, uint16_t* optContentLen)
{
if (optLen < optRecordMinimumSize) {
return false;
return false;
}
-int rewriteResponseWithoutEDNSOption(const std::vector<uint8_t>& initialPacket, const uint16_t optionCodeToSkip, vector<uint8_t>& newContent)
+int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const uint16_t optionCodeToSkip, PacketBuffer& newContent)
{
assert(initialPacket.size() >= sizeof(dnsheader));
const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
if (ntohs(dh->qdcount) == 0)
return ENOENT;
- GenericPacketReader<std::vector<uint8_t>> pr(initialPacket);
+ PacketReader pr(pdns_string_view(reinterpret_cast<const char*>(initialPacket.data()), initialPacket.size()));
size_t idx = 0;
DNSName rrname;
rrtype = pr.get16BitInt();
rrclass = pr.get16BitInt();
- DNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode);
+ GenericDNSPacketWriter<PacketBuffer> pw(newContent, rrname, rrtype, rrclass, dh->opcode);
pw.getHeader()->id=dh->id;
pw.getHeader()->qr=dh->qr;
pw.getHeader()->aa=dh->aa;
return 0;
}
-bool addEDNS(std::vector<uint8_t>& packet, size_t maximumSize, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode)
+bool addEDNS(PacketBuffer& packet, size_t maximumSize, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode)
{
if (!generateOptRR(std::string(), packet, maximumSize, payloadSize, ednsrcode, dnssecOK)) {
return false;
extern size_t g_EdnsUDPPayloadSize;
extern uint16_t g_PayloadSizeSelfGenAnswers;
-int rewriteResponseWithoutEDNS(const std::vector<uint8_t>& initialPacket, vector<uint8_t>& newContent);
-int locateEDNSOptRR(const std::vector<uint8_t> & packet, uint16_t * optStart, size_t * optLen, bool * last);
-bool generateOptRR(const std::string& optRData, std::vector<uint8_t>& res, size_t maximumSize, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK);
+int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent);
+int locateEDNSOptRR(const PacketBuffer & packet, uint16_t * optStart, size_t * optLen, bool * last);
+bool generateOptRR(const std::string& optRData, PacketBuffer& res, size_t maximumSize, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK);
void generateECSOption(const ComboAddress& source, string& res, uint16_t ECSPrefixLength);
int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove);
-int rewriteResponseWithoutEDNSOption(const std::vector<uint8_t>& initialPacket, const uint16_t optionCodeToSkip, vector<uint8_t>& newContent);
-int getEDNSOptionsStart(const std::vector<uint8_t>& packet, const size_t offset, uint16_t* optRDPosition, size_t * remaining);
-bool isEDNSOptionInOpt(const std::vector<uint8_t>& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart = nullptr, uint16_t* optContentLen = nullptr);
-bool addEDNS(std::vector<uint8_t>& packet, size_t maximumSize, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode);
+int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const uint16_t optionCodeToSkip, PacketBuffer& newContent);
+int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_t* optRDPosition, size_t * remaining);
+bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart = nullptr, uint16_t* optContentLen = nullptr);
+bool addEDNS(PacketBuffer& packet, size_t maximumSize, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode);
bool addEDNSToQueryTurnedResponse(DNSQuestion& dq);
bool setNegativeAndAdditionalSOA(DNSQuestion& dq, bool nxd, const DNSName& zone, uint32_t ttl, const DNSName& mname, const DNSName& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum);
bool handleEDNSClientSubnet(DNSQuestion& dq, bool& ednsAdded, bool& ecsAdded);
-bool handleEDNSClientSubnet(std::vector<uint8_t>& packet, size_t maximumSize, size_t qnameWireLength, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption);
+bool handleEDNSClientSubnet(PacketBuffer& packet, size_t maximumSize, size_t qnameWireLength, bool& ednsAdded, bool& ecsAdded, bool overrideExisting, const string& newECSOption);
bool parseEDNSOptions(const DNSQuestion& dq);
d_queries++;
if(d_addECS) {
- std::vector<uint8_t> query(dq->getData());
+ PacketBuffer query(dq->getData());
bool ednsAdded = false;
bool ecsAdded = false;
class HTTPStatusAction: public DNSAction
{
public:
- HTTPStatusAction(int code, const std::vector<uint8_t>& body, const std::string& contentType): d_body(body), d_contentType(contentType), d_code(code)
+ HTTPStatusAction(int code, const PacketBuffer& body, const std::string& contentType): d_body(body), d_contentType(contentType), d_code(code)
{
}
return Action::None;
}
- dq->du->setHTTPResponse(d_code, std::vector<uint8_t>(d_body), d_contentType);
+ dq->du->setHTTPResponse(d_code, PacketBuffer(d_body), d_contentType);
dq->getHeader()->qr = true; // for good measure
setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
return Action::HeaderModify;
ResponseConfig d_responseConfig;
private:
- std::vector<uint8_t> d_body;
+ PacketBuffer d_body;
std::string d_contentType;
int d_code;
};
#ifdef HAVE_DNS_OVER_HTTPS
luaCtx.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional<std::string> contentType, boost::optional<responseParams_t> vars) {
- auto ret = std::shared_ptr<DNSAction>(new HTTPStatusAction(status, std::vector<uint8_t>(body.begin(), body.end()), contentType ? *contentType : ""));
+ auto ret = std::shared_ptr<DNSAction>(new HTTPStatusAction(status, PacketBuffer(body.begin(), body.end()), contentType ? *contentType : ""));
auto hsa = std::dynamic_pointer_cast<HTTPStatusAction>(ret);
parseResponseConfig(vars, hsa->d_responseConfig);
return ret;
if (dq.du == nullptr) {
return;
}
- std::vector<uint8_t> vect(body.begin(), body.end());
+ PacketBuffer vect(body.begin(), body.end());
dq.du->setHTTPResponse(statusCode, std::move(vect), contentType ? *contentType : "");
});
#endif /* HAVE_DNS_OVER_HTTPS */
headers->push_back({ boost::to_lower_copy(header.first), header.second });
}
}
- return std::make_shared<DOHResponseMapEntry>(regex, status, std::vector<uint8_t>(content.begin(), content.end()), headers);
+ return std::make_shared<DOHResponseMapEntry>(regex, status, PacketBuffer(content.begin(), content.end()), headers);
});
}
int times = times_.get_value_or(100000);
DNSName suffix(suffix_.get_value_or("powerdns.com"));
struct item {
- vector<uint8_t> packet;
+ PacketBuffer packet;
ComboAddress rem;
DNSName qname;
uint16_t qtype, qclass;
i.qclass = 1;
i.rem=ComboAddress("127.0.0.1");
i.rem.sin4.sin_addr.s_addr = random();
- DNSPacketWriter pw(i.packet, i.qname, i.qtype);
+ GenericDNSPacketWriter<PacketBuffer> pw(i.packet, i.qname, i.qtype);
items.push_back(i);
}
static size_t const s_initialUDPPacketBufferSize = s_maxPacketCacheEntrySize + DNSCRYPT_MAX_RESPONSE_PADDING_AND_MAC_SIZE;
static_assert(s_initialUDPPacketBufferSize <= UINT16_MAX, "Packet size should fit in a uint16_t");
-static void truncateTC(std::vector<uint8_t>& packet, size_t maximumSize, unsigned int qnameWireLength)
+static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qnameWireLength)
{
try
{
struct DelayedPacket
{
int fd;
- std::vector<uint8_t> packet;
+ PacketBuffer packet;
ComboAddress destination;
ComboAddress origDest;
void operator()()
doAvg(g_stats.latencyAvg1000000, udiff, 1000000);
}
-bool responseContentMatches(const std::vector<uint8_t>& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength)
+bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength)
{
if (response.size() < sizeof(dnsheader)) {
return false;
return addEDNSToQueryTurnedResponse(dq);
}
-static bool fixUpResponse(std::vector<uint8_t>& response, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, bool* zeroScope)
+static bool fixUpResponse(PacketBuffer& response, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, bool* zeroScope)
{
if (response.size() < sizeof(dnsheader)) {
return false;
}
else {
/* Removing an intermediary RR could lead to compression error */
- std::vector<uint8_t> rewrittenResponse;
+ PacketBuffer rewrittenResponse;
if (rewriteResponseWithoutEDNS(response, rewrittenResponse) == 0) {
response = std::move(rewrittenResponse);
}
response.resize(response.size() - (existingOptLen - optLen));
}
else {
- std::vector<uint8_t> rewrittenResponse;
+ PacketBuffer rewrittenResponse;
/* Removing an intermediary RR could lead to compression error */
if (rewriteResponseWithoutEDNSOption(response, EDNSOptionCode::ECS, rewrittenResponse) == 0) {
response = std::move(rewrittenResponse);
}
#ifdef HAVE_DNSCRYPT
-static bool encryptResponse(std::vector<uint8_t>& response, size_t maximumSize, bool tcp, std::shared_ptr<DNSCryptQuery> dnsCryptQuery)
+static bool encryptResponse(PacketBuffer& response, size_t maximumSize, bool tcp, std::shared_ptr<DNSCryptQuery> dnsCryptQuery)
{
if (dnsCryptQuery) {
int res = dnsCryptQuery->encryptResponse(response, maximumSize, tcp);
return true;
}
-bool processResponse(std::vector<uint8_t>& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, bool muted)
+bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, bool muted)
{
if (!applyRulesToResponse(localRespRulactions, dr)) {
return false;
return true;
}
-static bool sendUDPResponse(int origFD, const std::vector<uint8_t>& response, const int delayMsec, const ComboAddress& origDest, const ComboAddress& origRemote)
+static bool sendUDPResponse(int origFD, const PacketBuffer& response, const int delayMsec, const ComboAddress& origDest, const ComboAddress& origRemote)
{
if(delayMsec && g_delay) {
DelayedPacket dp{origFD, response, origRemote, origDest};
try {
setThreadName("dnsdist/respond");
auto localRespRulactions = g_resprulactions.getLocal();
- std::vector<uint8_t> response(s_initialUDPPacketBufferSize);
+ PacketBuffer response(s_initialUDPPacketBufferSize);
/* when the answer is encrypted in place, we need to get a copy
of the original header before encryption to fill the ring buffer */
return true;
}
-ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const std::vector<uint8_t>& request, bool healthCheck)
+ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck)
{
ssize_t result;
return true;
}
-bool checkDNSCryptQuery(const ClientState& cs, std::vector<uint8_t>& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp)
+bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp)
{
if (cs.dnscryptCtx) {
#ifdef HAVE_DNSCRYPT
- vector<uint8_t> response;
+ PacketBuffer response;
dnsCryptQuery = std::make_shared<DNSCryptQuery>(cs.dnscryptCtx);
bool decrypted = handleDNSCryptQuery(query, dnsCryptQuery, tcp, now, response);
}
#if defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE)
-static void queueResponse(const ClientState& cs, const std::vector<uint8_t>& response, const ComboAddress& dest, const ComboAddress& remote, struct mmsghdr& outMsg, struct iovec* iov, cmsgbuf_aligned* cbuf)
+static void queueResponse(const ClientState& cs, const PacketBuffer& response, const ComboAddress& dest, const ComboAddress& remote, struct mmsghdr& outMsg, struct iovec* iov, cmsgbuf_aligned* cbuf)
{
outMsg.msg_len = 0;
fillMSGHdr(&outMsg.msg_hdr, iov, nullptr, 0, const_cast<char*>(reinterpret_cast<const char *>(&response.at(0))), response.size(), const_cast<ComboAddress*>(&remote));
return ProcessQueryResult::Drop;
}
-static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct msghdr* msgh, const ComboAddress& remote, ComboAddress& dest, std::vector<uint8_t>& query, struct mmsghdr* responsesVect, unsigned int* queuedResponses, struct iovec* respIOV, cmsgbuf_aligned* respCBuf)
+static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct msghdr* msgh, const ComboAddress& remote, ComboAddress& dest, PacketBuffer& query, struct mmsghdr* responsesVect, unsigned int* queuedResponses, struct iovec* respIOV, cmsgbuf_aligned* respCBuf)
{
assert(responsesVect == nullptr || (queuedResponses != nullptr && respIOV != nullptr && respCBuf != nullptr));
uint16_t queryId = 0;
{
struct MMReceiver
{
- std::vector<uint8_t> packet;
+ PacketBuffer packet;
ComboAddress remote;
ComboAddress dest;
struct iovec iov;
else
#endif /* defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE) */
{
- std::vector<uint8_t> packet(s_initialUDPPacketBufferSize);
+ PacketBuffer packet(s_initialUDPPacketBufferSize);
/* the actual buffer is larger because:
- we may have to add EDNS and/or ECS
- we use it for self-generated responses (from rule or cache)
#include "iputils.hh"
#include "misc.hh"
#include "mplexer.hh"
+#include "noinitvector.hh"
#include "sholder.hh"
#include "tcpiohandler.hh"
#include "uuid-utils.hh"
extern uint16_t g_ECSSourcePrefixV6;
extern bool g_ECSOverride;
-typedef std::unordered_map<string, string> QTag;
+using QTag = std::unordered_map<string, string>;
struct DNSQuestion
{
- DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, std::vector<uint8_t>& data_, bool isTcp, const struct timespec* queryTime_):
+ DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
data(data_), qname(name), local(lc), remote(rem), queryTime(queryTime_), tempFailureTTL(boost::none), qtype(type), qclass(class_), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tcp(isTcp), ecsOverride(g_ECSOverride) {
const uint16_t* flags = getFlagsFromDNSHeader(getHeader());
origFlags = *flags;
std::string getTrailingData() const;
bool setTrailingData(const std::string&);
- const std::vector<uint8_t>& getData() const
+ const PacketBuffer& getData() const
{
return data;
}
- std::vector<uint8_t>& getMutableData()
+ PacketBuffer& getMutableData()
{
return data;
}
}
protected:
- std::vector<uint8_t>& data;
+ PacketBuffer& data;
public:
boost::optional<boost::uuids::uuid> uniqueId;
struct DNSResponse : DNSQuestion
{
- DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, std::vector<uint8_t>& data_, bool isTcp, const struct timespec* queryTime_):
+ DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
DNSQuestion(name, type, class_, lc, rem, data_, isTcp, queryTime_) { }
DNSResponse(const DNSResponse&) = delete;
DNSResponse& operator=(const DNSResponse&) = delete;
bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect
void resetLuaSideEffect(); // reset to indeterminate state
-bool responseContentMatches(const std::vector<uint8_t>& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength);
-bool processResponse(std::vector<uint8_t>& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, bool muted);
+bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength);
+bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRulactions, DNSResponse& dr, bool muted);
bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop);
bool checkQueryHeaders(const struct dnsheader* dh);
extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
-int handleDNSCryptQuery(std::vector<uint8_t>& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, std::vector<uint8_t>& response);
-bool checkDNSCryptQuery(const ClientState& cs, std::vector<uint8_t>& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
+int handleDNSCryptQuery(PacketBuffer& packet, std::shared_ptr<DNSCryptQuery>& query, bool tcp, time_t now, PacketBuffer& response);
+bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
uint16_t getRandomDNSID();
enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };
ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
-DNSResponse makeDNSResponseFromIDState(IDState& ids, std::vector<uint8_t>& data, bool isTCP);
+DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP);
void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname);
int pickBackendSocketForSending(std::shared_ptr<DownstreamState>& state);
-ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const std::vector<uint8_t>& request, bool healthCheck = false);
+ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck = false);
misc.cc misc.hh \
mplexer.hh \
namespaces.hh \
+ noinitvector.hh \
packetcache.hh \
pdnsexception.hh \
pollmplexer.cc \
iputils.cc iputils.hh \
misc.cc misc.hh \
namespaces.hh \
+ noinitvector.hh \
pdnsexception.hh \
pollmplexer.cc \
proxy-protocol.cc proxy-protocol.hh \
checkClass = std::get<2>(ret);
}
- vector<uint8_t> packet;
- DNSPacketWriter dpw(packet, checkName, checkType, checkClass);
+ PacketBuffer packet;
+ GenericDNSPacketWriter<PacketBuffer> dpw(packet, checkName, checkType, checkClass);
dnsheader * requestHeader = dpw.getHeader();
*requestHeader = checkHeader;
#include "dnsdist.hh"
-DNSResponse makeDNSResponseFromIDState(IDState& ids, std::vector<uint8_t>& data, bool isTCP)
+DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP)
{
DNSResponse dr(&ids.qname, ids.qtype, ids.qclass, &ids.origDest, &ids.origRemote, data, isTCP, &ids.sentTime.d_start);
dr.origFlags = ids.origFlags;
}
#ifdef HAVE_DNS_OVER_HTTPS
- std::vector<uint8_t> bodyVect(body, body + bodyLen);
+ PacketBuffer bodyVect(body, body + bodyLen);
dq->dq->du->setHTTPResponse(statusCode, std::move(bodyVect), contentType);
dq->dq->getHeader()->qr = true;
#endif
return addProxyProtocol(dq, payload);
}
-bool addProxyProtocol(std::vector<uint8_t>& buffer, const std::string& payload)
+bool addProxyProtocol(PacketBuffer& buffer, const std::string& payload)
{
auto previousSize = buffer.size();
if (payload.size() > (std::numeric_limits<size_t>::max() - previousSize)) {
return true;
}
-bool addProxyProtocol(std::vector<uint8_t>& buffer, bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector<ProxyProtocolValue>& values)
+bool addProxyProtocol(PacketBuffer& buffer, bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector<ProxyProtocolValue>& values)
{
auto payload = makeProxyHeader(tcp, source, destination, values);
return addProxyProtocol(buffer, payload);
bool addProxyProtocol(DNSQuestion& dq);
bool addProxyProtocol(DNSQuestion& dq, const std::string& payload);
-bool addProxyProtocol(std::vector<uint8_t>& buffer, const std::string& payload);
-bool addProxyProtocol(std::vector<uint8_t>& buffer, bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector<ProxyProtocolValue>& values);
+bool addProxyProtocol(PacketBuffer& buffer, const std::string& payload);
+bool addProxyProtocol(PacketBuffer& buffer, bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector<ProxyProtocolValue>& values);
static std::string getSecPollStatus(const std::string& queriedName, int timeout=2)
{
const DNSName& sentName = DNSName(queriedName);
- vector<uint8_t> packet;
+ std::vector<uint8_t> packet;
DNSPacketWriter pw(packet, sentName, QType::TXT);
pw.getHeader()->id = getRandomDNSID();
pw.getHeader()->rd = 1;
would block.
*/
// XXX could probably be implemented as a TCPIOHandler
-static IOState tryRead(int fd, std::vector<uint8_t>& buffer, size_t& pos, size_t toRead)
+static IOState tryRead(int fd, PacketBuffer& buffer, size_t& pos, size_t toRead)
{
if (buffer.size() < (pos + toRead)) {
throw std::out_of_range("Calling tryRead() with a too small buffer (" + std::to_string(buffer.size()) + ") for a read of " + std::to_string(toRead) + " bytes starting at " + std::to_string(pos));
{
}
- TCPQuery(std::vector<uint8_t>&& buffer, IDState&& state): d_idstate(std::move(state)), d_buffer(std::move(buffer))
+ TCPQuery(PacketBuffer&& buffer, IDState&& state): d_idstate(std::move(state)), d_buffer(std::move(buffer))
{
}
IDState d_idstate;
- std::vector<uint8_t> d_buffer;
+ PacketBuffer d_buffer;
};
class TCPConnectionToBackend;
memset(&d_cleartextDH, 0, sizeof(d_cleartextDH));
}
- TCPResponse(std::vector<uint8_t>&& buffer, IDState&& state, std::shared_ptr<TCPConnectionToBackend> conn): TCPQuery(std::move(buffer), std::move(state)), d_connection(conn)
+ TCPResponse(PacketBuffer&& buffer, IDState&& state, std::shared_ptr<TCPConnectionToBackend> conn): TCPQuery(std::move(buffer), std::move(state)), d_connection(conn)
{
memset(&d_cleartextDH, 0, sizeof(d_cleartextDH));
}
static const uint16_t s_xfrID;
- std::vector<uint8_t> d_responseBuffer;
+ PacketBuffer d_responseBuffer;
std::deque<TCPQuery> d_pendingQueries;
std::unordered_map<uint16_t, TCPQuery> d_pendingResponses;
std::unique_ptr<Socket> d_socket{nullptr};
enum class State { doingHandshake, readingQuerySize, readingQuery, sendingResponse, idle /* in case of XFR, we stop processing queries */ };
std::map<std::shared_ptr<DownstreamState>, std::deque<std::shared_ptr<TCPConnectionToBackend>>> d_activeConnectionsToBackend;
- std::vector<uint8_t> d_buffer;
+ PacketBuffer d_buffer;
std::deque<TCPResponse> d_queuedResponses;
TCPClientThreadData& d_threadData;
TCPResponse d_currentResponse;
}
/* Always called from the main DoH thread */
-static void handleResponse(DOHFrontend& df, st_h2o_req_t* req, uint16_t statusCode, const std::vector<uint8_t>& response, const std::vector<std::pair<std::string, std::string>>& customResponseHeaders, const std::string& contentType, bool addContentType)
+static void handleResponse(DOHFrontend& df, st_h2o_req_t* req, uint16_t statusCode, const PacketBuffer& response, const std::vector<std::pair<std::string, std::string>>& customResponseHeaders, const std::string& contentType, bool addContentType)
{
constexpr int overwrite_if_exists = 1;
constexpr int maybe_token = 1;
/* This executes in the main DoH thread.
We allocate a DOHUnit and send it to dnsdistclient() function in the doh client thread
via a pipe */
-static void doh_dispatch_query(DOHServerConfig* dsc, h2o_handler_t* self, h2o_req_t* req, std::vector<uint8_t>&& query, const ComboAddress& local, const ComboAddress& remote, std::string&& path)
+static void doh_dispatch_query(DOHServerConfig* dsc, h2o_handler_t* self, h2o_req_t* req, PacketBuffer&& query, const ComboAddress& local, const ComboAddress& remote, std::string&& path)
{
try {
/* we only parse it there as a sanity check, we will parse it again later */
else
++dsc->df->d_http1Stats.d_nbQueries;
- std::vector<uint8_t> query;
+ PacketBuffer query;
/* We reserve at least 512 additional bytes to be able to add EDNS, but we also want
at least s_maxPacketCacheEntrySize bytes to be able to fill the answer from the packet cache */
query.reserve(std::max(req->entity.len + 512, s_maxPacketCacheEntrySize));
break;
}
- std::vector<uint8_t> decoded;
+ PacketBuffer decoded;
/* rough estimate so we hopefully don't need a new allocation later */
/* We reserve at least 512 additional bytes to be able to add EDNS, but we also want
}
}
-void DOHUnit::setHTTPResponse(uint16_t statusCode, std::vector<uint8_t>&& body_, const std::string& contentType_)
+void DOHUnit::setHTTPResponse(uint16_t statusCode, PacketBuffer&& body_, const std::string& contentType_)
{
status_code = statusCode;
response = std::move(body_);
--- /dev/null
+../noinitvector.hh
\ No newline at end of file
}
}
- IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite) override
+ IOState tryWrite(PacketBuffer& buffer, size_t& pos, size_t toWrite) override
{
do {
int res = SSL_write(d_conn.get(), reinterpret_cast<const char *>(&buffer.at(pos)), static_cast<int>(toWrite - pos));
return IOState::Done;
}
- IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead) override
+ IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead) override
{
do {
int res = SSL_read(d_conn.get(), reinterpret_cast<char *>(&buffer.at(pos)), static_cast<int>(toRead - pos));
throw std::runtime_error("Error accepting a new connection");
}
- IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite) override
+ IOState tryWrite(PacketBuffer& buffer, size_t& pos, size_t toWrite) override
{
do {
ssize_t res = gnutls_record_send(d_conn.get(), reinterpret_cast<const char *>(&buffer.at(pos)), toWrite - pos);
return IOState::Done;
}
- IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead) override
+ IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead) override
{
do {
ssize_t res = gnutls_record_recv(d_conn.get(), reinterpret_cast<char *>(&buffer.at(pos)), toRead - pos);
uint16_t qclass = QClass::IN;
ComboAddress lc("192.0.2.1:53");
ComboAddress rem("192.0.2.128:42");
- std::vector<uint8_t> packet(sizeof(dnsheader));
+ PacketBuffer packet(sizeof(dnsheader));
bool isTcp = false;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
uint16_t qclass = QClass::IN;
ComboAddress lc("192.0.2.1:53");
ComboAddress rem("192.0.2.128:42");
- std::vector<uint8_t> packet(sizeof(dnsheader));
+ PacketBuffer packet(sizeof(dnsheader));
bool isTcp = false;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
return "";
}
-void DOHUnit::setHTTPResponse(uint16_t statusCode, std::vector<uint8_t>&& body_, const std::string& contentType_)
+void DOHUnit::setHTTPResponse(uint16_t statusCode, PacketBuffer&& body_, const std::string& contentType_)
{
}
#endif /* HAVE_DNS_OVER_HTTPS */
static const ComboAddress lc("127.0.0.1:53");
static const ComboAddress rem("192.0.2.1:42");
static struct timespec queryRealTime;
- static std::vector<uint8_t> packet(sizeof(dnsheader));
+ static PacketBuffer packet(sizeof(dnsheader));
uint16_t qtype = QType::A;
uint16_t qclass = QClass::IN;
uint16_t qclass = QClass::IN;
ComboAddress lc("127.0.0.1:53");
ComboAddress rem("192.0.2.1:42");
- std::vector<uint8_t> packet(sizeof(dnsheader));
+ PacketBuffer packet(sizeof(dnsheader));
bool isTcp = false;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
*/
-DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode)
+template <typename Container> GenericDNSPacketWriter<Container>::GenericDNSPacketWriter(Container& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode)
: d_content(content), d_qname(qname), d_canonic(false), d_lowerCase(false)
{
d_content.clear();
d_rollbackmarker = 0;
}
-dnsheader* DNSPacketWriter::getHeader()
+template <typename Container> dnsheader* GenericDNSPacketWriter<Container>::getHeader()
{
return reinterpret_cast<dnsheader*>(&*d_content.begin());
}
-void DNSPacketWriter::startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, DNSResourceRecord::Place place, bool compress)
+template <typename Container> void GenericDNSPacketWriter<Container>::startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, DNSResourceRecord::Place place, bool compress)
{
d_compress = compress;
commit();
d_sor=d_content.size(); // this will remind us where to stuff the record size
}
-void DNSPacketWriter::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version)
+template <typename Container> void GenericDNSPacketWriter<Container>::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version)
{
uint32_t ttl=0;
}
}
-void DNSPacketWriter::xfr48BitInt(uint64_t val)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfr48BitInt(uint64_t val)
{
unsigned char bytes[6];
uint16_t theLeft = htons((val >> 32)&0xffffU);
}
-void DNSPacketWriter::xfr32BitInt(uint32_t val)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfr32BitInt(uint32_t val)
{
uint32_t rval=htonl(val);
uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
d_content.insert(d_content.end(), ptr, ptr+4);
}
-void DNSPacketWriter::xfr16BitInt(uint16_t val)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfr16BitInt(uint16_t val)
{
uint16_t rval=htons(val);
uint8_t* ptr=reinterpret_cast<uint8_t*>(&rval);
d_content.insert(d_content.end(), ptr, ptr+2);
}
-void DNSPacketWriter::xfr8BitInt(uint8_t val)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfr8BitInt(uint8_t val)
{
d_content.push_back(val);
}
"blah" -> blah
"blah\"blah" -> blah"blah
*/
-void DNSPacketWriter::xfrText(const string& text, bool, bool lenField)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrText(const string& text, bool, bool lenField)
{
if(text.empty()) {
d_content.push_back(0);
}
}
-void DNSPacketWriter::xfrUnquotedText(const string& text, bool lenField)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrUnquotedText(const string& text, bool lenField)
{
if(text.empty()) {
d_content.push_back(0);
static constexpr bool l_verbose=false;
static constexpr uint16_t maxCompressionOffset=16384;
-uint16_t DNSPacketWriter::lookupName(const DNSName& name, uint16_t* matchLen)
+template <typename Container> uint16_t GenericDNSPacketWriter<Container>::lookupName(const DNSName& name, uint16_t* matchLen)
{
// iterate over the written labels, see if we find a match
const auto& raw = name.getStorage();
return bestpos;
}
// this is the absolute hottest function in the pdns recursor
-void DNSPacketWriter::xfrName(const DNSName& name, bool compress, bool)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrName(const DNSName& name, bool compress, bool)
{
if(l_verbose)
cout<<"Wants to write "<<name<<", compress="<<compress<<", canonic="<<d_canonic<<", LC="<<d_lowerCase<<endl;
}
}
-void DNSPacketWriter::xfrBlob(const string& blob, int )
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlob(const string& blob, int )
{
const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
d_content.insert(d_content.end(), ptr, ptr+blob.size());
}
-void DNSPacketWriter::xfrBlobNoSpaces(const string& blob, int )
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrBlobNoSpaces(const string& blob, int )
{
xfrBlob(blob);
}
-void DNSPacketWriter::xfrHexBlob(const string& blob, bool keepReading)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrHexBlob(const string& blob, bool keepReading)
{
xfrBlob(blob);
}
-void DNSPacketWriter::xfrSvcParamKeyVals(const std::set<SvcParam> &kvs)
+template <typename Container> void GenericDNSPacketWriter<Container>::xfrSvcParamKeyVals(const std::set<SvcParam> &kvs)
{
for (auto const ¶m : kvs) {
// Key first!
}
// call __before commit__
-void DNSPacketWriter::getRecordPayload(string& records)
+template <typename Container> void GenericDNSPacketWriter<Container>::getRecordPayload(string& records)
{
records.assign(d_content.begin() + d_sor, d_content.end());
}
-uint32_t DNSPacketWriter::size()
+template <typename Container> uint32_t GenericDNSPacketWriter<Container>::size()
{
return d_content.size();
}
-void DNSPacketWriter::rollback()
+template <typename Container> void GenericDNSPacketWriter<Container>::rollback()
{
d_content.resize(d_rollbackmarker);
d_sor = 0;
}
-void DNSPacketWriter::truncate()
+template <typename Container> void GenericDNSPacketWriter<Container>::truncate()
{
d_content.resize(d_truncatemarker);
dnsheader* dh=reinterpret_cast<dnsheader*>( &*d_content.begin());
dh->ancount = dh->nscount = dh->arcount = 0;
}
-void DNSPacketWriter::commit()
+template <typename Container> void GenericDNSPacketWriter<Container>::commit()
{
if(!d_sor)
return;
}
}
+
+template class GenericDNSPacketWriter<std::vector<uint8_t>>;
+#include "noinitvector.hh"
+template class GenericDNSPacketWriter<PacketBuffer>;
+
+
*/
-class DNSPacketWriter : public boost::noncopyable
+template <typename Container> class GenericDNSPacketWriter : public boost::noncopyable
{
public:
//! Start a DNS Packet in the vector passed, with question qname, qtype and qclass
- DNSPacketWriter(vector<uint8_t>& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0);
+ GenericDNSPacketWriter(Container& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0);
/** Start a new DNS record within this packet for namq, qtype, ttl, class and in the requested place. Note that packets can only be written in natural order -
ANSWER, AUTHORITY, ADDITIONAL */
{
d_lowerCase=val;
}
- vector <uint8_t>& getContent()
+ Container& getContent()
{
return d_content;
}
uint16_t d_sor;
uint16_t d_rollbackmarker; // start of last complete packet, for rollback
- vector <uint8_t>& d_content;
+ Container& d_content;
DNSName d_qname;
uint16_t d_truncatemarker; // end of header, for truncate
bool d_canonic, d_lowerCase, d_compress{false};
};
+using DNSPacketWriter = GenericDNSPacketWriter<std::vector<uint8_t>>;
+
typedef vector<pair<string::size_type, string::size_type> > labelparts_t;
// bool labeltokUnescape(labelparts_t& parts, const DNSName& label);
std::vector<string> segmentDNSText(const string& text); // from dnslabeltext.rl
#pragma once
#include "iputils.hh"
#include "libssl.hh"
+#include "noinitvector.hh"
struct DOHServerConfig;
class DOHResponseMapEntry
{
public:
- DOHResponseMapEntry(const std::string& regex, uint16_t status, const std::vector<uint8_t>& content, const boost::optional<std::vector<std::pair<std::string, std::string>>>& headers): d_regex(regex), d_customHeaders(headers), d_content(content), d_status(status)
+ DOHResponseMapEntry(const std::string& regex, uint16_t status, const PacketBuffer& content, const boost::optional<std::vector<std::pair<std::string, std::string>>>& headers): d_regex(regex), d_customHeaders(headers), d_content(content), d_status(status)
{
if (status >= 400 && !d_content.empty() && d_content.at(d_content.size() -1) != 0) {
// we need to make sure it's null-terminated
return d_status;
}
- const std::vector<uint8_t>& getContent() const
+ const PacketBuffer& getContent() const
{
return d_content;
}
private:
Regex d_regex;
boost::optional<std::vector<std::pair<std::string, std::string>>> d_customHeaders;
- std::vector<uint8_t> d_content;
+ PacketBuffer d_content;
uint16_t d_status;
};
}
std::vector<std::pair<std::string, std::string>> headers;
- std::vector<uint8_t> query;
- std::vector<uint8_t> response;
+ PacketBuffer query;
+ PacketBuffer response;
std::string sni;
std::string path;
std::string scheme;
std::string getHTTPScheme() const;
std::string getHTTPQueryString() const;
std::unordered_map<std::string, std::string> getHTTPHeaders() const;
- void setHTTPResponse(uint16_t statusCode, std::vector<uint8_t>&& body, const std::string& contentType="");
+ void setHTTPResponse(uint16_t statusCode, PacketBuffer&& body, const std::string& contentType="");
};
#endif /* HAVE_DNS_OVER_HTTPS */
uint16_t qtype;
uint16_t qclass;
unsigned int consumed;
- std::vector<uint8_t> vect(data, data+size);
+ PacketBuffer vect(data, data+size);
const DNSName qname(reinterpret_cast<const char*>(data), size, sizeof(dnsheader), false, &qtype, &qclass, &consumed);
pcSkipCookies.getKey(qname.getStorage(), consumed, vect, false);
pcHashCookies.getKey(qname.getStorage(), consumed, vect, false);
--- /dev/null
+#pragma once
+
+#include <memory>
+#include <new>
+#include <utility>
+#include <vector>
+
+// based on boost::core::noinit_adaptor
+// The goal is to avoid initialization of the content of a container,
+// because setting several kB of uint8_t to 0 has a real cost if you
+// do 100k times per second.
+template<class Allocator>
+struct noinit_adaptor: Allocator
+{
+ template<class U>
+ struct rebind {
+ typedef noinit_adaptor<typename std::allocator_traits<Allocator>::template
+ rebind_alloc<U> > other;
+ };
+
+ noinit_adaptor(): Allocator() { }
+
+ template<class U>
+ noinit_adaptor(U&& u) noexcept : Allocator(std::forward<U>(u)) { }
+
+ template<class U>
+ noinit_adaptor(const noinit_adaptor<U>& u) noexcept : Allocator(static_cast<const U&>(u)) { }
+
+ template<class U>
+ void construct(U* p) {
+ ::new((void*)p) U;
+ }
+
+ template<class U, class V, class... Args>
+ void construct(U* p, V&& v, Args&&... args) {
+ ::new((void*)p) U(std::forward<V>(v), std::forward<Args>(args)...);
+ }
+
+ template<class U>
+ void destroy(U* p) {
+ p->~U();
+ }
+};
+
+template<class T, class U>
+inline bool operator==(const noinit_adaptor<T>& lhs,
+ const noinit_adaptor<U>& rhs) noexcept
+{
+ return static_cast<const T&>(lhs) == static_cast<const U&>(rhs);
+}
+
+template<class T, class U>
+inline bool operator!=(const noinit_adaptor<T>& lhs,
+ const noinit_adaptor<U>& rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+template<class Allocator>
+inline noinit_adaptor<Allocator> noinit_adapt(const Allocator& a) noexcept
+{
+ return noinit_adaptor<Allocator>(a);
+}
+
+template<class T> using NoInitVector = std::vector<T, noinit_adaptor<std::allocator<T>>>;
+
+using PacketBuffer = NoInitVector<uint8_t>;
mtasker_context.cc mtasker_context.hh \
namespaces.hh \
negcache.hh negcache.cc \
+ noinitvector.hh \
nsecrecords.cc \
opensslsigners.cc opensslsigners.hh \
packetcache.hh \
--- /dev/null
+../noinitvector.hh
\ No newline at end of file
*/
#include <iostream>
#include "namespaces.hh"
+#include "noinitvector.hh"
#include "misc.hh"
#include "base64.hh"
#include "sodcrypto.hh"
}
template int B64Decode<std::vector<uint8_t>>(const std::string& strInput, std::vector<uint8_t>& strOutput);
+template int B64Decode<PacketBuffer>(const std::string& strInput, PacketBuffer& strOutput);
template int B64Decode<std::string>(const std::string& strInput, std::string& strOutput);
/*
#include "libssl.hh"
#include "misc.hh"
+#include "noinitvector.hh"
enum class IOState { Done, NeedRead, NeedWrite };
virtual IOState tryHandshake() = 0;
virtual size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0) = 0;
virtual size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) = 0;
- virtual IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite) = 0;
- virtual IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead) = 0;
+ virtual IOState tryWrite(PacketBuffer& buffer, size_t& pos, size_t toWrite) = 0;
+ virtual IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead) = 0;
virtual bool hasBufferedData() const = 0;
virtual std::string getServerNameIndication() const = 0;
virtual LibsslTLSVersion getTLSVersion() const = 0;
return Done when toRead bytes have been read, needRead or needWrite if the IO operation
would block.
*/
- IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead)
+ IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead)
{
if (buffer.size() < toRead || pos >= toRead) {
throw std::out_of_range("Calling tryRead() with a too small buffer (" + std::to_string(buffer.size()) + ") for a read of " + std::to_string(toRead - pos) + " bytes starting at " + std::to_string(pos));
return Done when toWrite bytes have been written, needRead or needWrite if the IO operation
would block.
*/
- IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite)
+ IOState tryWrite(PacketBuffer& buffer, size_t& pos, size_t toWrite)
{
if (buffer.size() < toWrite || pos >= toWrite) {
throw std::out_of_range("Calling tryWrite() with a too small buffer (" + std::to_string(buffer.size()) + ") for a write of " + std::to_string(toWrite - pos) + " bytes starting at " + std::to_string(pos));
auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
DNSName name("2.name.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::TXT, QClass::IN, 0);
pw.getHeader()->rd = 0;
std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
BOOST_CHECK_EQUAL(query->isValid(), true);
BOOST_CHECK_EQUAL(query->isEncrypted(), false);
- std::vector<uint8_t> response;
+ PacketBuffer response;
query->getCertificateResponse(now, response);
DNSName name("2.name.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::A, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 0;
std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
DNSName name("2.WRONG.name.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::TXT, QClass::IN, 0);
pw.getHeader()->rd = 0;
std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
DNSName name("www.powerdns.com.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
pw.getHeader()->rd = 1;
size_t requiredSize = plainQuery.size() + sizeof(DNSCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
if (requiredSize < DNSCryptQuery::s_minUDPLength) {
unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
DNSName name("www.powerdns.com.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
pw.getHeader()->rd = 1;
int res = ctx->encryptQuery(plainQuery, /* not enough room */ plainQuery.size(), clientPublicKey, clientPrivateKey, clientNonce, false, std::make_shared<DNSCryptCert>(resolverCert));
unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
DNSName name("www.powerdns.com.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
pw.getHeader()->rd = 1;
size_t requiredSize = plainQuery.size() + sizeof(DNSCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
DNSName name("www.powerdns.com.");
- vector<uint8_t> plainQuery;
- DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
+ PacketBuffer plainQuery;
+ GenericDNSPacketWriter<PacketBuffer> pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
pw.getHeader()->rd = 1;
size_t initialSize = plainQuery.size();
static const uint16_t ECSSourcePrefixV4 = 24;
static const uint16_t ECSSourcePrefixV6 = 56;
-static void validateQuery(const std::vector<uint8_t>& packet, bool hasEdns=true, bool hasXPF=false, uint16_t additionals=0, uint16_t answers=0, uint16_t authorities=0)
+static void validateQuery(const PacketBuffer& packet, bool hasEdns=true, bool hasXPF=false, uint16_t additionals=0, uint16_t answers=0, uint16_t authorities=0)
{
MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
BOOST_CHECK_EQUAL(mdp.d_header.arcount, expectedARCount);
}
-static void validateECS(const std::vector<uint8_t>& packet, const ComboAddress& expected)
+static void validateECS(const PacketBuffer& packet, const ComboAddress& expected)
{
ComboAddress rem("::1");
unsigned int consumed = 0;
uint16_t qtype;
uint16_t qclass;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, &qclass, &consumed);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &rem, const_cast<std::vector<uint8_t>&>(packet), false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &rem, const_cast<PacketBuffer&>(packet), false, nullptr);
BOOST_CHECK(parseEDNSOptions(dq));
BOOST_REQUIRE(dq.ednsOptions != nullptr);
BOOST_CHECK_EQUAL(dq.ednsOptions->size(), 1U);
BOOST_CHECK_EQUAL(expectedOption.substr(EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), std::string(ecsOption->second.values.at(0).content, ecsOption->second.values.at(0).size));
}
-static void validateResponse(const std::vector<uint8_t>& packet, bool hasEdns, uint8_t additionalCount=0)
+static void validateResponse(const PacketBuffer& packet, bool hasEdns, uint8_t additionalCount=0)
{
MOADNSParser mdp(false, reinterpret_cast<const char*>(packet.data()), packet.size());
ComboAddress remote;
DNSName name("www.powerdns.com.");
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
- vector<uint8_t> queryWithXPF;
+ PacketBuffer queryWithXPF;
{
- std::vector<uint8_t> packet = query;
+ PacketBuffer packet = query;
/* large enough packet */
unsigned int consumed = 0;
}
{
- std::vector<uint8_t> packet = query;
+ PacketBuffer packet = query;
/* packet is already too large for the 4096 limit over UDP */
packet.resize(4096);
}
{
- std::vector<uint8_t> packet = query;
+ PacketBuffer packet = query;
/* packet with trailing data (overriding it) */
unsigned int consumed = 0;
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
uint16_t len = query.size();
/* large enough packet */
- std::vector<uint8_t> packet = query;
+ PacketBuffer packet = query;
unsigned int consumed = 0;
uint16_t qtype;
BOOST_CHECK_EQUAL(ecsAdded, true);
validateQuery(packet);
validateECS(packet, remote);
- vector<uint8_t> queryWithEDNS = packet;
+ PacketBuffer queryWithEDNS = packet;
/* not large enough packet */
packet = query;
ComboAddress remote("192.0.2.1");
DNSName name("www.powerdns.com.");
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
auto packet = query;
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.addOpt(512, 0, 0);
pw.commit();
ComboAddress remote("2001:DB8::1");
DNSName name("www.powerdns.com.");
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.addOpt(512, 0, 0);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, ECSSourcePrefixV4);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, ECSSourcePrefixV4);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 32);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
// smaller (less specific so less bits) option
static_assert(8 < ECSSourcePrefixV4, "The ECS scope should be smaller");
ecsOpts.source = Netmask(origRemote, 8);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 8);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.startRecord(DNSName("tsigname."), QType::TSIG, 0, QClass::ANY, DNSResourceRecord::ADDITIONAL, false);
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(DNSName("powerdns.com."), QType::A, 0, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.commit();
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 8);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(DNSName("powerdns.com."), QType::A, 0, QClass::IN, DNSResourceRecord::AUTHORITY, true);
pw.commit();
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 8);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.addOpt(512, 0, 0, opts);
pw.commit();
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 8);
string origECSOption = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOption));
pw.startRecord(DNSName("additional"), QType::A, 0, QClass::IN, DNSResourceRecord::ADDITIONAL, false);
pw.xfr32BitInt(0x01020304);
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(DNSName("additional"), QType::A, 0, QClass::IN, DNSResourceRecord::ADDITIONAL, false);
pw.xfr32BitInt(0x01020304);
string newECSOption;
generateECSOption(remote, newECSOption, remote.sin4.sin_family == AF_INET ? ECSSourcePrefixV4 : ECSSourcePrefixV6);
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(DNSName("tsigname."), QType::TSIG, 0, QClass::ANY, DNSResourceRecord::ADDITIONAL, false);
pw.commit();
BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst) {
DNSName name("www.powerdns.com.");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNS(response, newResponse);
BOOST_CHECK_EQUAL(res, 0);
BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary) {
DNSName name("www.powerdns.com.");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNS(response, newResponse);
BOOST_CHECK_EQUAL(res, 0);
BOOST_AUTO_TEST_CASE(removeEDNSWhenLast) {
DNSName name("www.powerdns.com.");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
pw.addOpt(512, 0, 0);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNS(response, newResponse);
BOOST_CHECK_EQUAL(res, 0);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, ECSSourcePrefixV4);
string origECSOptionStr = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
pw.addOpt(512, 0, 0, opts);
pw.commit();
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
cookiesOpt.client = string("deadbeef");
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
pw.addOpt(512, 0, 0, opts);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
string cookiesOptionStr1 = makeEDNSCookiesOptString(cookiesOpt);
string cookiesOptionStr2 = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr1));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr2));
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, ECSSourcePrefixV4);
string origECSOptionStr = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
pw.addOpt(512, 0, 0, opts);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, ECSSourcePrefixV4);
string origECSOptionStr = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
pw.addOpt(512, 0, 0, opts);
pw.commit();
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNSOption(response, EDNSOptionCode::ECS, newResponse);
BOOST_CHECK_EQUAL(res, 0);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
cookiesOpt.client = string("deadbeef");
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
pw.addOpt(512, 0, 0, opts);
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNSOption(response, EDNSOptionCode::ECS, newResponse);
BOOST_CHECK_EQUAL(res, 0);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr1 = makeEDNSCookiesOptString(cookiesOpt);
string cookiesOptionStr2 = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr1));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr2));
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNSOption(response, EDNSOptionCode::ECS, newResponse);
BOOST_CHECK_EQUAL(res, 0);
DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
- vector<uint8_t> response;
- DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pw(response, name, QType::A, QClass::IN, 0);
pw.getHeader()->qr = 1;
pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
pw.xfr32BitInt(0x01020304);
cookiesOpt.client = string("deadbeef");
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
pw.addOpt(512, 0, 0, opts);
pw.xfr32BitInt(0x01020304);
pw.commit();
- vector<uint8_t> newResponse;
+ PacketBuffer newResponse;
int res = rewriteResponseWithoutEDNSOption(response, EDNSOptionCode::ECS, newResponse);
BOOST_CHECK_EQUAL(res, 0);
validateResponse(newResponse, true, 1);
}
-static DNSQuestion getDNSQuestion(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& realTime, vector<uint8_t>& query)
+static DNSQuestion getDNSQuestion(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& realTime, PacketBuffer& query)
{
return DNSQuestion(&qname, qtype, qclass, &lc, &rem, query, false, &realTime);
}
-static DNSQuestion turnIntoResponse(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& queryRealTime, vector<uint8_t>& query, bool resizeBuffer=true)
+static DNSQuestion turnIntoResponse(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& queryRealTime, PacketBuffer& query, bool resizeBuffer=true)
{
if (resizeBuffer) {
query.resize(4096);
return dq;
}
-static int getZ(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, vector<uint8_t>& query)
+static int getZ(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, PacketBuffer& query)
{
ComboAddress lc("127.0.0.1");
ComboAddress rem("127.0.0.1");
cookiesOpt.client = string("deadbeef");
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
{
/* no EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.commit();
BOOST_CHECK_EQUAL(getZ(qname, qtype, qclass, query), 0);
{
/* truncated EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
pw.commit();
{
/* valid EDNS, no options, DO not set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0);
pw.commit();
{
/* valid EDNS, no options, DO set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
pw.commit();
{
/* valid EDNS, options, DO not set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0, opts);
pw.commit();
{
/* valid EDNS, options, DO set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO, opts);
pw.commit();
cookiesOpt.client = string("deadbeef");
cookiesOpt.server = string("deadbeef");
string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, origECSOptionStr));
ComboAddress lc("127.0.0.1");
{
/* no EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.getHeader()->qr = 1;
pw.getHeader()->rcode = RCode::NXDomain;
pw.commit();
{
/* truncated EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
pw.commit();
{
/* valid EDNS, no options, DO not set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0);
pw.commit();
{
/* valid EDNS, no options, DO set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
pw.commit();
{
/* valid EDNS, options, DO not set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0, opts);
pw.commit();
{
/* valid EDNS, options, DO set */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, EDNS_HEADER_FLAG_DO, opts);
pw.commit();
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(ComboAddress("127.0.0.1"), ECSSourcePrefixV4);
const string ecsOptionStr = makeEDNSSubnetOptsString(ecsOpts);
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
const ComboAddress lc("127.0.0.1");
const ComboAddress rem("127.0.0.1");
{
/* no EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.getHeader()->qr = 1;
pw.getHeader()->rcode = RCode::NXDomain;
pw.commit();
{
/* valid EDNS, no options */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0);
pw.commit();
{
/* valid EDNS, options */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0, opts);
pw.commit();
BOOST_AUTO_TEST_CASE(test_isEDNSOptionInOpt) {
- auto locateEDNSOption = [](const vector<uint8_t>& query, uint16_t code, size_t* optContentStart, uint16_t* optContentLen) {
+ auto locateEDNSOption = [](const PacketBuffer& query, uint16_t code, size_t* optContentStart, uint16_t* optContentLen) {
uint16_t optStart;
size_t optLen;
bool last = false;
const string cookiesOptionStr = makeEDNSCookiesOptString(cookiesOpt);
const size_t sizeOfCookieOption = /* option code */ 2 + /* option length */ 2 + cookiesOpt.client.size() + cookiesOpt.server.size();
/*
- DNSPacketWriter::optvect_t opts;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
{
/* no EDNS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.getHeader()->qr = 1;
pw.getHeader()->rcode = RCode::NXDomain;
pw.commit();
{
/* valid EDNS, no options */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
pw.addOpt(512, 0, 0);
pw.commit();
{
/* valid EDNS, two cookie options but no ECS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
- DNSPacketWriter::optvect_t opts;
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
pw.addOpt(512, 0, 0, opts);
{
/* valid EDNS, two ECS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
- DNSPacketWriter::optvect_t opts;
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
pw.addOpt(512, 0, 0, opts);
{
/* valid EDNS, one ECS between two cookies */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
- DNSPacketWriter::optvect_t opts;
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
opts.push_back(make_pair(EDNSOptionCode::COOKIE, cookiesOptionStr));
{
/* valid EDNS, one 65002 after an ECS */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, qname, qtype, qclass, 0);
- DNSPacketWriter::optvect_t opts;
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, qname, qtype, qclass, 0);
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
opts.push_back(make_pair(EDNSOptionCode::ECS, ecsOptionStr));
opts.push_back(make_pair(65535, cookiesOptionStr));
pw.addOpt(512, 0, 0, opts);
ComboAddress remote;
DNSName name("www.powerdns.com.");
- vector<uint8_t> query;
- vector<uint8_t> queryWithEDNS;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ PacketBuffer queryWithEDNS;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
- DNSPacketWriter pwEDNS(queryWithEDNS, name, QType::A, QClass::IN, 0);
+ GenericDNSPacketWriter<PacketBuffer> pwEDNS(queryWithEDNS, name, QType::A, QClass::IN, 0);
pwEDNS.getHeader()->rd = 1;
pwEDNS.addOpt(1232, 0, 0);
pwEDNS.commit();
{
/* no EDNS and no other additional record */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.commit();
{
/* nothing in additional (so no EDNS) but a record in ANSWER */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(name, QType::A, 60, QClass::IN, DNSResourceRecord::ANSWER);
pw.xfrIP(v4.sin4.sin_addr.s_addr);
{
/* nothing in additional (so no EDNS) but a record in AUTHORITY */
- vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.startRecord(name, QType::A, 60, QClass::IN, DNSResourceRecord::AUTHORITY);
pw.xfrIP(v4.sin4.sin_addr.s_addr);
DNSName a=DNSName(std::to_string(counter))+DNSName(" hello");
BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, a, QType::A, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->ra = 1;
pwR.getHeader()->qr = 1;
size_t delcounter=0;
for(delcounter=0; delcounter < counter/1000; ++delcounter) {
DNSName a=DNSName(std::to_string(delcounter))+DNSName(" hello");
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
boost::optional<Netmask> subnet;
size_t expected=counter-skipped-deleted;
for(; delcounter < counter; ++delcounter) {
DNSName a(DNSName(std::to_string(delcounter))+DNSName(" hello"));
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
boost::optional<Netmask> subnet;
DNSName a = DNSName("servfail");
BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, a, QType::A, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->ra = 0;
pwR.getHeader()->qr = 1;
bool dnssecOK = false;
try {
DNSName name("nodata");
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, name, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, name, QType::A, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->ra = 0;
pwR.getHeader()->qr = 1;
bool dnssecOK = false;
try {
DNSName name("nxdomain");
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, name, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, name, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, name, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, name, QType::A, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->ra = 0;
pwR.getHeader()->qr = 1;
bool dnssecOK = false;
for(unsigned int counter=0; counter < 100000; ++counter) {
DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, a, QType::A, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->ra = 1;
pwR.getHeader()->qr = 1;
ComboAddress remote;
for(unsigned int counter=0; counter < 100000; ++counter) {
DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, a, QType::A, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
/* lookup for a query with a first ECS value,
insert a corresponding response */
{
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, qname, qtype, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, qname, qtype, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
pwQ.getHeader()->id = qid;
- DNSPacketWriter::optvect_t ednsOptions;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t ednsOptions;
EDNSSubnetOpts opt;
opt.source = Netmask("10.0.59.220/32");
ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt)));
BOOST_REQUIRE(subnetOut);
BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, qname, qtype, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, qname, qtype, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->id = qid;
pwR.startRecord(qname, qtype, 100, QClass::IN, DNSResourceRecord::ANSWER);
/* now lookup for the same query with a different ECS value,
we should get the same key (collision) but no match */
{
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, qname, qtype, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, qname, qtype, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
pwQ.getHeader()->id = qid;
- DNSPacketWriter::optvect_t ednsOptions;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t ednsOptions;
EDNSSubnetOpts opt;
opt.source = Netmask("10.0.167.48/32");
ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt)));
/* to be able to compute a new collision if the packet cache hashing code is updated */
{
DNSDistPacketCache pc(10000);
- DNSPacketWriter::optvect_t ednsOptions;
+ GenericDNSPacketWriter<PacketBuffer>::optvect_t ednsOptions;
EDNSSubnetOpts opt;
std::map<uint32_t, Netmask> colMap;
size_t collisions = 0;
for (size_t idxA = 0; idxA < 256; idxA++) {
for (size_t idxB = 0; idxB < 256; idxB++) {
for (size_t idxC = 0; idxC < 256; idxC++) {
- vector<uint8_t> secondQuery;
- DNSPacketWriter pwFQ(secondQuery, qname, QType::AAAA, QClass::IN, 0);
+ PacketBuffer secondQuery;
+ GenericDNSPacketWriter<PacketBuffer> pwFQ(secondQuery, qname, QType::AAAA, QClass::IN, 0);
pwFQ.getHeader()->rd = 1;
pwFQ.getHeader()->qr = false;
pwFQ.getHeader()->id = 0x42;
insert a corresponding response with DO set,
check that it doesn't match without DO, but does with it */
{
- vector<uint8_t> query;
- DNSPacketWriter pwQ(query, qname, qtype, QClass::IN, 0);
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pwQ(query, qname, qtype, QClass::IN, 0);
pwQ.getHeader()->rd = 1;
pwQ.getHeader()->id = qid;
pwQ.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
bool found = PC.get(dq, 0, &key, subnetOut, true);
BOOST_CHECK_EQUAL(found, false);
- vector<uint8_t> response;
- DNSPacketWriter pwR(response, qname, qtype, QClass::IN, 0);
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, qname, qtype, QClass::IN, 0);
pwR.getHeader()->rd = 1;
pwR.getHeader()->id = qid;
pwR.startRecord(qname, qtype, 100, QClass::IN, DNSResourceRecord::ANSWER);