diff --git a/include/ircd/rfc1035.h b/include/ircd/rfc1035.h index a5942fc81..8e1cd933a 100644 --- a/include/ircd/rfc1035.h +++ b/include/ircd/rfc1035.h @@ -125,6 +125,8 @@ static_assert "The RFC1035 header is not the right size in this environment" ); +/// DNS operation code +/// enum class ircd::rfc1035::op :uint8_t { @@ -135,37 +137,68 @@ enum class ircd::rfc1035::op UPDATE = 5, ///< Update [RFC 2136] }; +/// Resource record abstract base +/// struct ircd::rfc1035::record { struct A; struct AAAA; struct CNAME; struct SRV; + + uint16_t type; + time_t ttl; + const_buffer rdata; + + template const T &as() const; + + record(const answer &); + virtual ~record() noexcept; }; +template +const T & +ircd::rfc1035::record::as() +const +{ + return dynamic_cast(*this); +} + +// +// Types of records +// + +/// IPv4 address record struct ircd::rfc1035::record::A +:record { uint32_t ip4; - A(const const_buffer &rdata); + A(const answer &); }; +/// IPv6 address record struct ircd::rfc1035::record::AAAA +:record { uint128_t ip6; - AAAA(const const_buffer &rdata); + AAAA(const answer &); }; +/// Canonical name aliasing record struct ircd::rfc1035::record::CNAME +:record { string_view name; char namebuf[256]; - CNAME(const const_buffer &rdata); + CNAME(const answer &); }; +/// Service record struct ircd::rfc1035::record::SRV +:record { uint16_t priority; uint16_t weight; @@ -173,5 +206,5 @@ struct ircd::rfc1035::record::SRV string_view tgt; char tgtbuf[256]; - SRV(const const_buffer &rdata); + SRV(const answer &); }; diff --git a/ircd/rfc1035.cc b/ircd/rfc1035.cc index 969b4b822..a24b9ad65 100644 --- a/ircd/rfc1035.cc +++ b/ircd/rfc1035.cc @@ -174,7 +174,25 @@ ircd::rfc1035::answer::parse(const const_buffer &in) return { data(in), pos }; } -ircd::rfc1035::record::A::A(const const_buffer &rdata) +// +// Record +// + +ircd::rfc1035::record::record(const answer &answer) +:type{answer.qtype} +,ttl{answer.ttl} +,rdata{answer.rdata} +{ +} + +/// vtable +ircd::rfc1035::record::~record() +noexcept +{ +} + +ircd::rfc1035::record::A::A(const answer &answer) +:record{answer} { assert(size(rdata) == 4); if(unlikely(size(rdata) < 4)) @@ -186,7 +204,8 @@ ircd::rfc1035::record::A::A(const const_buffer &rdata) ip4 = bswap(*(const uint32_t *)data(rdata)); } -ircd::rfc1035::record::AAAA::AAAA(const const_buffer &rdata) +ircd::rfc1035::record::AAAA::AAAA(const answer &answer) +:record{answer} { assert(size(rdata) == 16); if(unlikely(size(rdata) < 16)) @@ -198,7 +217,8 @@ ircd::rfc1035::record::AAAA::AAAA(const const_buffer &rdata) ip6 = bswap(*(const uint128_t *)data(rdata)); } -ircd::rfc1035::record::CNAME::CNAME(const const_buffer &rdata) +ircd::rfc1035::record::CNAME::CNAME(const answer &answer) +:record{answer} { if(unlikely(size(rdata) < 1)) throw error @@ -210,7 +230,8 @@ ircd::rfc1035::record::CNAME::CNAME(const const_buffer &rdata) name = string_view{namebuf, len}; } -ircd::rfc1035::record::SRV::SRV(const const_buffer &rdata) +ircd::rfc1035::record::SRV::SRV(const answer &answer) +:record{answer} { if(unlikely(size(rdata) < 2 + 2 + 2 + 1)) throw error @@ -231,6 +252,10 @@ ircd::rfc1035::record::SRV::SRV(const const_buffer &rdata) assert(std::distance(pos, end(rdata)) == 0); } +// +// Util / misc +// + ircd::const_buffer ircd::rfc1035::make_name(const mutable_buffer &out, const string_view &fqdn)