mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code
This commit is contained in:
194
include/dns.h
194
include/dns.h
@@ -121,30 +121,117 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Struct that represent DNS queries.
|
||||
*/
|
||||
struct Query {
|
||||
std::string name;
|
||||
uint16_t type, qclass;
|
||||
class Query {
|
||||
public:
|
||||
/**
|
||||
* \brief Constructs a DNS query.
|
||||
*
|
||||
* \param nm The name of the domain being resolved.
|
||||
* \param tp The query type.
|
||||
* \param cl The query class.
|
||||
*/
|
||||
Query(const std::string &nm, QueryType tp, QueryClass cl)
|
||||
: name_(nm), type_(tp), qclass_(cl) {}
|
||||
|
||||
Query(const std::string &nm, uint16_t t, uint16_t c) :
|
||||
name(nm), type(t), qclass(c) {}
|
||||
Query() {}
|
||||
/**
|
||||
* \brief Default constructs this Query.
|
||||
*/
|
||||
Query() : type_(), qclass_() {}
|
||||
|
||||
/**
|
||||
* \brief Setter for the name field.
|
||||
*
|
||||
* \param nm The name to be set.
|
||||
*/
|
||||
void dname(const std::string &nm) {
|
||||
name_ = nm;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the query type field.
|
||||
*
|
||||
* \param tp The query type to be set.
|
||||
*/
|
||||
void type(QueryType tp) {
|
||||
type_ = tp;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the query class field.
|
||||
*
|
||||
* \param cl The query class to be set.
|
||||
*/
|
||||
void query_class(QueryClass cl) {
|
||||
qclass_ = cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the name field.
|
||||
*/
|
||||
const std::string &dname() const { return name_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the query type field.
|
||||
*/
|
||||
QueryType type() const { return type_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the query class field.
|
||||
*/
|
||||
QueryClass query_class() const { return qclass_; }
|
||||
private:
|
||||
std::string name_;
|
||||
QueryType type_;
|
||||
QueryClass qclass_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Struct that represent DNS resource records.
|
||||
*/
|
||||
struct Resource {
|
||||
std::string dname, addr;
|
||||
uint16_t type, qclass;
|
||||
uint32_t ttl;
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
Resource(const std::string &nm, const std::string &ad,
|
||||
uint16_t t, uint16_t c, uint32_t tt) :
|
||||
dname(nm), addr(ad), type(t), qclass(c), ttl(tt) {}
|
||||
uint16_t t, uint16_t c, uint32_t tt)
|
||||
: dname_(nm), addr_(ad), type_(t), qclass_(c), ttl_(tt) {}
|
||||
|
||||
Resource() : type_(), qclass_(), ttl_() {}
|
||||
|
||||
/**
|
||||
* \brief Getter for the dname field.
|
||||
*
|
||||
* This returns the domain name for which this record
|
||||
* provides an answer.
|
||||
*/
|
||||
const std::string &dname() const { return dname_; }
|
||||
|
||||
/**
|
||||
* Getter for the type field.
|
||||
*/
|
||||
const std::string &data() const { return addr_; }
|
||||
|
||||
/**
|
||||
* Getter for the query type field.
|
||||
*/
|
||||
uint16_t type() const { return type_; }
|
||||
|
||||
/**
|
||||
* Getter for the query class field.
|
||||
*/
|
||||
uint16_t query_class() const { return qclass_; }
|
||||
|
||||
/**
|
||||
* Getter for the type field.
|
||||
*/
|
||||
uint32_t ttl() const { return ttl_; }
|
||||
private:
|
||||
std::string dname_, addr_;
|
||||
uint16_t type_, qclass_;
|
||||
uint32_t ttl_;
|
||||
};
|
||||
|
||||
typedef std::list<Query> queries_type;
|
||||
typedef std::list<Resource> resources_type;
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
@@ -154,9 +241,7 @@ namespace Tins {
|
||||
DNS();
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates a DNS object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as
|
||||
* children of this one.
|
||||
* \brief Constructor which creates a DNS object from a buffer.
|
||||
* \param buffer The buffer from which this PDU will be
|
||||
* constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
@@ -253,28 +338,28 @@ namespace Tins {
|
||||
*
|
||||
* \return uint16_t containing the value of the questions field.
|
||||
*/
|
||||
uint16_t questions() const { return Endian::be_to_host(dns.questions); }
|
||||
uint16_t questions_count() const { return Endian::be_to_host(dns.questions); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the answers field.
|
||||
*
|
||||
* \return uint16_t containing the value of the answers field.
|
||||
*/
|
||||
uint16_t answers() const { return Endian::be_to_host(dns.answers); }
|
||||
uint16_t answers_count() const { return Endian::be_to_host(dns.answers); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the authority field.
|
||||
*
|
||||
* \return uint16_t containing the value of the authority field.
|
||||
*/
|
||||
uint16_t authority() const { return Endian::be_to_host(dns.authority); }
|
||||
uint16_t authority_count() const { return Endian::be_to_host(dns.authority); }
|
||||
|
||||
/**
|
||||
* \brief Setter for the additional field.
|
||||
*
|
||||
* \return uint16_t containing the value of the additional field.
|
||||
*/
|
||||
uint16_t additional() const { return Endian::be_to_host(dns.additional); }
|
||||
uint16_t additional_count() const { return Endian::be_to_host(dns.additional); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
@@ -373,14 +458,6 @@ namespace Tins {
|
||||
void rcode(uint8_t new_rcode);
|
||||
|
||||
// Methods
|
||||
/**
|
||||
* \brief Add a query to perform.
|
||||
*
|
||||
* \param name The name to be resolved.
|
||||
* \param type The type of this query.
|
||||
* \param qclass The class of this query.
|
||||
*/
|
||||
void add_query(const std::string &name, QueryType type, QueryClass qclass);
|
||||
|
||||
/**
|
||||
* \brief Add a query to perform.
|
||||
@@ -398,8 +475,8 @@ namespace Tins {
|
||||
* \param ttl The time-to-live of this answer.
|
||||
* \param ip The ip address of the resolved name.
|
||||
*/
|
||||
void add_answer(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, IPv4Address ip);
|
||||
void add_answer(const std::string &name,
|
||||
const DNSResourceRecord::info &info, address_type ip);
|
||||
|
||||
/**
|
||||
* \brief Add a query response.
|
||||
@@ -410,8 +487,8 @@ namespace Tins {
|
||||
* \param ttl The time-to-live of this answer.
|
||||
* \param dname The domain of the resolved name.
|
||||
*/
|
||||
void add_answer(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, const std::string &dname);
|
||||
void add_answer(const std::string &name,
|
||||
const DNSResourceRecord::info &info, const std::string &dname);
|
||||
|
||||
/**
|
||||
* \brief Add a query response.
|
||||
@@ -423,8 +500,8 @@ namespace Tins {
|
||||
* \param data The data of this option.
|
||||
* \param sz The size of the data.
|
||||
*/
|
||||
void add_answer(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, const uint8_t *data, uint32_t sz);
|
||||
void add_answer(const std::string &name,
|
||||
const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz);
|
||||
|
||||
/**
|
||||
* \brief Add an authority record.
|
||||
@@ -436,8 +513,8 @@ namespace Tins {
|
||||
* \param data The data of this option.
|
||||
* \param sz The size of the data.
|
||||
*/
|
||||
void add_authority(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, const uint8_t *data, uint32_t sz);
|
||||
void add_authority(const std::string &name,
|
||||
const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz);
|
||||
|
||||
/**
|
||||
* \brief Add an additional record.
|
||||
@@ -448,8 +525,8 @@ namespace Tins {
|
||||
* \param ttl The time-to-live of this record.
|
||||
* \param ip The ip address of the resolved name.
|
||||
*/
|
||||
void add_additional(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, uint32_t ip);
|
||||
void add_additional(const std::string &name,
|
||||
const DNSResourceRecord::info &info, uint32_t ip);
|
||||
|
||||
|
||||
/**
|
||||
@@ -457,14 +534,14 @@ namespace Tins {
|
||||
* \return std::list<Query> containing the queries in this
|
||||
* record.
|
||||
*/
|
||||
queries_type dns_queries() const;
|
||||
queries_type queries() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for this PDU's DNS answers
|
||||
* \return std::list<Resource> containing the answers in this
|
||||
* record.
|
||||
*/
|
||||
resources_type dns_answers();
|
||||
resources_type answers() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
@@ -472,6 +549,17 @@ namespace Tins {
|
||||
DNS *clone() const {
|
||||
return new DNS(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a resource record information
|
||||
*
|
||||
* \param type The type of the query.
|
||||
* \param qclass The class of the query.
|
||||
* \param ttl The time-to-live of the query.
|
||||
*/
|
||||
static DNSResourceRecord::info make_info(QueryType type, QueryClass qclass, uint32_t ttl) {
|
||||
return DNSResourceRecord::info((uint16_t)type, (uint16_t)qclass, ttl);
|
||||
}
|
||||
private:
|
||||
struct dnshdr {
|
||||
uint16_t id;
|
||||
@@ -516,23 +604,23 @@ namespace Tins {
|
||||
void unparse_domain_name(const std::string &dn, std::string &out) const;
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
uint8_t *serialize_list(const ResourcesType &lst, uint8_t *buffer) const;
|
||||
void compose_name(const uint8_t *ptr, uint32_t sz, std::string &out);
|
||||
void convert_resources(const ResourcesType &lst, std::list<Resource> &res);
|
||||
DNSResourceRecord make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, uint32_t ip);
|
||||
DNSResourceRecord make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, const std::string &dname);
|
||||
DNSResourceRecord make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, const uint8_t *ptr, uint32_t len);
|
||||
void add_suffix(uint32_t index, const uint8_t *data, uint32_t sz);
|
||||
uint32_t build_suffix_map(uint32_t index, const ResourcesType &lst);
|
||||
uint32_t build_suffix_map(uint32_t index, const QueriesType &lst);
|
||||
void build_suffix_map();
|
||||
bool contains_dname(uint16_t type);
|
||||
void compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const;
|
||||
void convert_resources(const ResourcesType &lst, std::list<Resource> &res) const;
|
||||
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, uint32_t ip);
|
||||
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, const std::string &dname);
|
||||
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, const uint8_t *ptr, uint32_t len);
|
||||
void add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) const;
|
||||
uint32_t build_suffix_map(uint32_t index, const ResourcesType &lst) const;
|
||||
uint32_t build_suffix_map(uint32_t index, const QueriesType &lst) const;
|
||||
void build_suffix_map() const ;
|
||||
static bool contains_dname(uint16_t type);
|
||||
|
||||
dnshdr dns;
|
||||
uint32_t extra_size;
|
||||
std::list<Query> queries;
|
||||
std::list<Query> queries_;
|
||||
ResourcesType ans, arity, addit;
|
||||
SuffixMap suffixes;
|
||||
SuffixIndices suffix_indices;
|
||||
mutable SuffixMap suffixes;
|
||||
mutable SuffixIndices suffix_indices;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -37,9 +37,14 @@ public:
|
||||
/**
|
||||
* \brief The type used to store resource records' information.
|
||||
*/
|
||||
struct Info {
|
||||
struct info {
|
||||
uint16_t type, qclass;
|
||||
uint32_t ttl;
|
||||
|
||||
info(uint16_t tp, uint16_t qc, uint32_t tm)
|
||||
: type(tp), qclass(qc), ttl(tm) { }
|
||||
|
||||
info() : type(), qclass(), ttl() {}
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
@@ -143,14 +148,14 @@ public:
|
||||
/**
|
||||
* \brief Returns a reference to the info field.
|
||||
*/
|
||||
Info &info() {
|
||||
info &information() {
|
||||
return info_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns a const reference to the info field.
|
||||
*/
|
||||
const Info &info() const {
|
||||
const info &information() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
@@ -165,7 +170,7 @@ private:
|
||||
DNSRRImpl *clone_impl() const;
|
||||
size_t impl_size() const;
|
||||
|
||||
Info info_;
|
||||
info info_;
|
||||
std::vector<uint8_t> data;
|
||||
DNSRRImpl *impl;
|
||||
};
|
||||
|
||||
160
src/dns.cpp
160
src/dns.cpp
@@ -40,7 +40,7 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
|
||||
throw std::runtime_error("Not enough size for a DNS header in the buffer.");
|
||||
std::memcpy(&dns, buffer, sizeof(dnshdr));
|
||||
const uint8_t *end(buffer + total_sz);
|
||||
uint16_t nquestions(questions());
|
||||
uint16_t nquestions(questions_count());
|
||||
buffer += sizeof(dnshdr);
|
||||
total_sz -= sizeof(dnshdr);
|
||||
for(uint16_t i(0); i < nquestions; ++i) {
|
||||
@@ -50,19 +50,19 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
|
||||
Query query;
|
||||
if((ptr + (sizeof(uint16_t) * 2)) >= end)
|
||||
throw std::runtime_error("Not enough size for a given query.");
|
||||
query.name = string(buffer, ptr);
|
||||
query.dname(string(buffer, ptr));
|
||||
ptr++;
|
||||
const uint16_t *opt_ptr = reinterpret_cast<const uint16_t*>(ptr);
|
||||
query.type = *(opt_ptr++);
|
||||
query.qclass = *(opt_ptr++);
|
||||
queries.push_back(query);
|
||||
query.type((QueryType)*(opt_ptr++));
|
||||
query.query_class((QueryClass)*(opt_ptr++));
|
||||
queries_.push_back(query);
|
||||
total_sz -= reinterpret_cast<const uint8_t*>(opt_ptr) - buffer;
|
||||
extra_size += reinterpret_cast<const uint8_t*>(opt_ptr) - buffer;
|
||||
buffer = reinterpret_cast<const uint8_t*>(opt_ptr);
|
||||
}
|
||||
buffer = build_resource_list(ans, buffer, total_sz, answers());
|
||||
buffer = build_resource_list(arity, buffer, total_sz, authority());
|
||||
build_resource_list(addit, buffer, total_sz, additional());
|
||||
buffer = build_resource_list(ans, buffer, total_sz, answers_count());
|
||||
buffer = build_resource_list(arity, buffer, total_sz, authority_count());
|
||||
build_resource_list(addit, buffer, total_sz, additional_count());
|
||||
}
|
||||
|
||||
const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr, uint32_t &sz, uint16_t nrecs) {
|
||||
@@ -135,68 +135,73 @@ bool DNS::contains_dname(uint16_t type) {
|
||||
type == PTR || type == NS;
|
||||
}
|
||||
|
||||
void DNS::add_query(const string &name, QueryType type, QueryClass qclass) {
|
||||
void DNS::add_query(const Query &query) {
|
||||
string new_str;
|
||||
parse_domain_name(name, new_str);
|
||||
parse_domain_name(query.dname(), new_str);
|
||||
|
||||
queries.push_back(
|
||||
Query(new_str,
|
||||
Endian::host_to_be<uint16_t>(type),
|
||||
Endian::host_to_be<uint16_t>(qclass))
|
||||
queries_.push_back(
|
||||
Query(
|
||||
new_str,
|
||||
(QueryType)Endian::host_to_be<uint16_t>(query.type()),
|
||||
(QueryClass)Endian::host_to_be<uint16_t>(query.query_class())
|
||||
)
|
||||
);
|
||||
extra_size += new_str.size() + 1 + (sizeof(uint16_t) << 1);
|
||||
dns.questions = Endian::host_to_be<uint16_t>(queries.size());
|
||||
dns.questions = Endian::host_to_be<uint16_t>(queries_.size());
|
||||
}
|
||||
|
||||
void DNS::add_query(const Query &query) {
|
||||
add_query(
|
||||
query.name,
|
||||
static_cast<QueryType>(query.type),
|
||||
static_cast<QueryClass>(query.qclass)
|
||||
);
|
||||
}
|
||||
|
||||
void DNS::add_answer(const string &name, QueryType type, QueryClass qclass, uint32_t ttl, IPv4Address ip) {
|
||||
ans.push_back(make_record(name, type, qclass, ttl, Endian::host_to_be((uint32_t)ip)));
|
||||
void DNS::add_answer(const string &name, const DNSResourceRecord::info &info,
|
||||
address_type ip)
|
||||
{
|
||||
ans.push_back(make_record(name, info, Endian::host_to_be((uint32_t)ip)));
|
||||
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
|
||||
}
|
||||
|
||||
void DNS::add_answer(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, const std::string &dname) {
|
||||
void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info,
|
||||
const std::string &dname)
|
||||
{
|
||||
string new_str;
|
||||
parse_domain_name(dname, new_str);
|
||||
DNSResourceRecord res = make_record(name, type, qclass, ttl, new_str);
|
||||
DNSResourceRecord res = make_record(name, info, new_str);
|
||||
ans.push_back(res);
|
||||
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
|
||||
}
|
||||
|
||||
void DNS::add_answer(const std::string &name, QueryType type, QueryClass qclass,
|
||||
uint32_t ttl, const uint8_t *data, uint32_t sz) {
|
||||
ans.push_back(make_record(name, type, qclass, ttl, data, sz));
|
||||
void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info,
|
||||
const uint8_t *data, uint32_t sz)
|
||||
{
|
||||
ans.push_back(make_record(name, info, data, sz));
|
||||
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
|
||||
}
|
||||
|
||||
void DNS::add_authority(const string &name, QueryType type,
|
||||
QueryClass qclass, uint32_t ttl, const uint8_t *data, uint32_t sz) {
|
||||
arity.push_back(make_record(name, type, qclass, ttl, data, sz));
|
||||
void DNS::add_authority(const string &name, const DNSResourceRecord::info &info,
|
||||
const uint8_t *data, uint32_t sz)
|
||||
{
|
||||
arity.push_back(make_record(name, info, data, sz));
|
||||
dns.authority = Endian::host_to_be<uint16_t>(arity.size());
|
||||
}
|
||||
|
||||
void DNS::add_additional(const string &name, QueryType type, QueryClass qclass, uint32_t ttl, uint32_t ip) {
|
||||
addit.push_back(make_record(name, type, qclass, ttl, ip));
|
||||
void DNS::add_additional(const string &name, const DNSResourceRecord::info &info,
|
||||
uint32_t ip)
|
||||
{
|
||||
addit.push_back(make_record(name, info, ip));
|
||||
dns.additional = Endian::host_to_be<uint16_t>(addit.size());
|
||||
}
|
||||
|
||||
DNSResourceRecord DNS::make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, uint32_t ip) {
|
||||
DNSResourceRecord DNS::make_record(const std::string &name, const DNSResourceRecord::info &info, uint32_t ip) {
|
||||
ip = Endian::host_to_be(ip);
|
||||
return make_record(name, type, qclass, ttl, reinterpret_cast<uint8_t*>(&ip), sizeof(ip));
|
||||
return make_record(name, info, reinterpret_cast<uint8_t*>(&ip), sizeof(ip));
|
||||
}
|
||||
|
||||
DNSResourceRecord DNS::make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, const std::string &dname) {
|
||||
return make_record(name, type, qclass, ttl, reinterpret_cast<const uint8_t*>(dname.c_str()), dname.size() + 1);
|
||||
DNSResourceRecord DNS::make_record(const std::string &name,
|
||||
const DNSResourceRecord::info &info, const std::string &dname)
|
||||
{
|
||||
return make_record(name, info, reinterpret_cast<const uint8_t*>(dname.c_str()), dname.size() + 1);
|
||||
}
|
||||
|
||||
DNSResourceRecord DNS::make_record(const std::string &name, QueryType type, QueryClass qclass, uint32_t ttl, const uint8_t *ptr, uint32_t len) {
|
||||
DNSResourceRecord DNS::make_record(const std::string &name,
|
||||
const DNSResourceRecord::info &info, const uint8_t *ptr, uint32_t len)
|
||||
{
|
||||
string nm;
|
||||
parse_domain_name(name, nm);
|
||||
uint16_t index = find_domain_name(nm);
|
||||
@@ -205,19 +210,19 @@ DNSResourceRecord DNS::make_record(const std::string &name, QueryType type, Quer
|
||||
res = make_offseted_record(Endian::host_to_be(index), ptr, len);
|
||||
else
|
||||
res = make_named_record(nm, ptr, len);
|
||||
res.info().type = Endian::host_to_be<uint16_t>(type);
|
||||
res.info().qclass = Endian::host_to_be<uint16_t>(qclass);
|
||||
res.info().ttl = Endian::host_to_be(ttl);
|
||||
res.information().type = Endian::host_to_be<uint16_t>(info.type);
|
||||
res.information().qclass = Endian::host_to_be<uint16_t>(info.qclass);
|
||||
res.information().ttl = Endian::host_to_be(info.ttl);
|
||||
extra_size += res.size();
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t DNS::find_domain_name(const std::string &dname) {
|
||||
uint16_t index(sizeof(dnshdr));
|
||||
list<Query>::const_iterator it(queries.begin());
|
||||
for(; it != queries.end() && it->name != dname; ++it)
|
||||
index += it->name.size() + 1 + (sizeof(uint16_t) << 1);
|
||||
if(it != queries.end() ||
|
||||
list<Query>::const_iterator it(queries_.begin());
|
||||
for(; it != queries_.end() && it->dname() != dname; ++it)
|
||||
index += it->dname().size() + 1 + (sizeof(uint16_t) << 1);
|
||||
if(it != queries_.end() ||
|
||||
find_domain_name(dname, ans, index) ||
|
||||
find_domain_name(dname, arity, index) ||
|
||||
find_domain_name(dname, addit, index))
|
||||
@@ -271,12 +276,13 @@ void DNS::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *par
|
||||
assert(total_sz >= sizeof(dns) + extra_size);
|
||||
std::memcpy(buffer, &dns, sizeof(dns));
|
||||
buffer += sizeof(dns);
|
||||
for(list<Query>::const_iterator it(queries.begin()); it != queries.end(); ++it) {
|
||||
std::memcpy(buffer, it->name.c_str(), it->name.size() + 1);
|
||||
buffer += it->name.size() + 1;
|
||||
*((uint16_t*)buffer) = it->type;
|
||||
for(list<Query>::const_iterator it(queries_.begin()); it != queries_.end(); ++it) {
|
||||
std::copy(it->dname().begin(), it->dname().end(), buffer);
|
||||
buffer += it->dname().size();
|
||||
*buffer++ = 0;
|
||||
*((uint16_t*)buffer) = it->type();
|
||||
buffer += sizeof(uint16_t);
|
||||
*((uint16_t*)buffer) = it->qclass;
|
||||
*((uint16_t*)buffer) = it->query_class();
|
||||
buffer += sizeof(uint16_t);
|
||||
}
|
||||
buffer = serialize_list(ans, buffer);
|
||||
@@ -290,7 +296,7 @@ uint8_t *DNS::serialize_list(const ResourcesType &lst, uint8_t *buffer) const {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void DNS::add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) {
|
||||
void DNS::add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) const {
|
||||
uint32_t i(0), suff_sz(data[0]);
|
||||
SuffixMap::iterator it;
|
||||
while((i + suff_sz + 1 <= sz || (suff_sz == 0xc0 && i + 1 < sz)) && suff_sz) {
|
||||
@@ -309,7 +315,7 @@ void DNS::add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DNS::build_suffix_map(uint32_t index, const ResourcesType &lst) {
|
||||
uint32_t DNS::build_suffix_map(uint32_t index, const ResourcesType &lst) const {
|
||||
const string *str;
|
||||
for(ResourcesType::const_iterator it(lst.begin()); it != lst.end(); ++it) {
|
||||
str = it->dname();
|
||||
@@ -319,38 +325,38 @@ uint32_t DNS::build_suffix_map(uint32_t index, const ResourcesType &lst) {
|
||||
}
|
||||
else
|
||||
index += sizeof(uint16_t);
|
||||
index += sizeof(DNSResourceRecord::Info) + sizeof(uint16_t);
|
||||
index += sizeof(DNSResourceRecord::info) + sizeof(uint16_t);
|
||||
uint32_t sz(it->data_size());
|
||||
const uint8_t *ptr = it->data_ptr();
|
||||
if(Endian::be_to_host(it->info().type) == MX) {
|
||||
if(Endian::be_to_host(it->information().type) == MX) {
|
||||
ptr += 2;
|
||||
sz -= 2;
|
||||
index += 2;
|
||||
}
|
||||
if(contains_dname(it->info().type))
|
||||
if(contains_dname(it->information().type))
|
||||
add_suffix(index, ptr, sz);
|
||||
index += sz;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t DNS::build_suffix_map(uint32_t index, const list<Query> &lst) {
|
||||
uint32_t DNS::build_suffix_map(uint32_t index, const list<Query> &lst) const {
|
||||
for(list<Query>::const_iterator it(lst.begin()); it != lst.end(); ++it) {
|
||||
add_suffix(index, (uint8_t*)it->name.c_str(), it->name.size());
|
||||
index += it->name.size() + 1 + (sizeof(uint16_t) << 1);
|
||||
add_suffix(index, (uint8_t*)it->dname().c_str(), it->dname().size());
|
||||
index += it->dname().size() + 1 + (sizeof(uint16_t) << 1);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void DNS::build_suffix_map() {
|
||||
void DNS::build_suffix_map() const {
|
||||
uint32_t index(sizeof(dnshdr));
|
||||
index = build_suffix_map(index, queries);
|
||||
index = build_suffix_map(index, queries_);
|
||||
index = build_suffix_map(index, ans);
|
||||
index = build_suffix_map(index, arity);
|
||||
build_suffix_map(index, addit);
|
||||
}
|
||||
|
||||
void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) {
|
||||
void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const {
|
||||
uint32_t i(0);
|
||||
while(i < sz) {
|
||||
if(i && ptr[i])
|
||||
@@ -360,7 +366,6 @@ void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) {
|
||||
index &= 0x3fff;
|
||||
SuffixMap::iterator it(suffixes.find(index));
|
||||
SuffixIndices::iterator suff_it(suffix_indices.find(index));
|
||||
//assert(it != suffixes.end() && suff_it == suffix_indices.end());
|
||||
if(it == suffixes.end() || suff_it == suffix_indices.end())
|
||||
throw std::runtime_error("Malformed DNS packet");
|
||||
bool first(true);
|
||||
@@ -391,7 +396,7 @@ void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) {
|
||||
}
|
||||
}
|
||||
|
||||
void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res) {
|
||||
void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res) const {
|
||||
if(!suffixes.size())
|
||||
build_suffix_map();
|
||||
const string *str_ptr;
|
||||
@@ -410,31 +415,38 @@ void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res)
|
||||
if(sz == 4)
|
||||
addr = IPv4Address(*(uint32_t*)ptr).to_string();
|
||||
else {
|
||||
if(Endian::be_to_host(it->info().type) == MX) {
|
||||
if(Endian::be_to_host(it->information().type) == MX) {
|
||||
ptr += 2;
|
||||
sz -= 2;
|
||||
}
|
||||
compose_name(ptr, sz, addr);
|
||||
}
|
||||
res.push_back(
|
||||
Resource(dname, addr, Endian::be_to_host(it->info().type),
|
||||
Endian::host_to_be(it->info().qclass), Endian::be_to_host(it->info().ttl)
|
||||
Resource(dname, addr, Endian::be_to_host(it->information().type),
|
||||
Endian::host_to_be(it->information().qclass),
|
||||
Endian::be_to_host(it->information().ttl)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DNS::queries_type DNS::dns_queries() const {
|
||||
DNS::queries_type DNS::queries() const {
|
||||
queries_type output;
|
||||
for(std::list<Query>::const_iterator it(queries.begin()); it != queries.end(); ++it) {
|
||||
for(std::list<Query>::const_iterator it(queries_.begin()); it != queries_.end(); ++it) {
|
||||
string dn;
|
||||
unparse_domain_name(it->name, dn);
|
||||
output.push_back(Query(dn, Endian::be_to_host(it->type), Endian::be_to_host(it->qclass)));
|
||||
unparse_domain_name(it->dname(), dn);
|
||||
output.push_back(
|
||||
Query(
|
||||
dn,
|
||||
(QueryType)Endian::be_to_host<uint16_t>(it->type()),
|
||||
(QueryClass)Endian::be_to_host<uint16_t>(it->query_class())
|
||||
)
|
||||
);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
DNS::resources_type DNS::dns_answers() {
|
||||
DNS::resources_type DNS::answers() const {
|
||||
resources_type res;
|
||||
convert_resources(ans, res);
|
||||
return res;
|
||||
|
||||
@@ -104,7 +104,7 @@ uint32_t DNSResourceRecord::write(uint8_t *buffer) const {
|
||||
buffer += sz;
|
||||
std::memcpy(buffer, &info_, sizeof(info_));
|
||||
buffer += sizeof(info_);
|
||||
*((uint16_t*)buffer) = Endian::host_to_be(data.size());
|
||||
*((uint16_t*)buffer) = Endian::host_to_be<uint16_t>(data.size());
|
||||
buffer += sizeof(uint16_t);
|
||||
std::copy(data.begin(), data.end(), buffer);
|
||||
return sz + sizeof(info_) + sizeof(uint16_t) + data.size();
|
||||
|
||||
Reference in New Issue
Block a user