2018-04-10 01:49:37 +07:00
|
|
|
#pragma once
|
2018-04-09 21:43:24 +07:00
|
|
|
#include "dns-storage.hh"
|
2018-04-14 05:12:53 +07:00
|
|
|
#include "record-types.hh"
|
2018-04-15 21:29:17 +07:00
|
|
|
#include <arpa/inet.h>
|
2018-04-12 03:12:57 +07:00
|
|
|
#include <vector>
|
2018-04-09 21:43:24 +07:00
|
|
|
|
2018-04-17 19:19:44 +07:00
|
|
|
/*!
|
|
|
|
@file
|
|
|
|
@brief Defines DNSMessageReader and DNSMessageWriter
|
|
|
|
*/
|
|
|
|
|
2018-04-16 22:09:27 +07:00
|
|
|
//! A class that parses a DNS Message
|
2018-04-13 18:37:17 +07:00
|
|
|
class DNSMessageReader
|
2018-04-09 21:43:24 +07:00
|
|
|
{
|
2018-04-13 18:37:17 +07:00
|
|
|
public:
|
|
|
|
DNSMessageReader(const char* input, uint16_t length);
|
|
|
|
DNSMessageReader(const std::string& str) : DNSMessageReader(str.c_str(), str.size()) {}
|
2018-04-16 22:09:27 +07:00
|
|
|
struct dnsheader dh=dnsheader{}; //!< the DNS header
|
|
|
|
std::vector<uint8_t> payload; //!< The payload
|
|
|
|
uint16_t payloadpos{0}; //!< Current position of processing
|
2018-04-15 21:29:17 +07:00
|
|
|
|
2018-04-16 22:09:27 +07:00
|
|
|
//! Copies the qname and type to you
|
2018-04-13 18:37:17 +07:00
|
|
|
void getQuestion(DNSName& name, DNSType& type) const;
|
2018-04-16 22:09:27 +07:00
|
|
|
//! Returns true if there was an EDNS record, plus copies details
|
2018-04-13 18:37:17 +07:00
|
|
|
bool getEDNS(uint16_t* newsize, bool* doBit) const;
|
2018-04-16 05:14:18 +07:00
|
|
|
|
2018-04-17 19:19:44 +07:00
|
|
|
//! Puts the next RR in content, unless at 'end of message', in which case it returns false
|
2018-04-16 05:14:18 +07:00
|
|
|
bool getRR(DNSSection& section, DNSName& name, DNSType& type, uint32_t& ttl, std::unique_ptr<RRGen>& content);
|
2018-04-17 17:32:56 +07:00
|
|
|
void skipRRs(int n); //!< Skip over n RRs
|
2018-04-16 05:14:18 +07:00
|
|
|
|
2018-04-13 22:39:44 +07:00
|
|
|
uint8_t d_ednsVersion{0};
|
2018-04-16 05:14:18 +07:00
|
|
|
|
2018-04-17 19:19:44 +07:00
|
|
|
void xfrName(DNSName& ret, uint16_t* pos=0); //!< put the next name in ret, or copy it from pos
|
|
|
|
//! Convenience form of xfrName that returns its result
|
2018-04-16 05:14:18 +07:00
|
|
|
DNSName getName(uint16_t* pos=0) { DNSName res; xfrName(res, pos); return res;}
|
2018-04-17 19:19:44 +07:00
|
|
|
//! Gets the next 8 bit unsigned integer from the message, or the one from 'pos'
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt8(uint8_t&res, uint16_t* pos = 0)
|
2018-04-15 21:29:17 +07:00
|
|
|
{
|
2018-04-16 05:14:18 +07:00
|
|
|
if(!pos) pos = &payloadpos;
|
|
|
|
res=payload.at((*pos)++);
|
2018-04-15 21:29:17 +07:00
|
|
|
}
|
2018-04-17 19:19:44 +07:00
|
|
|
//! Convenience form that returns the next 8 bit integer, or from pos
|
|
|
|
uint8_t getUInt8(uint16_t* pos=0)
|
2018-04-16 05:14:18 +07:00
|
|
|
{ uint8_t ret; xfrUInt8(ret, pos); return ret; }
|
2018-04-17 19:19:44 +07:00
|
|
|
|
|
|
|
//! Gets the next 16 bit unsigned integer from the message
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt16(uint16_t& res)
|
2018-04-15 21:29:17 +07:00
|
|
|
{
|
2018-04-16 05:14:18 +07:00
|
|
|
memcpy(&res, &payload.at(payloadpos+1)-1, 2);
|
2018-04-15 21:29:17 +07:00
|
|
|
payloadpos+=2;
|
2018-04-16 05:14:18 +07:00
|
|
|
res=htons(res);
|
2018-04-15 21:29:17 +07:00
|
|
|
}
|
2018-04-17 19:19:44 +07:00
|
|
|
//! Convenience form that returns the next 16 bit integer
|
2018-04-16 05:14:18 +07:00
|
|
|
uint16_t getUInt16()
|
|
|
|
{ uint16_t ret; xfrUInt16(ret); return ret; }
|
2018-04-17 19:19:44 +07:00
|
|
|
|
|
|
|
//! Gets the next 32 bit unsigned integer from the message
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt32(uint32_t& res)
|
2018-04-15 21:29:17 +07:00
|
|
|
{
|
2018-04-16 05:14:18 +07:00
|
|
|
memcpy(&res, &payload.at(payloadpos+3)-3, 4);
|
|
|
|
payloadpos+=4;
|
|
|
|
res=ntohl(res);
|
|
|
|
}
|
2018-04-17 19:19:44 +07:00
|
|
|
|
|
|
|
//! Gets the next size bytes from the message, of from pos
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrBlob(std::string& blob, int size, uint16_t* pos = 0)
|
|
|
|
{
|
|
|
|
if(!pos) pos = &payloadpos;
|
|
|
|
if(!size) {
|
|
|
|
blob.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
blob.assign(&payload.at(*pos), &payload.at(*pos+size-1)+1);
|
|
|
|
(*pos) += size;
|
2018-04-15 21:29:17 +07:00
|
|
|
}
|
|
|
|
|
2018-04-17 19:19:44 +07:00
|
|
|
//! Convenience function that returns next size bytes of the message, or from pos
|
2018-04-16 05:14:18 +07:00
|
|
|
std::string getBlob(int size, uint16_t* pos = 0)
|
|
|
|
{
|
|
|
|
std::string res;
|
|
|
|
xfrBlob(res, size, pos);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-04-13 18:37:17 +07:00
|
|
|
DNSName d_qname;
|
2018-04-16 05:14:18 +07:00
|
|
|
DNSType d_qtype{(DNSType)0};
|
|
|
|
DNSClass d_qclass{(DNSClass)0};
|
2018-04-13 18:37:17 +07:00
|
|
|
uint16_t d_bufsize;
|
2018-04-13 22:39:44 +07:00
|
|
|
bool d_doBit{false};
|
|
|
|
|
|
|
|
bool d_haveEDNS{false};
|
2018-04-09 21:43:24 +07:00
|
|
|
};
|
|
|
|
|
2018-04-16 22:09:27 +07:00
|
|
|
//! A DNS Message writer
|
2018-04-13 20:23:00 +07:00
|
|
|
class DNSMessageWriter
|
2018-04-09 21:43:24 +07:00
|
|
|
{
|
2018-04-13 20:23:00 +07:00
|
|
|
public:
|
2018-04-12 21:29:59 +07:00
|
|
|
struct dnsheader dh=dnsheader{};
|
|
|
|
std::vector<uint8_t> payload;
|
|
|
|
uint16_t payloadpos=0;
|
2018-04-13 20:23:00 +07:00
|
|
|
DNSName d_qname;
|
|
|
|
DNSType d_qtype;
|
|
|
|
DNSClass d_qclass;
|
|
|
|
bool haveEDNS{false};
|
|
|
|
bool d_doBit;
|
2018-04-15 01:16:56 +07:00
|
|
|
bool d_nocompress{false}; // if set, never compress. For AXFR/IXFR
|
2018-04-13 22:39:44 +07:00
|
|
|
RCode d_ercode{(RCode)0};
|
2018-04-12 21:29:59 +07:00
|
|
|
|
2018-04-13 20:23:00 +07:00
|
|
|
DNSMessageWriter(const DNSName& name, DNSType type, int maxsize=500);
|
2018-04-14 20:48:01 +07:00
|
|
|
~DNSMessageWriter();
|
2018-04-14 05:12:53 +07:00
|
|
|
DNSMessageWriter(const DNSMessageWriter&) = delete;
|
|
|
|
DNSMessageWriter& operator=(const DNSMessageWriter&) = delete;
|
2018-04-13 20:23:00 +07:00
|
|
|
void clearRRs();
|
2018-04-12 21:31:43 +07:00
|
|
|
void putRR(DNSSection section, const DNSName& name, DNSType type, uint32_t ttl, const std::unique_ptr<RRGen>& rr);
|
2018-04-13 22:39:44 +07:00
|
|
|
void setEDNS(uint16_t bufsize, bool doBit, RCode ercode = (RCode)0);
|
2018-04-14 05:12:53 +07:00
|
|
|
std::string serialize();
|
2018-04-09 21:43:24 +07:00
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt8(uint8_t val)
|
2018-04-12 03:12:57 +07:00
|
|
|
{
|
|
|
|
payload.at(payloadpos++)=val;
|
|
|
|
}
|
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
uint16_t xfrUInt16(uint16_t val)
|
2018-04-12 03:12:57 +07:00
|
|
|
{
|
|
|
|
val = htons(val);
|
|
|
|
memcpy(&payload.at(payloadpos+2)-2, &val, 2);
|
|
|
|
payloadpos+=2;
|
|
|
|
return payloadpos - 2;
|
|
|
|
}
|
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt16At(uint16_t pos, uint16_t val)
|
2018-04-12 03:12:57 +07:00
|
|
|
{
|
|
|
|
val = htons(val);
|
|
|
|
memcpy(&payload.at(pos+2)-2, &val, 2);
|
|
|
|
}
|
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrUInt32(uint32_t val)
|
2018-04-09 21:43:24 +07:00
|
|
|
{
|
2018-04-12 03:12:57 +07:00
|
|
|
val = htonl(val);
|
|
|
|
memcpy(&payload.at(payloadpos+sizeof(val)) - sizeof(val), &val, sizeof(val));
|
|
|
|
payloadpos += sizeof(val);
|
2018-04-09 21:43:24 +07:00
|
|
|
}
|
2018-04-12 03:12:57 +07:00
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrBlob(const std::string& blob)
|
2018-04-12 03:12:57 +07:00
|
|
|
{
|
|
|
|
memcpy(&payload.at(payloadpos+blob.size()) - blob.size(), blob.c_str(), blob.size());
|
|
|
|
payloadpos += blob.size();;
|
|
|
|
}
|
|
|
|
|
2018-04-16 05:14:18 +07:00
|
|
|
void xfrBlob(const unsigned char* blob, int size)
|
2018-04-12 03:12:57 +07:00
|
|
|
{
|
|
|
|
memcpy(&payload.at(payloadpos+size) - size, blob, size);
|
|
|
|
payloadpos += size;
|
|
|
|
}
|
2018-04-16 05:14:18 +07:00
|
|
|
|
|
|
|
void xfrName(const DNSName& name, bool compress=true);
|
2018-04-13 20:23:00 +07:00
|
|
|
private:
|
2018-04-14 20:48:01 +07:00
|
|
|
std::unique_ptr<DNSNode> d_comptree;
|
2018-04-13 22:39:44 +07:00
|
|
|
void putEDNS(uint16_t bufsize, RCode ercode, bool doBit);
|
2018-04-17 17:32:56 +07:00
|
|
|
bool d_serialized{false}; // needed to make serialize() idempotent
|
2018-04-12 03:12:57 +07:00
|
|
|
};
|
|
|
|
|