2024-11-01 22:53:43 +00:00
/*
* Copyright ( c ) 2024 , Ali Mohammad Pur < mpfard @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
# include <AK/Base64.h>
2024-11-20 21:54:21 +00:00
# include <AK/IPv4Address.h>
# include <AK/IPv6Address.h>
2024-11-01 22:53:43 +00:00
# include <AK/RedBlackTree.h>
# include <AK/Time.h>
namespace DNS {
namespace Messages {
struct DomainName ;
struct ParseContext {
CountingStream & stream ;
NonnullOwnPtr < RedBlackTree < u16 , DomainName > > pointers ;
} ;
enum class OpCode : u8 ;
struct Options {
// 1 1 1 1 1 1
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | ID |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// |QR| Opcode |AA|TC|RD|RA| Z |AD|CD| RCODE |
constexpr inline static u16 QRMask = 0 b1000000000000000 ;
constexpr inline static u16 OpCodeMask = 0 b0111100000000000 ;
constexpr inline static u16 AuthoritativeAnswerMask = 0 b0000010000000000 ;
constexpr inline static u16 TruncatedMask = 0 b0000001000000000 ;
constexpr inline static u16 RecursionDesiredMask = 0 b0000000100000000 ;
constexpr inline static u16 RecursionAvailableMask = 0 b0000000010000000 ;
constexpr inline static u16 AuthenticatedDataMask = 0 b0000000000100000 ;
constexpr inline static u16 CheckingDisabledMask = 0 b0000000000010000 ;
constexpr inline static u16 ResponseCodeMask = 0 b0000000000001111 ;
enum class ResponseCode : u16 {
NoError = 0 ,
FormatError = 1 ,
ServerFailure = 2 ,
NameError = 3 ,
NotImplemented = 4 ,
Refused = 5 ,
} ;
void set_is_question ( bool value ) { raw = ( raw & ~ QRMask ) | ( value ? QRMask : 0 ) ; }
void set_is_authoritative_answer ( bool value ) { raw = ( raw & ~ AuthoritativeAnswerMask ) | ( value ? AuthoritativeAnswerMask : 0 ) ; }
void set_is_truncated ( bool value ) { raw = ( raw & ~ TruncatedMask ) | ( value ? TruncatedMask : 0 ) ; }
void set_recursion_desired ( bool value ) { raw = ( raw & ~ RecursionDesiredMask ) | ( value ? RecursionDesiredMask : 0 ) ; }
void set_recursion_available ( bool value ) { raw = ( raw & ~ RecursionAvailableMask ) | ( value ? RecursionAvailableMask : 0 ) ; }
void set_response_code ( ResponseCode code ) { raw = ( raw & ~ ResponseCodeMask ) | static_cast < u16 > ( code ) ; }
void set_checking_disabled ( bool value ) { raw = ( raw & ~ CheckingDisabledMask ) | ( value ? CheckingDisabledMask : 0 ) ; }
void set_authenticated_data ( bool value ) { raw = ( raw & ~ AuthenticatedDataMask ) | ( value ? AuthenticatedDataMask : 0 ) ; }
void set_op_code ( OpCode code ) { raw = ( raw & ~ OpCodeMask ) | ( static_cast < u16 > ( code ) < < 11 ) ; }
bool is_question ( ) const { return ( raw & QRMask ) = = 0 ; }
bool is_authoritative_answer ( ) const { return ( raw & AuthoritativeAnswerMask ) ! = 0 ; }
bool is_truncated ( ) const { return ( raw & TruncatedMask ) ! = 0 ; }
bool recursion_desired ( ) const { return ( raw & RecursionDesiredMask ) ! = 0 ; }
bool recursion_available ( ) const { return ( raw & RecursionAvailableMask ) ! = 0 ; }
bool checking_disabled ( ) const { return ( raw & CheckingDisabledMask ) ! = 0 ; }
bool authenticated_data ( ) const { return ( raw & AuthenticatedDataMask ) ! = 0 ; }
ResponseCode response_code ( ) const { return static_cast < ResponseCode > ( raw & ResponseCodeMask ) ; }
OpCode op_code ( ) const { return static_cast < OpCode > ( ( raw & OpCodeMask ) > > 11 ) ; }
String to_string ( ) const ;
NetworkOrdered < u16 > raw { 0 } ;
} ;
StringView to_string ( Options : : ResponseCode ) ;
struct Header {
NetworkOrdered < u16 > id ;
Options options ;
NetworkOrdered < u16 > question_count ;
NetworkOrdered < u16 > answer_count ;
NetworkOrdered < u16 > authority_count ;
NetworkOrdered < u16 > additional_count ;
} ;
struct DomainName {
Vector < ByteString > labels ;
static DomainName from_string ( StringView ) ;
static ErrorOr < DomainName > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const ;
String to_string ( ) const ;
} ;
// Listing from IANA https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4.
enum class ResourceType : u16 {
Reserved = 0 , // [RFC6895]
A = 1 , // a host address [RFC1035]
NS = 2 , // an authoritative name server [RFC1035]
MD = 3 , // a mail destination (OBSOLETE - use MX) [RFC1035]
MF = 4 , // a mail forwarder (OBSOLETE - use MX) [RFC1035]
CNAME = 5 , // the canonical name for an alias [RFC1035]
SOA = 6 , // marks the start of a zone of authority [RFC1035]
MB = 7 , // a mailbox domain name (EXPERIMENTAL) [RFC1035]
MG = 8 , // a mail group member (EXPERIMENTAL) [RFC1035]
MR = 9 , // a mail rename domain name (EXPERIMENTAL) [RFC1035]
NULL_ = 10 , // a null RR (EXPERIMENTAL) [RFC1035]
WKS = 11 , // a well known service description [RFC1035]
PTR = 12 , // a domain name pointer [RFC1035]
HINFO = 13 , // host information [RFC1035]
MINFO = 14 , // mailbox or mail list information [RFC1035]
MX = 15 , // mail exchange [RFC1035]
TXT = 16 , // text strings [RFC1035]
RP = 17 , // for Responsible Person [RFC1183]
AFSDB = 18 , // for AFS Data Base location [RFC1183][RFC5864]
X25 = 19 , // for X.25 PSDN address [RFC1183]
ISDN = 20 , // for ISDN address [RFC1183]
RT = 21 , // for Route Through [RFC1183]
NSAP = 22 , // for NSAP address, NSAP style A record (DEPRECATED) [RFC1706][Moving TPC.INT and NSAP.INT infrastructure domains to historic]
NSAP_PTR = 23 , // for domain name pointer, NSAP style (DEPRECATED) [RFC1706][Moving TPC.INT and NSAP.INT infrastructure domains to historic]
SIG = 24 , // for security signature [RFC2536][RFC2931][RFC3110][RFC4034]
KEY = 25 , // for security key [RFC2536][RFC2539][RFC3110][RFC4034]
PX = 26 , // X.400 mail mapping information [RFC2163]
GPOS = 27 , // Geographical Position [RFC1712]
AAAA = 28 , // IP6 Address [RFC3596]
LOC = 29 , // Location Information [RFC1876]
NXT = 30 , // Next Domain (OBSOLETE) [RFC2535][RFC3755]
EID = 31 , // Endpoint Identifier [Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt]
NIMLOC = 32 , // Nimrod Locator [1][Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt]
SRV = 33 , // Server Selection [1][RFC2782]
ATMA = 34 , // ATM Address "[ ATM Forum Technical Committee, "ATM Name System, V2.0", Doc ID: AF-DANS-0152.000, July 2000. Available from and held in escrow by IANA.]"
NAPTR = 35 , // Naming Authority Pointer [RFC3403]
KX = 36 , // Key Exchanger [RFC2230]
CERT = 37 , // CERT [RFC4398]
A6 = 38 , // A6 (OBSOLETE - use AAAA) [RFC2874][RFC3226][RFC6563]
DNAME = 39 , // DNAME [RFC6672]
SINK = 40 , // SINK [Donald_E_Eastlake][draft-eastlake-kitchen-sink]
OPT = 41 , // OPT [RFC3225][RFC6891]
APL = 42 , // APL [RFC3123]
DS = 43 , // Delegation Signer [RFC4034]
SSHFP = 44 , // SSH Key Fingerprint [RFC4255]
IPSECKEY = 45 , // IPSECKEY [RFC4025]
RRSIG = 46 , // RRSIG [RFC4034]
NSEC = 47 , // NSEC [RFC4034][RFC9077]
DNSKEY = 48 , // DNSKEY [RFC4034]
DHCID = 49 , // DHCID [RFC4701]
NSEC3 = 50 , // NSEC3 [RFC5155][RFC9077]
NSEC3PARAM = 51 , // NSEC3PARAM [RFC5155]
TLSA = 52 , // TLSA [RFC6698]
SMIMEA = 53 , // S/MIME cert association [RFC8162]
HIP = 55 , // Host Identity Protocol [RFC8005]
NINFO = 56 , // NINFO [Jim_Reid]
RKEY = 57 , // RKEY [Jim_Reid]
TALINK = 58 , // Trust Anchor LINK [Wouter_Wijngaards]
CDS = 59 , // Child DS [RFC7344]
CDNSKEY = 60 , // DNSKEY(s) the Child wants reflected in DS [RFC7344]
OPENPGPKEY = 61 , // OpenPGP Key [RFC7929]
CSYNC = 62 , // Child-To-Parent Synchronization [RFC7477]
ZONEMD = 63 , // Message Digest Over Zone Data [RFC8976]
SVCB = 64 , // General-purpose service binding [RFC9460]
HTTPS = 65 , // SVCB-compatible type for use with HTTP [RFC9460]
SPF = 99 , // [RFC7208]
UINFO = 100 , // [IANA-Reserved]
UID = 101 , // [IANA-Reserved]
GID = 102 , // [IANA-Reserved]
UNSPEC = 103 , // [IANA-Reserved]
NID = 104 , // [RFC6742]
L32 = 105 , // [RFC6742]
L64 = 106 , // [RFC6742]
LP = 107 , // [RFC6742]
EUI48 = 108 , // an EUI-48 address [RFC7043]
EUI64 = 109 , // an EUI-64 address [RFC7043]
NXNAME = 128 , // NXDOMAIN indicator for Compact Denial of Existence [draft-ietf-dnsop-compact-denial-of-existence-04]
TKEY = 249 , // Transaction Key [RFC2930]
TSIG = 250 , // Transaction Signature [RFC8945]
IXFR = 251 , // incremental transfer [RFC1995]
AXFR = 252 , // transfer of an entire zone [RFC1035][RFC5936]
MAILB = 253 , // mailbox-related RRs (MB, MG or MR) [RFC1035]
MAILA = 254 , // mail agent RRs (OBSOLETE - see MX) [RFC1035]
ANY = 255 , // A request for some or all records the server has available [RFC1035][RFC6895][RFC8482]
URI = 256 , // URI [RFC7553]
CAA = 257 , // Certification Authority Restriction [RFC8659]
AVC = 258 , // Application Visibility and Control [Wolfgang_Riedel]
DOA = 259 , // Digital Object Architecture [draft-durand-doa-over-dns]
AMTRELAY = 260 , // Automatic Multicast Tunneling Relay [RFC8777]
RESINFO = 261 , // Resolver Information as Key/Value Pairs [RFC9606]
WALLET = 262 , // Public wallet address [Paul_Hoffman]
CLA = 263 , // BP Convergence Layer Adapter [draft-johnson-dns-ipn-cla-07]
IPN = 264 , // BP Node Number [draft-johnson-dns-ipn-cla-07]
TA = 32768 , // DNSSEC Trust Authorities "[Sam_Weiler][Deploying DNSSEC Without a Signed Root. Technical Report 1999-19, Information Networking Institute, Carnegie Mellon University, April 2004.]"
DLV = 32769 , // DNSSEC Lookaside Validation (OBSOLETE) [RFC8749][RFC4431]
} ;
StringView to_string ( ResourceType ) ;
Optional < ResourceType > resource_type_from_string ( StringView ) ;
// Listing from IANA https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2.
enum class Class : u16 {
IN = 1 , // the Internet [RFC1035]
CH = 3 , // the CHAOS class [Moon1981]
HS = 4 , // Hesiod [Dyer1987]
} ;
StringView to_string ( Class ) ;
// Listing from IANA https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-3.
enum class OpCode : u8 {
Query = 0 , // a standard query (QUERY)
IQuery = 1 , // an inverse query (IQUERY)
Status = 2 , // a server status request (STATUS)
Notify = 4 , // NOTIFY
Update = 5 , // dynamic update (RFC 2136)
DSO = 6 , // DNS Stateful Operations (DSO) [RFC8490]
Reserved = 7 , // [RFC6895]
ReservedMask = 15 // [RFC6895]
} ;
StringView to_string ( OpCode ) ;
namespace TLSA {
// Listings from IANA https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml.
enum class CertUsage : u8 {
CAConstraint = 0 ,
ServiceCertificateConstraint = 1 ,
TrustAnchorAssertion = 2 ,
DomainIssuedCertificate = 3 ,
Private = 255
} ;
enum class Selector : u8 {
FullCertificate = 0 ,
SubjectPublicKeyInfo = 1 ,
Private = 255
} ;
enum class MatchingType : u8 {
Full = 0 ,
SHA256 = 1 ,
SHA512 = 2 ,
Private = 255
} ;
}
namespace DNSSEC {
// Listing from IANA https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml.
enum class Algorithm : u8 {
RSAMD5 = 1 , // RSA/MD5 [RFC4034][RFC3110]
DSA = 3 , // DSA/SHA-1 [RFC3755][RFC2536]
RSASHA1 = 5 , // RSA/SHA-1 [RFC3110]
RSASHA1NSEC3SHA1 = 7 , // [RFC5155]
RSASHA256 = 8 , // RSA/SHA-256 [RFC5702]
RSASHA512 = 10 , // RSA/SHA-512 [RFC5702]
ECDSAP256SHA256 = 13 , // ECDSA Curve P-256 with SHA-256 [RFC6605]
ECDSAP384SHA384 = 14 , // ECDSA Curve P-384 with SHA-384 [RFC6605]
ED25519 = 15 , // Ed25519 [RFC8080]
Unknown = 255 // Reserved for Private Use
} ;
static inline StringView to_string ( Algorithm algorithm )
{
switch ( algorithm ) {
case Algorithm : : RSAMD5 :
return " RSAMD5 " sv ;
case Algorithm : : DSA :
return " DSA " sv ;
case Algorithm : : RSASHA1 :
return " RSASHA1 " sv ;
case Algorithm : : RSASHA1NSEC3SHA1 :
return " RSASHA1NSEC3SHA1 " sv ;
case Algorithm : : RSASHA256 :
return " RSASHA256 " sv ;
case Algorithm : : RSASHA512 :
return " RSASHA512 " sv ;
case Algorithm : : ECDSAP256SHA256 :
return " ECDSAP256SHA256 " sv ;
case Algorithm : : ECDSAP384SHA384 :
return " ECDSAP384SHA384 " sv ;
case Algorithm : : ED25519 :
return " ED25519 " sv ;
case Algorithm : : Unknown :
return " Unknown " sv ;
}
VERIFY_NOT_REACHED ( ) ;
}
// Listing from IANA https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml.
enum class DigestType : u8 {
SHA1 = 1 , // SHA-1 [RFC3658]
SHA256 = 2 , // SHA-256 [RFC4509]
GOST3411 = 3 , // GOST R 34.11-94 [RFC5933]
SHA384 = 4 , // SHA-384 [RFC6605]
SHA512 = 5 , // SHA-512 [RFC6605]
SHA224 = 6 , // SHA-224 [RFC6605]
Unknown = 255 // Reserved for Private Use
} ;
static inline StringView to_string ( DigestType digest_type )
{
switch ( digest_type ) {
case DigestType : : SHA1 :
return " SHA1 " sv ;
case DigestType : : SHA256 :
return " SHA256 " sv ;
case DigestType : : GOST3411 :
return " GOST3411 " sv ;
case DigestType : : SHA384 :
return " SHA384 " sv ;
case DigestType : : SHA512 :
return " SHA512 " sv ;
case DigestType : : SHA224 :
return " SHA224 " sv ;
case DigestType : : Unknown :
return " Unknown " sv ;
}
VERIFY_NOT_REACHED ( ) ;
}
// Listing from IANA https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml.
enum class NSEC3HashAlgorithm : u8 {
SHA1 = 1 , // [RFC5155]
SHA256 = 2 , // [RFC6605]
GOST3411 = 3 , // [RFC5933]
SHA384 = 4 , // [RFC6605]
SHA512 = 5 , // [RFC6605]
SHA224 = 6 , // [RFC6605]
Unknown = 255 // Reserved for Private Use
} ;
static inline StringView to_string ( NSEC3HashAlgorithm hash_algorithm )
{
switch ( hash_algorithm ) {
case NSEC3HashAlgorithm : : SHA1 :
return " SHA1 " sv ;
case NSEC3HashAlgorithm : : SHA256 :
return " SHA256 " sv ;
case NSEC3HashAlgorithm : : GOST3411 :
return " GOST3411 " sv ;
case NSEC3HashAlgorithm : : SHA384 :
return " SHA384 " sv ;
case NSEC3HashAlgorithm : : SHA512 :
return " SHA512 " sv ;
case NSEC3HashAlgorithm : : SHA224 :
return " SHA224 " sv ;
case NSEC3HashAlgorithm : : Unknown :
return " Unknown " sv ;
}
VERIFY_NOT_REACHED ( ) ;
}
}
struct Question {
DomainName name ;
ResourceType type ;
Class class_ ;
static ErrorOr < Question > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const ;
} ;
namespace Records {
struct A {
IPv4Address address ;
static constexpr ResourceType type = ResourceType : : A ;
static ErrorOr < A > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return address . to_string ( ) ; }
} ;
struct AAAA {
IPv6Address address ;
static constexpr ResourceType type = ResourceType : : AAAA ;
static ErrorOr < AAAA > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return address . to_string ( ) ; }
} ;
struct TXT {
ByteString content ;
static constexpr ResourceType type = ResourceType : : TXT ;
static ErrorOr < TXT > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return String : : formatted ( " Text: '{}' " , StringView { content } ) ; }
} ;
struct CNAME {
DomainName names ;
static constexpr ResourceType type = ResourceType : : CNAME ;
static ErrorOr < CNAME > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return names . to_string ( ) ; }
} ;
struct NS {
DomainName name ;
static constexpr ResourceType type = ResourceType : : NS ;
static ErrorOr < NS > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return name . to_string ( ) ; }
} ;
struct SOA {
DomainName mname ;
DomainName rname ;
u32 serial ;
u32 refresh ;
u32 retry ;
u32 expire ;
u32 minimum ;
static constexpr ResourceType type = ResourceType : : SOA ;
static ErrorOr < SOA > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const
{
return String : : formatted ( " SOA MName: '{}', RName: '{}', Serial: {}, Refresh: {}, Retry: {}, Expire: {}, Minimum: {} " , mname . to_string ( ) , rname . to_string ( ) , serial , refresh , retry , expire , minimum ) ;
}
} ;
struct MX {
u16 preference ;
DomainName exchange ;
static constexpr ResourceType type = ResourceType : : MX ;
static ErrorOr < MX > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return String : : formatted ( " MX Preference: {}, Exchange: '{}' " , preference , exchange . to_string ( ) ) ; }
} ;
struct PTR {
DomainName name ;
static constexpr ResourceType type = ResourceType : : PTR ;
static ErrorOr < PTR > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return name . to_string ( ) ; }
} ;
struct SRV {
u16 priority ;
u16 weight ;
u16 port ;
DomainName target ;
static constexpr ResourceType type = ResourceType : : SRV ;
static ErrorOr < SRV > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return String : : formatted ( " SRV Priority: {}, Weight: {}, Port: {}, Target: '{}' " , priority , weight , port , target . to_string ( ) ) ; }
} ;
struct DNSKEY {
u16 flags ;
u8 protocol ;
DNSSEC : : Algorithm algorithm ;
ByteBuffer public_key ;
constexpr static inline u16 FlagSecureEntryPoint = 0 b1000000000000000 ;
constexpr static inline u16 FlagZoneKey = 0 b0100000000000000 ;
constexpr static inline u16 FlagRevoked = 0 b0010000000000000 ;
constexpr bool is_secure_entry_point ( ) const { return flags & FlagSecureEntryPoint ; }
constexpr bool is_zone_key ( ) const { return flags & FlagZoneKey ; }
constexpr bool is_revoked ( ) const { return flags & FlagRevoked ; }
constexpr bool is_key_signing_key ( ) const { return is_secure_entry_point ( ) & & is_zone_key ( ) & & ! is_revoked ( ) ; }
static constexpr ResourceType type = ResourceType : : DNSKEY ;
static ErrorOr < DNSKEY > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const
{
return String : : formatted ( " DNSKEY Flags: {}{}{}{}({}), Protocol: {}, Algorithm: {}, Public Key: {} " ,
is_secure_entry_point ( ) ? " sep " sv : " " sv ,
is_zone_key ( ) ? " zone " sv : " " sv ,
is_revoked ( ) ? " revoked " sv : " " sv ,
is_key_signing_key ( ) ? " ksk " sv : " " sv ,
flags ,
protocol ,
DNSSEC : : to_string ( algorithm ) ,
TRY ( encode_base64 ( public_key ) ) ) ;
}
} ;
struct CDNSKEY : public DNSKEY {
template < typename . . . Ts >
CDNSKEY ( Ts & & . . . args )
: DNSKEY ( forward < Ts > ( args ) . . . )
{
}
static constexpr ResourceType type = ResourceType : : CDNSKEY ;
static ErrorOr < CDNSKEY > from_raw ( ParseContext & raw ) { return DNSKEY : : from_raw ( raw ) ; }
} ;
struct DS {
u16 key_tag ;
DNSSEC : : Algorithm algorithm ;
DNSSEC : : DigestType digest_type ;
ByteBuffer digest ;
static constexpr ResourceType type = ResourceType : : DS ;
static ErrorOr < DS > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return " DS " _string ; }
} ;
struct CDS : public DS {
template < typename . . . Ts >
CDS ( Ts & & . . . args )
: DS ( forward < Ts > ( args ) . . . )
{
}
static constexpr ResourceType type = ResourceType : : CDS ;
static ErrorOr < CDS > from_raw ( ParseContext & raw ) { return DS : : from_raw ( raw ) ; }
} ;
struct SIG {
ResourceType type_covered ;
DNSSEC : : Algorithm algorithm ;
u8 label_count ;
u32 original_ttl ;
UnixDateTime expiration ;
UnixDateTime inception ;
u16 key_tag ;
DomainName signers_name ;
ByteBuffer signature ;
static constexpr ResourceType type = ResourceType : : SIG ;
static ErrorOr < SIG > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const ;
} ;
struct RRSIG : public SIG {
template < typename . . . Ts >
RRSIG ( Ts & & . . . args )
: SIG ( forward < Ts > ( args ) . . . )
{
}
static constexpr ResourceType type = ResourceType : : RRSIG ;
static ErrorOr < RRSIG > from_raw ( ParseContext & raw ) { return SIG : : from_raw ( raw ) ; }
} ;
struct NSEC {
DomainName next_domain_name ;
Vector < ResourceType > types ;
static constexpr ResourceType type = ResourceType : : NSEC ;
static ErrorOr < NSEC > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return " NSEC " _string ; }
} ;
struct NSEC3 {
DNSSEC : : NSEC3HashAlgorithm hash_algorithm ;
u8 flags ;
u16 iterations ;
ByteBuffer salt ;
DomainName next_hashed_owner_name ;
Vector < ResourceType > types ;
static constexpr ResourceType type = ResourceType : : NSEC3 ;
static ErrorOr < NSEC3 > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return " NSEC3 " _string ; }
} ;
struct NSEC3PARAM {
DNSSEC : : NSEC3HashAlgorithm hash_algorithm ;
u8 flags ;
u16 iterations ;
ByteBuffer salt ;
constexpr static inline u8 FlagOptOut = 0 b10000000 ;
constexpr bool is_opt_out ( ) const { return flags & FlagOptOut ; }
static constexpr ResourceType type = ResourceType : : NSEC3PARAM ;
static ErrorOr < NSEC3PARAM > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return " NSEC3PARAM " _string ; }
} ;
struct TLSA {
Messages : : TLSA : : CertUsage cert_usage ;
Messages : : TLSA : : Selector selector ;
Messages : : TLSA : : MatchingType matching_type ;
ByteBuffer certificate_association_data ;
static ErrorOr < TLSA > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return " TLSA " _string ; }
} ;
struct HINFO {
ByteString cpu ;
ByteString os ;
static constexpr ResourceType type = ResourceType : : HINFO ;
static ErrorOr < HINFO > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const { return Error : : from_string_literal ( " Not implemented " ) ; }
ErrorOr < String > to_string ( ) const { return String : : formatted ( " HINFO CPU: '{}', OS: '{}' " , StringView { cpu } , StringView { os } ) ; }
} ;
struct OPT {
struct Option {
u16 code ;
ByteBuffer data ;
} ;
// 1 1 1 1 1 1
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | UDP Payload Size |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | Extended RCode | VER | ZZ |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// |DO| Z |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | OPT-LEN / OPT-DATA...
NetworkOrdered < u16 > udp_payload_size { 0 } ;
NetworkOrdered < u32 > extended_rcode_and_flags { 0 } ;
Vector < Option > options ;
static constexpr u32 MaskExtendedRCode = 0 b11111111000000000000000000000000 ;
static constexpr u32 MaskVersion = 0 b00000000111100000000000000000000 ;
static constexpr u32 MaskDO = 0 b00000000000000001000000000000000 ;
static constexpr ResourceType type = ResourceType : : OPT ;
constexpr u8 extended_rcode ( ) const { return ( extended_rcode_and_flags & MaskExtendedRCode ) > > 24 ; }
constexpr u8 version ( ) const { return ( extended_rcode_and_flags & MaskVersion ) > > 20 ; }
constexpr bool dnssec_ok ( ) const { return extended_rcode_and_flags & MaskDO ; }
void set_extended_rcode ( u8 value ) { extended_rcode_and_flags = ( extended_rcode_and_flags & ~ MaskExtendedRCode ) | ( value < < 24 ) ; }
void set_version ( u8 value ) { extended_rcode_and_flags = ( extended_rcode_and_flags & ~ MaskVersion ) | ( value < < 20 ) ; }
void set_dnssec_ok ( bool value ) { extended_rcode_and_flags = ( extended_rcode_and_flags & ~ MaskDO ) | ( value ? MaskDO : 0 ) ; }
static ErrorOr < OPT > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const ;
ErrorOr < String > to_string ( ) const
{
StringBuilder builder ;
builder . appendff ( " OPT UDP Payload Size: {}, Extended RCode: {}, Version: {}, DNSSEC OK: {} " , udp_payload_size , extended_rcode ( ) , version ( ) , dnssec_ok ( ) ) ;
for ( auto & option : options )
builder . appendff ( " , opt[{} = '{:hex-dump}'] " , option . code , option . data . bytes ( ) ) ;
return builder . to_string ( ) ;
}
} ;
}
using Record = Variant <
Records : : A ,
Records : : AAAA ,
Records : : TXT ,
Records : : CNAME ,
Records : : NS ,
Records : : SOA ,
Records : : MX ,
Records : : PTR ,
Records : : SRV ,
Records : : DNSKEY ,
Records : : CDNSKEY ,
Records : : DS ,
Records : : CDS ,
Records : : RRSIG ,
Records : : NSEC ,
Records : : NSEC3 ,
Records : : NSEC3PARAM ,
Records : : TLSA ,
Records : : HINFO ,
Records : : OPT ,
// TODO: Add more records.
ByteBuffer > ; // Fallback for unknown records.
struct ResourceRecord {
DomainName name ;
ResourceType type ;
Class class_ ;
u32 ttl ;
Record record ;
Optional < ByteBuffer > raw ;
static ErrorOr < ResourceRecord > from_raw ( ParseContext & ) ;
ErrorOr < void > to_raw ( ByteBuffer & ) const ;
ErrorOr < String > to_string ( ) const ;
} ;
struct ZoneAuthority {
DomainName name ;
ByteString admin_mailbox ;
u32 serial ;
u32 refresh ;
u32 retry ;
u32 expire ;
u32 minimum_ttl ;
} ;
struct Message {
Header header ;
Vector < Question > questions ;
Vector < ResourceRecord > answers ;
Vector < ResourceRecord > authorities ;
Vector < ResourceRecord > additional_records ;
static ErrorOr < Message > from_raw ( ParseContext & ) ;
static ErrorOr < Message > from_raw ( Stream & ) ;
ErrorOr < size_t > to_raw ( ByteBuffer & ) const ;
ErrorOr < String > format_for_log ( ) const ;
} ;
}
}