Indented.Net.Dns.psm1

using namespace System.Management.Automation
using namespace System.Collections.Generic
using namespace System.Globalization
using namespace System.IO
using namespace System.Text
using namespace Indented.IO
using namespace Indented.Net.Dns
using namespace System.Net.Sockets
using namespace System.Collections
using namespace System.Diagnostics
using namespace System.Net
using namespace System.Net.NetworkInformation
#Region '.\enum\AFSDBSubType.ps1' 0
enum AFSDBSubType {
    AFSv3Loc   = 1    # Andrews File Service v3.0 Location Service [RFC1183]
    DCENCARoot = 2    # DCE/NCA root cell directory node [RFC1183]
}
#EndRegion '.\enum\AFSDBSubType.ps1' 5
#Region '.\enum\AMTRelayType.ps1' 0
enum AMTRelayType {
    None
    IPv4
    IPv6
    DomainName
}
#EndRegion '.\enum\AMTRelayType.ps1' 7
#Region '.\enum\ATMAFormat.ps1' 0
enum ATMAFormat {
    AESA = 0    # ATM End System Address
    E164 = 1    # E.164 address format
    NSAP = 2    # Network Service Access Protocol (NSAP) address model
}
#EndRegion '.\enum\ATMAFormat.ps1' 6
#Region '.\enum\CAAFlag.ps1' 0
enum CAAFlag {
    None
    IssuerCritical = 128
}
#EndRegion '.\enum\CAAFlag.ps1' 5
#Region '.\enum\CacheResourceType.ps1' 0
enum CacheResourceType {
    Hint = 1
    Address
}
#EndRegion '.\enum\CacheResourceType.ps1' 5
#Region '.\enum\CertificateType.ps1' 0
enum CertificateType {
    PKIX         = 1      # X.509 as per PKIX
    SPKI         = 2      # SPKI certificate
    PGP          = 3      # OpenPGP packet
    IPKIX        = 4      # The URL of an X.509 data object
    ISPKI        = 5      # The URL of an SPKI certificate
    IPGP         = 6      # The fingerprint and URL of an OpenPGP packet
    ACPKIX       = 7      # Attribute Certificate
    IACPKIX      = 8      # The URL of an Attribute Certificate
    URI          = 253    # URI private
    OID          = 254    # OID private
    Experimental = 65534
    Reserved     = 65535
}
#EndRegion '.\enum\CertificateType.ps1' 15
#Region '.\enum\CertificateUsage.ps1' 0
enum CertificateUsage {
    CAConstraint
    ServiceCertificateConstraint
    TrustAnchorAssertion
    DomainIssuedCertificate
}
#EndRegion '.\enum\CertificateUsage.ps1' 7
#Region '.\enum\CSYNCFlags.ps1' 0
enum CSYNCFlags {
    None
    Immediate
    Soaminimum
}
#EndRegion '.\enum\CSYNCFlags.ps1' 6
#Region '.\enum\DigestType.ps1' 0
enum DigestType {
    SHA1   = 1    # MANDATORY [RFC3658]
    SHA256 = 2    # MANDATORY [RFC4059]
    GOST   = 3    # OPTIONAL [RFC5933]
    SHA384 = 4    # OPTIONAL [RFC6605]
}
#EndRegion '.\enum\DigestType.ps1' 7
#Region '.\enum\DistanceType.ps1' 0
enum DistanceType {
    Latitude = 1
    Longitude
}
#EndRegion '.\enum\DistanceType.ps1' 5
#Region '.\enum\DOALocation.ps1' 0
enum DOALocation {
    Reserved
    Local
    Uri
    Hdl
}
#EndRegion '.\enum\DOALocation.ps1' 7
#Region '.\enum\DOAType.ps1' 0
enum DOAType {
    Reserved
    ContactEmail
    ContactWebsite
    ContactTelephone
    PublicKey        = 100
}
#EndRegion '.\enum\DOAType.ps1' 8
#Region '.\enum\EDnsDNSSECOK.ps1' 0
[Flags()]
enum EDnsDNSSECOK {
    NONE = 0
    DO   = 32768    # DNSSEC answer OK [RFC4035][RFC3225]
}
#EndRegion '.\enum\EDnsDNSSECOK.ps1' 6
#Region '.\enum\EDnsOptionCode.ps1' 0
enum EDnsOptionCode {
    LLQ                  = 1    # On-hold [http://files.dns-sd.org/draft-sekar-dns-llq.txt]
    UL                   = 2    # On-hold [http://files.dns-sd.org/draft-sekar-dns-ul.txt]
    NSID                 = 3    # Standard [RFC5001]
    DAU                  = 5    # Standard [RFC6975]
    DHU                  = 6    # Standard [RFC6975]
    N3U                  = 7    # Standard [RFC6975]
    EDNSClientSubnet     = 8    # Optional [draft-vandergaast-edns-client-subnet][Wilmer_van_der_Gaast]
}
#EndRegion '.\enum\EDnsOptionCode.ps1' 10
#Region '.\enum\EncryptionAlgorithm.ps1' 0
enum EncryptionAlgorithm {
    RSAMD5               = 1       # RSA/MD5 (deprecated see 5) [RFC3110][RFC4034]
    DH                   = 2       # Diffie-Hellman [RFC2539]
    DSA                  = 3       # DSA/SHA1 [RFC3755]
    RSASHA1              = 5       # RSA/SHA-1 [RFC3110][RFC4034]
    DSANSEC3SHA1         = 6       # DSA-NSEC3-SHA1 [RFC5155]
    RSASHA1NSEC3SHA1     = 7       # RSASHA1-NSEC3-SHA1 [RFC5155]
    RSASHA256            = 8       # RSA/SHA-256 [RFC5702]
    RSASHA512            = 10      # RSA/SHA-512 [RFC5702]
    ECCGOST              = 12      # GOST R 34.10-2001 [RFC5933]
    ECDSAP256SHA256      = 13      # ECDSA Curve P-256 with SHA-256 [RFC6605]
    ECDSAP384SHA384      = 14      # ECDSA Curve P-384 with SHA-384 [RFC6605]
    INDIRECT             = 252     # Reserved for indirect keys [RFC4034]
    PRIVATEDNS           = 253     # Private algorithm [RFC4034]
    PRIVATEOID           = 254     # Private algorithm OID [RFC4034]
}
#EndRegion '.\enum\EncryptionAlgorithm.ps1' 17
#Region '.\enum\HeaderFlags.ps1' 0
[Flags()]
enum HeaderFlags {
    None = 0
    AA   = 1024    # Authoritative Answer [RFC1035]
    TC   = 512     # Truncated Response [RFC1035]
    RD   = 256     # Recursion Desired [RFC1035]
    RA   = 128     # Recursion Allowed [RFC1035]
    AD   = 32      # Authenticated Data [RFC4035]
    CD   = 16      # Checking Disabled [RFC4035]
}
#EndRegion '.\enum\HeaderFlags.ps1' 11
#Region '.\enum\IanaAddressFamily.ps1' 0
enum IanaAddressFamily {
    IPv4                   = 1        # IP version 4
    IPv6                   = 2        # IP version 6
    NSAP                   = 3        # NSAP
    HDLC                   = 4        # HDLC (8-bit multidrop)
    BBN                    = 5        # BBN 1822
    IEEE802                = 6        # 802 (includes all 802 media plus Ethernet "canonical format")
    E163                   = 7        # E.163
    E164                   = 8        # E.164 (SMDS Frame Relay ATM)
    F69                    = 9        # F.69 (Telex)
    X121                   = 10       # X.121 (X.25 Frame Relay)
    IPX                    = 11       # IPX
    Appletalk              = 12       # Appletalk
    DecNetIV               = 13       # DecNet IV
    BanyanVines            = 14       # Banyan Vines
    E164NSAP               = 15       # E.164 with NSAP format subaddress [ATM Forum UNI 3.1. October 1995.][Andy_Malis]
    DNS                    = 16       # DNS (Domain Name System)
    DistinguishedName      = 17       # Distinguished Name [Charles_Lynn]
    ASNumber               = 18       # AS Number [Charles_Lynn]
    XTPOverIpv4            = 19       # XTP over IP version 4 [Mike_Saul]
    XTPOverIPv6            = 20       # XTP over IP version 6 [Mike_Saul]
    XTPNativeMode          = 21       # XTP native mode XTP [Mike_Saul]
    FibreChannelWWPortName = 22       # Fibre Channel World-Wide Port Name [Mark_Bakke]
    FibreChannelWWNodeName = 23       # Fibre Channel World-Wide Node Name [Mark_Bakke]
    GWID                   = 24       # GWID [Subra_Hegde]
    AFIForL2VPN            = 25       # AFI for L2VPN information [RFC4761][RFC6074]
    MPLSTPSectionID        = 26       # MPLS-TP Section Endpoint Identifier [RFC-ietf-mpls-gach-adv-08]
    MPLSTPLSPID            = 27       # MPLS-TP LSP Endpoint Identifier [RFC-ietf-mpls-gach-adv-08]
    MPLSTPPseudowireID     = 28       # MPLS-TP Pseudowire Endpoint Identifier [RFC-ietf-mpls-gach-adv-08]
    EIGRPCommon            = 16384    # EIGRP Common Service Family [Donnie_Savage]
    EIGRPIPv4              = 16385    # EIGRP IPv4 Service Family [Donnie_Savage]
    EIGRPIPv6              = 16386    # EIGRP IPv6 Service Family [Donnie_Savage]
    LCAF                   = 16387    # LISP Canonical Address Format (LCAF) [David_Meyer]
    BGPLS                  = 16388    # BGP-LS [draft-ietf-idr-ls-distribution]
    MAC48bit               = 16389    # 48-bit MAC [RFC-eastlake-rfc5342bis-05]
    MAC64bit               = 16390    # 64-bit MAC [RFC-eastlake-rfc5342bis-05]
    OUI                    = 16391    # OUI [draft-eastlake-trill-ia-appsubtlv]
    MAC24                  = 16392    # MAC/24 [draft-eastlake-trill-ia-appsubtlv]
    MAC40                  = 16393    # MAC/40 [draft-eastlake-trill-ia-appsubtlv]
    IPv664                 = 16394    # IPv6/64 [draft-eastlake-trill-ia-appsubtlv]
    RBridgePortID          = 16395    # RBridge Port ID [draft-eastlake-trill-ia-appsubtlv]
}
#EndRegion '.\enum\IanaAddressFamily.ps1' 43
#Region '.\enum\IPSECAlgorithm.ps1' 0
enum IPSECAlgorithm {
    DSA = 1    # [RFC4025]
    RSA = 2    # [RFC4025]
}
#EndRegion '.\enum\IPSECAlgorithm.ps1' 5
#Region '.\enum\IPSECGatewayType.ps1' 0
enum IPSECGatewayType {
    NoGateway  = 0    # No gateway is present [RFC4025]
    IPv4       = 1    # A 4-byte IPv4 address is present [RFC4025]
    IPv6       = 2    # A 16-byte IPv6 address is present [RFC4025]
    DomainName = 3    # A wire-encoded domain name is present [RFC4025]
}
#EndRegion '.\enum\IPSECGatewayType.ps1' 7
#Region '.\enum\KEYAC.ps1' 0
enum KEYAC {
    AuthAndConfPermitted = 0    # Use of the key for authentication and/or confidentiality is permitted.
    AuthProhibited       = 2    # Use of the key is prohibited for authentication.
    ConfProhibited       = 1    # Use of the key is prohibited for confidentiality.
    NoKey                = 3    # No key information
}
#EndRegion '.\enum\KEYAC.ps1' 7
#Region '.\enum\KEYNameType.ps1' 0
enum KEYNameType {
    UserKey  = 0    # Indicates that this is a key associated with a "user" or "account" at an end entity usually a host.
    ZoneKey  = 1    # Indicates that this is a zone key for the zone whose name is the KEY RR owner name.
    NonZone  = 2    # Indicates that this is a key associated with the non-zone "entity" whose name is the RR owner name.
    Reserved = 3    # Reserved
}
#EndRegion '.\enum\KEYNameType.ps1' 7
#Region '.\enum\KEYProtocol.ps1' 0
enum KEYProtocol {
    Reserved = 0
    TLS      = 1
    EMmail   = 2
    DNSSEC   = 3
    IPSEC    = 4
    All      = 255
}
#EndRegion '.\enum\KEYProtocol.ps1' 9
#Region '.\enum\LLQErrorCode.ps1' 0
enum LLQErrorCode {
    NoError    = 0
    ServFull   = 1
    Static     = 2
    FormatErr  = 3
    NoSuchLLQ  = 4
    BadVers    = 5
    UnknownErr = 6
}
#EndRegion '.\enum\LLQErrorCode.ps1' 10
#Region '.\enum\LLQOpCode.ps1' 0
enum LLQOpCode {
    LLQSetup   = 1
    LLQRefresh = 2
    LLQEvent   = 3
}
#EndRegion '.\enum\LLQOpCode.ps1' 6
#Region '.\enum\MatchingType.ps1' 0
enum MatchingType {
    NoHashUsed
    Sha256
    Sha512
}
#EndRegion '.\enum\MatchingType.ps1' 6
#Region '.\enum\MessageCompression.ps1' 0
enum MessageCompression {
    Enabled  = 192
    Disabled = 0
}
#EndRegion '.\enum\MessageCompression.ps1' 5
#Region '.\enum\MSDNSOption.ps1' 0
enum MSDNSOption {
    Query  = 0    # [RFC1035]
    IQuery = 1    # [RFC3425]
    Status = 2    # [RFC1035]
    Notify = 4    # [RFC1996]
    Update = 5    # [RFC2136]
}
#EndRegion '.\enum\MSDNSOption.ps1' 8
#Region '.\enum\NSEC3Flags.ps1' 0
enum NSEC3Flags {
    OptOut = 1    # [RFC5155]
}
#EndRegion '.\enum\NSEC3Flags.ps1' 4
#Region '.\enum\NSEC3HashAlgorithm.ps1' 0
enum NSEC3HashAlgorithm {
    SHA1 = 1    # [RFC5155]
}
#EndRegion '.\enum\NSEC3HashAlgorithm.ps1' 4
#Region '.\enum\OpCode.ps1' 0
enum OpCode {
    Query      = 0     # [RFC1035]
    IQuery     = 1     # [RFC3425]
    Status     = 2     # [RFC1035]
    Notify     = 4     # [RFC1996]
    Update     = 5     # [RFC2136]
}
#EndRegion '.\enum\OpCode.ps1' 8
#Region '.\enum\QR.ps1' 0
enum QR {
    Query    = 0
    Response = 32768
}
#EndRegion '.\enum\QR.ps1' 5
#Region '.\enum\RCode.ps1' 0
enum RCode {
    NoError  = 0     # No Error [RFC1035]
    FormErr  = 1     # Format Error [RFC1035]
    ServFail = 2     # Server Failure [RFC1035]
    NXDomain = 3     # Non-Existent Domain [RFC1035]
    NotImp   = 4     # Not Implemented [RFC1035]
    Refused  = 5     # Query Refused [RFC1035]
    YXDomain = 6     # Name Exists when it should not [RFC2136]
    YXRRSet  = 7     # RR Set Exists when it should not [RFC2136]
    NXRRSet  = 8     # RR Set that should exist does not [RFC2136]
    NotAuth  = 9     # Server Not Authoritative for zone [RFC2136]
    NotZone  = 10    # Name not contained in zone [RFC2136]
    BadVers  = 16    # Bad OPT Version [RFC2671]
    BadSig   = 16    # TSIG Signature Failure [RFC2845]
    BadKey   = 17    # Key not recognized [RFC2845]
    BadTime  = 18    # Signature out of time window [RFC2845]
    BadMode  = 19    # Bad TKEY Mode [RFC2930]
    BadName  = 20    # Duplicate key name [RFC2930]
    BadAlg   = 21    # Algorithm not supported [RFC2930]
    BadTrunc = 22    # Bad Truncation [RFC4635]
}
#EndRegion '.\enum\RCode.ps1' 22
#Region '.\enum\RecordClass.ps1' 0
enum RecordClass {
    IN   = 1      # [RFC1035]
    CH   = 3      # [Moon1981]
    HS   = 4      # [Dyer1987]
    NONE = 254    # [RFC2136]
    ANY  = 255    # [RFC1035]
}
#EndRegion '.\enum\RecordClass.ps1' 8
#Region '.\enum\RecordType.ps1' 0
enum RecordType {
    EMPTY      = 0        # an empty record [RFC1034] [MS DNS]
    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]
    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 [RFC1706]
    NSAPPTR    = 23       # for domain name pointer NSAP style [RFC1348]
    SIG        = 24       # for security signature [RFC4034][RFC3755][RFC2535]
    KEY        = 25       # for security key [RFC4034][RFC3755][RFC2535]
    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 [RFC3755][RFC2535]
    EID        = 31       # Endpoint Identifier [Patton]
    NIMLOC     = 32       # Nimrod Locator [Patton]
    SRV        = 33       # Server Selection [RFC2782]
    ATMA       = 34       # ATM Address [ATMDOC]
    NAPTR      = 35       # Naming Authority Pointer [RFC2915][RFC2168]
    KX         = 36       # Key Exchanger [RFC2230]
    CERT       = 37       # CERT [RFC4398]
    A6         = 38       # A6 (Experimental) [RFC3226][RFC2874]
    DNAME      = 39       # DNAME [RFC2672]
    SINK       = 40       # SINK [Eastlake]
    OPT        = 41       # OPT [RFC2671]
    APL        = 42       # APL [RFC3123]
    DS         = 43       # Delegation Signer [RFC4034][RFC3658]
    SSHFP      = 44       # SSH Key Fingerprint [RFC4255]
    IPSECKEY   = 45       # IPSECKEY [RFC4025]
    RRSIG      = 46       # RRSIG [RFC4034][RFC3755]
    NSEC       = 47       # NSEC [RFC4034][RFC3755]
    DNSKEY     = 48       # DNSKEY [RFC4034][RFC3755]
    DHCID      = 49       # DHCID [RFC4701]
    NSEC3      = 50       # NSEC3 [RFC5155]
    NSEC3PARAM = 51       # NSEC3PARAM [RFC5155]
    TLSA       = 52       # Transport Layer Security [RFC6698]
    SMIMEA     = 53       # S/MIME Certificate [RFC8162]
    HIP        = 55       # Host Identity Protocol [RFC5205]
    NINFO      = 56       # NINFO [Reid]
    RKEY       = 57       # RKEY [Reid]
    TALINK     = 58       # [Wouter_Wijngaards]
    CDS        = 59       # Child DS [RFC7344]
    CDNSKEY    = 60       # DNS key to reflect in DS [RFC7344]
    OPENPGPKEY = 61       # OpenPGP Key [RFC7929]
    CSYNC      = 62       # Child-to-Parent Synchronization [RFC7477]
    ZONEMD     = 63       # Synchronization message digest [draft-wessels-dns-zone-digest]
    SPF        = 99       # [RFC4408]
    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      # EUI-48 address [RFC7043]
    EUI64      = 109      # EUI-64 address [RFC7043]
    TKEY       = 249      # Transaction Key [RFC2930]
    TSIG       = 250      # Transaction Signature [RFC2845]
    IXFR       = 251      # incremental transfer [RFC1995]
    AXFR       = 252      # transfer of an entire zone [RFC1035]
    MAILB      = 253      # mailbox-related RRs (MB MG or MR) [RFC1035]
    MAILA      = 254      # mail agent RRs (Obsolete - see MX) [RFC1035]
    ANY        = 255      # A request for all records (*) [RFC1035]
    URI        = 256      # URI [RFC7553]
    CAA        = 257      # Certification Authority Restriction [RFC6844]
    AVC        = 258      # Visibility and Control [AVC/avc-completed-template]
    DOA        = 259      # Digital Object Architecture [DOA/doa-completed-template]
    AMTRELAY   = 260      # Multicast Tunnelling Relay [draft-ietf-mboned-driad-amt-discovery]
    TA         = 32768    # DNSSEC Trust Authorities [Weiler] 2005-12-13
    DLV        = 32769    # DNSSEC Lookaside Validation [RFC4431]
    WINS       = 65281    # WINS records (WINS Lookup record) [MS DNS]
    WINSR      = 65282    # WINSR records (WINS Reverse Lookup record) [MS DNS]
    UNKNOWN    = 65535    # Non-standard, implemented for this module.
}
#EndRegion '.\enum\RecordType.ps1' 94
#Region '.\enum\Selector.ps1' 0
enum Selector {
    FullCertificate
    SubjectPublicKeyInfo
}
#EndRegion '.\enum\Selector.ps1' 5
#Region '.\enum\SINKCoding.ps1' 0
enum SINKCoding {
    Reserved        = 0
    SNMPASN1        = 1
    OSIASN11990     = 2
    OSIASN11994     = 3
    PrivateAbstract = 63
    DNSRR           = 64
    MIME            = 65
    TextTagged      = 66
    PrivateFormat   = 254
}
#EndRegion '.\enum\SINKCoding.ps1' 12
#Region '.\enum\SINKMIMESubCoding.ps1' 0
enum SINKMIMESubCoding {
    SevenBit        = 1
    EightBit        = 2
    Binary          = 3
    QuotedPrintable = 4
    Base64          = 5
    Private         = 254
}
#EndRegion '.\enum\SINKMIMESubCoding.ps1' 9
#Region '.\enum\SINKPrivateAbstractSubCoding.ps1' 0
enum SINKSubCoding {
    Reserved     = 0
    BER          = 1
    DER          = 2
    PER          = 3
    PERUnaligned = 4
    CER          = 5
}
#EndRegion '.\enum\SINKPrivateAbstractSubCoding.ps1' 9
#Region '.\enum\SINKTextSubCoding.ps1' 0
enum SINKTextSubCoding {
    ASCII               = 1
    UTF7                = 2
    UTF8                = 3
    ASCIIWithMIMEHeader = 4
    Private             = 254
}
#EndRegion '.\enum\SINKTextSubCoding.ps1' 8
#Region '.\enum\SSHAlgorithm.ps1' 0
enum SSHAlgorithm {
    RSA     = 1    # [RFC4255]
    DSS     = 2    # [RFC4255]
    ECDSA   = 3    # [RFC6594]
    ED25519 = 4    # [RFC7479]
}
#EndRegion '.\enum\SSHAlgorithm.ps1' 7
#Region '.\enum\SSHFPType.ps1' 0
enum SSHFPType {
    SHA1   = 1    # [RFC4255]
    SHA256 = 2    # [RFC6594]
}
#EndRegion '.\enum\SSHFPType.ps1' 5
#Region '.\enum\TKEYMode.ps1' 0
enum TKEYMode {
    ServerAssignment   = 1    # Server assignment [RFC2930]
    DH                 = 2    # Diffie-Hellman Exchange [RFC2930]
    GSSAPI             = 3    # GSS-API negotiation [RFC2930]
    ResolverAssignment = 4    # Resolver assignment [RFC2930]
    KeyDeletion        = 5    # Key deletion [RFC2930]
}
#EndRegion '.\enum\TKEYMode.ps1' 8
#Region '.\enum\WINSMappingFlag.ps1' 0
enum WINSMappingFlag {
    Replicated = 0
    LocalOnly  = 65536
}
#EndRegion '.\enum\WINSMappingFlag.ps1' 5
#Region '.\enum\ZONEMDDigestType.ps1' 0
enum ZONEMDDigestType {
    SHA384 = 1
}
#EndRegion '.\enum\ZONEMDDigestType.ps1' 4
#Region '.\class\TransformDnsName.ps1' 0
#using namespace System.Management.Automation

class TransformDnsName : ArgumentTransformationAttribute {
    [Object] Transform(
        [EngineIntrinsics] $engineIntrinsics,
        [Object]           $inputData
    ) {
        $name = $inputData.ToString()

        if ($name -eq '.') {
            return $name
        }

        try {
            return [System.Globalization.IdnMapping]::new().GetAscii($name)
        } catch {
            return $name
        }
    }
}
#EndRegion '.\class\TransformDnsName.ps1' 21
#Region '.\class\ValidateDnsName.ps1' 0
#using namespace System.Management.Automation

class ValidateDnsName : ValidateEnumeratedArgumentsAttribute {
    Hidden $nameRegex = '^([A-Z0-9]|_[A-Z])(([\w\-]{0,61})[^_\-])?(\.([A-Z0-9]|_[A-Z])(([\w\-]{0,61})[^_\-])?)*$|^\.$'

    ValidateDnsName() { }

    [void] ValidateElement(
        [Object]$element
    ) {
        if (-not ([IPAddress]::TryParse($element, [ref]$null)) -and $element -notmatch $this.nameRegex) {
            $errorRecord = [ErrorRecord]::new(
                [ArgumentException]::new('Invalid name format'),
                'InvalidDnsName',
                [ErrorCategory]::InvalidArgument,
                $element
            )
            throw $errorRecord
        }
    }
}
#EndRegion '.\class\ValidateDnsName.ps1' 22
#Region '.\class\0.Top\AngularDistance.ps1' 0
class AngularDistance {
    [Int64]   $Degrees
    [Int64]   $Minutes
    [Decimal] $Seconds
    [string]  $Direction

    hidden static [Int64] $Equator = 2147483648
    hidden static [Int64] $PrimeMeridian = 2147483648

    AngularDistance([UInt32]$value, [DistanceType]$distanceType) {
        $this.Direction = switch ($distanceType) {
            'Latitude' {
                ('S', 'N')[$value -gt [AngularDistance]::Equator]
            }
            'Longitude' {
                ('W', 'E')[$value -gt [AngularDistance]::PrimeMeridian]
            }
        }

        $value = [Math]::Abs($value - 2147483648)

        $remainder = $value % (1000 * 60 * 60)
        $this.Degrees = ($value - $remainder) / (1000 * 60 * 60)
        $value = $remainder

        $remainder = $value % (1000 * 60)
        $this.Minutes = ($value - $remainder) / (1000 * 60)
        $value = $remainder

        $this.Seconds = $value / 1000
    }

    [UInt32] ToUInt32() {
        $value = (
            ($this.Seconds * 1000) +
            ($this.Minutes * 1000 * 60) +
            ($this.Degrees * 1000 * 60 * 60)
        )

        if ($this.Direction -in 'N', 'E') {
            $value = 2147483648 + $value
        } else {
            $value = 2147483648 - $value
        }

        return $value
    }

    [string] ToString() {
        return '{0} {1} {2:N3} {3}' -f @(
            $this.Degrees
            $this.Minutes
            $this.Seconds
            $this.Direction
        )
    }

    [string] ToLongString() {
        return '{0} degrees {1} minutes {2:N3} seconds {3}' -f @(
            $this.Degrees
            $this.Minutes
            $this.Seconds
            $this.Direction
        )
    }
}
#EndRegion '.\class\0.Top\AngularDistance.ps1' 67
#Region '.\class\0.Top\DnsRecordType.ps1' 0
class DnsRecordType : IComparable, IEquatable[Object] {
    [string] $Name
    [UInt16] $TypeID

    DnsRecordType(
        [RecordType] $value
    ) {
        if ($value -eq 'NSAPPTR') {
            $this.Name = 'NSAP-PTR'
        } else {
            $this.Name = $value
        }

        $this.TypeId = $value
    }

    DnsRecordType(
        [string] $value
    ) {
        if ($value -eq 'NSAPPTR') {
            $this.Name = 'NSAP-PTR'
        } else {
            $this.Name = $value
        }

        $value = $value.ToUpper().Trim()
        if ($value -eq 'NSAP-PTR') {
            $this.TypeID = 23
        } elseif ([RecordType].IsEnumDefined($value)) {
            $this.TypeID = [RecordType]$value
        } elseif ($value -match '^TYPE(\d+)$') {
            $this.TypeID = $matches[1]
        } else {
            throw 'Unable to parse record type to a type ID'
        }
    }

    DnsRecordType(
        [int] $value
    ) {
        $this.TypeID = $value
        if ([RecordType].IsEnumDefined($value)) {
            if ($value -eq 23) {
                $this.Name = 'NSAP-PTR'
            } else {
                $this.Name = [RecordType]$value
            }
        } else {
            $this.Name = 'TYPE{0}' -f $value
        }
    }

    hidden static [UInt16] op_Implicit([DnsRecordType] $dnsRecordType) {
        return [int]$dnsRecordType.TypeID
    }

    # Hack to support more than one cast
    hidden static [RecordType] op_Implicit([Object] $dnsRecordType) {
        return [RecordType]$dnsRecordType.TypeID
    }

    [int] CompareTo(
        [Object] $object
    ) {
        [UInt16]$uint16 = 0
        if ($object -is [DnsRecordType]) {
            return $this.TypeID.CompareTo($object.TypeID)
        } elseif ($object -is [RecordType]) {
            return $this.TypeID.CompareTo([UInt16]$object)
        } elseif ([int]::TryParse($object, [ref]$uint16)) {
            return $this.TypeID.CompareTo($uint16)
        } elseif ($object -is [string]) {
            try {
                return $this.TypeID.CompareTo(([DnsRecordType]$object).TypeID)
            } catch {
                throw 'Invalid record type'
            }
        } else {
            throw 'Invalid comparison'
        }
    }

    [bool] Equals(
        [Object] $object
    ) {
        return $this.CompareTo($object) -eq 0
    }

    [string] ToString() {
        return $this.Name
    }
}
#EndRegion '.\class\0.Top\DnsRecordType.ps1' 93
#Region '.\class\0.Top\EndianBinaryReader.ps1' 0
#using namespace System.Collections.Generic
#using namespace System.Globalization
#using namespace System.IO
#using namespace System.Text

class EndianBinaryReader : BinaryReader {
    [bool] $ConvertIdnToUnicode = $true

    hidden [IdnMapping] $idnMapping = [IdnMapping]::new()

    EndianBinaryReader([Stream]$BaseStream) : base($BaseStream) { }

    [UInt16] ReadUInt16(
        [bool] $isBigEndian
    ) {
        if ($isBigEndian) {
            return [UInt16](([UInt16]$this.ReadByte() -shl 8) -bor $this.ReadByte())
        } else {
            return $this.ReadUInt16()
        }
    }

    [UInt32] ReadUInt32(
        [bool] $isBigEndian
    ) {
        if ($isBigEndian) {
            return [UInt32](
                ([UInt32]$this.ReadByte() -shl 24) -bor
                ([UInt32]$this.ReadByte() -shl 16) -bor
                ([UInt32]$this.ReadByte() -shl 8) -bor
                $this.ReadByte())
        } else {
            return $this.ReadUInt32()
        }
    }

    [UInt64] ReadUInt48() {
        return $this.ReadUInt48($false)
    }

    [UInt64] ReadUInt48(
        [bool] $isBigEndian
    ) {
        if ($isBigEndian) {
            return [UInt64](
                ([UInt64]$this.ReadByte() -shl 40) -bor
                ([UInt64]$this.ReadByte() -shl 32) -bor
                ([UInt64]$this.ReadByte() -shl 24) -bor
                ([UInt64]$this.ReadByte() -shl 16) -bor
                ([UInt64]$this.ReadByte() -shl 8) -bor
                $this.ReadByte())
        } else {
            return [UInt64]($this.ReadByte() -bor
                ([UInt64]$this.ReadByte() -shl 8) -bor
                ([UInt64]$this.ReadByte() -shl 16) -bor
                ([UInt64]$this.ReadByte() -shl 24) -bor
                ([UInt64]$this.ReadByte() -shl 32) -bor
                ([UInt64]$this.ReadByte() -shl 40))
        }
    }

    [UInt64] ReadUInt64(
        [bool] $isBigEndian
    ) {
        if ($isBigEndian) {
            return [UInt64](
                ([UInt64]$this.ReadByte() -shl 56) -bor
                ([UInt64]$this.ReadByte() -shl 48) -bor
                ([UInt64]$this.ReadByte() -shl 40) -bor
                ([UInt64]$this.ReadByte() -shl 32) -bor
                ([UInt64]$this.ReadByte() -shl 24) -bor
                ([UInt64]$this.ReadByte() -shl 16) -bor
                ([UInt64]$this.ReadByte() -shl 8) -bor
                $this.ReadByte())
        } else {
            return $this.ReadUInt64()
        }
    }

    [byte] PeekByte() {
        $value = $this.ReadByte()
        $this.BaseStream.Seek(-1, 'Current')
        return $value
    }

    [IPAddress] ReadIPAddress() {
        return [IPAddress]::new($this.ReadBytes(4))
    }

    [IPAddress] ReadIPv6Address() {
        return [IPAddress]::new($this.ReadBytes(16))
    }

    # http://www.ietf.org/rfc/rfc1035.txt
    [string] ReadDnsCharacterString() {
        $length = 0
        return $this.ReadDnsCharacterString([ref]$length)
    }

    [string] ReadDnsCharacterString(
        [ref] $Length
    ) {
        [Char[]]$escapeChars = @(
            92
            34
        )
        [Char[]]$replaceChars = @(
            10
            13
        )

        $stringLength = $this.ReadByte()
        $Length.Value = $stringLength + 1

        $string = [string]::new($this.ReadChars($stringLength))

        foreach ($escapeChar in $escapeChars) {
            $string = $string.Replace([string]$escapeChar, ('\{0}' -f $escapeChar))
        }
        foreach ($replaceChar in $replaceChars) {
            $string = $string.Replace([string]$replaceChar, ('\{0:000}' -f [Int]$replaceChar))
        }

        return $string
    }

    [UInt16[]] ReadBitMap(
        [int] $length
    ) {
        [UInt16[]]$bits = while ($length -gt 0) {
            $windowNumber = $this.ReadByte()
            $bitMapLength = $this.ReadByte()
            $bytes = $this.ReadBytes($bitMapLength)

            $binaryString = [StringBuilder]::new()
            foreach ($byte in $bytes) {
                $null = $binaryString.Append(
                    [Convert]::ToString($byte, 2).PadLeft(8, '0')
                )
            }

            for ($i = 0; $i -lt $binaryString.Length; $i++) {
                if ($binaryString[$i] -eq '1') {
                    $i + (256 * $windowNumber)
                }
            }

            $length -= 2 + $bitMapLength
        }

        return $bits
    }

    # DNS messages implement compression to avoid bloat by repeated use of labels.
    #
    # If a label occurs elsewhere in the message a flag is set and an offset recorded as follows:
    #
    # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    # | 1 1| OFFSET |
    # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #
    # http://www.ietf.org/rfc/rfc1035.txt
    #
    [string] ReadDnsDomainName() {
        $name = [StringBuilder]::new()
        [UInt64]$CompressionStart = 0

        if ($this.BaseStream.Position -eq $this.BaseStream.Length) {
            return ''
        }

        while ($this.PeekByte() -ne 0) {
            $length = $this.ReadByte()

            if (($length -band [MessageCompression]::Enabled) -eq [MessageCompression]::Enabled) {
                if ($compressionStart -eq 0) {
                    $compressionStart = $this.BaseStream.Position
                }

                # Remove the compression flag bits to calculate the offset value (relative to the start of the message)
                [UInt16]$offset = ([UInt16]($length -bxor [MessageCompression]::Enabled) -shl 8) -bor $this.ReadByte()
                $null = $this.BaseStream.Seek($offset, 'Begin')
            } else {
                $null = $name.Append($this.ReadChars($length)).Append('.')
            }
        }
        if ($compressionStart -gt 0) {
            $null = $this.BaseStream.Seek($compressionStart, 'Begin')
        }

        $null = $this.ReadByte()

        if ($name[-1] -ne '.') {
            $null = $name.Append('.')
        }

        $name = $name.ToString()
        if ($this.ConvertIdnToUnicode) {
            if ($name -eq '.') {
                return $name
            }
            if ($name -match 'xn--') {
                try {
                    return $this.idnMapping.GetUnicode($name)
                } catch {
                    return $name
                }
            } else {
                return $name
            }
        } else {
            return $name
        }
    }

    [string] ReadDnsDomainName(
        [ref] $Length
    ) {
        $start = $this.BaseStream.Position
        $value = $this.ReadDnsDomainName()
        $end = $this.BaseStream.Position
        $Length.Value = $end - $start

        return $value
    }

    # RFC 1034:
    #
    # "Internally, programs that manipulate domain names should represent them
    # as sequences of labels, where each label is a length octet followed by
    # an octet string. Because all domain names end at the root, which has a
    # null string for a label, these internal representations can use a length
    # byte of zero to terminate a domain name."
    #
    # RFC 1035:
    #
    # "<domain-name> is a domain name represented as a series of labels, and
    # terminated by a label with zero length. <character-string> is a single
    # length octet followed by that number of characters. <character-string>
    # is treated as binary information, and can be up to 256 characters in
    # length (including the length octet)."
    #
    # http://www.ietf.org/rfc/rfc1034.txt
    # http://www.ietf.org/rfc/rfc1035.txt
    #
    static [byte[]] GetDnsDomainNameBytes(
        [string] $Name
    ) {
        # Drop any trailing . characters from the name. They are no longer necessary all names must be absolute by this point.
        $Name = $Name.TrimEnd('.')

        $bytes = [List[byte]]::new()
        if ($Name) {
            foreach ($label in $Name.Split('.')) {
                $bytes.Add($label.Length)
                $bytes.AddRange([byte[]][Char[]]$label)
            }
        }
        # Add a zero length root label
        $bytes.Add(0)

        return $bytes.ToArray()
    }
}
#EndRegion '.\class\0.Top\EndianBinaryReader.ps1' 265
#Region '.\class\0.Top\EndianBitConverter.ps1' 0
#using namespace System.Text

class EndianBitConverter {
    static [byte[]] GetBytes(
        [UInt16]  $value,
        [bool] $isBigEndian
    ) {
        if ([BitConverter]::IsLittleEndian -eq $isBigEndian) {
            return [BitConverter]::GetBytes(
                [IPAddress]::HostToNetworkOrder([int]$value)
            )[2, 3]
        } else {
            return [BitConverter]::GetBytes($value)
        }
    }

    static [byte[]] GetBytes(
        [UInt32]  $value,
        [bool] $isBigEndian
    ) {
        if ([BitConverter]::IsLittleEndian -eq $isBigEndian) {
            return [BitConverter]::GetBytes(
                [IPAddress]::HostToNetworkOrder([Int64]$value)
            )[4..7]
        } else {
            return [BitConverter]::GetBytes($value)
        }
    }

    static [string] ToBinary(
        [byte[]] $bytes
    ) {
        $string = [StringBuilder]::new()
        foreach ($byte in $bytes) {
            $string.Append(
                [Convert]::ToString($byte, 2).PadLeft(8, '0')
            )
        }
        return $string.ToString()
    }

    static [string] ToHexadecimal(
        [byte[]] $bytes
    ) {
        $string = [StringBuilder]::new()
        foreach ($byte in $bytes) {
            $string.AppendFormat('{0:X2}' -f $byte)
        }
        return $string.ToString()
    }

    static [string] ToBase32String(
        [byte[]] $bytes
    ) {
        $base32Characters = '0123456789ABCDEFGHIJKLMNOPQRSTUV'

        if ($bytes.Count -eq 0) {
            return ''
        }

        $binaryString = ''
        foreach ($byte in $bytes) {
            $binaryString += [Convert]::ToString($byte, 2).PadLeft(8, '0')
        }

        $chars = foreach ($value in $binaryString -split '(?<=\G.{5})') {
            if ($value) {
                $byte = [Convert]::ToByte($value.PadRight('0', 5), 2)
                $base32Characters[$byte]
            }
        }

        return [string]::new($chars)
    }
}
#EndRegion '.\class\0.Top\EndianBitConverter.ps1' 76
#Region '.\class\1.MessageParts\DnsHeader.ps1' 0
class DnsHeader {
    <#
                                       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 | RCODE |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | QDCOUNT |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | ANCOUNT |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | NSCOUNT |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | ARCOUNT |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [UInt16]      $ID
    [QR]          $QR
    [OpCode]      $OpCode
    [HeaderFlags] $Flags
    [RCode]       $RCode
    [UInt16]      $QuestionCount
    [UInt16]      $AnswerCount
    [UInt16]      $AuthorityCount
    [UInt16]      $AdditionalCount

    DnsHeader() { }

    DnsHeader(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.ID = $binaryReader.ReadUInt16($true)

        $value = $binaryReader.ReadUInt16($true)
        $this.QR = $value -band 0x8000
        $this.OpCode = ($value -band 0x7800) -shr 11
        $this.Flags = $value -band 0x07B0
        $this.RCode = $value -band 0x000F

        $this.QuestionCount = $binaryReader.ReadUInt16($true)
        $this.AnswerCount = $binaryReader.ReadUInt16($true)
        $this.AuthorityCount = $binaryReader.ReadUInt16($true)
        $this.AdditionalCount = $binaryReader.ReadUInt16($true)
    }

    DnsHeader(
        [bool] $recursionDesired,
        [UInt16]  $questionCount
    ) {
        $this.ID = Get-Random -Minimum 0 -Maximum ([UInt16]::MaxValue + 1)

        if ($recursionDesired) {
            $this.Flags = [HeaderFlags]::RD
        }
        $this.QuestionCount = $questionCount
    }

    [byte[]] ToByteArray() {
        $bytes = [byte[]]::new(12)

        $bytes[0], $bytes[1] = [EndianBitConverter]::GetBytes($this.ID, $true)

        # QR, Flags, OpCode and RCode
        [UInt16]$value = (
            $this.QR -bor
            ([UInt16]$this.OpCode -shl 11) -bor
            $this.Flags -bor
            $this.RCode
        )
        $bytes[2], $bytes[3] = [EndianBitConverter]::GetBytes($value, $true)

        $bytes[4], $bytes[5] = [EndianBitConverter]::GetBytes($this.QuestionCount, $true)
        $bytes[6], $bytes[7] = [EndianBitConverter]::GetBytes($this.AnswerCount, $true)
        $bytes[8], $bytes[9] = [EndianBitConverter]::GetBytes($this.AuthorityCount, $true)
        $bytes[10], $bytes[11] = [EndianBitConverter]::GetBytes($this.AdditionalCount, $true)

        return $bytes
    }

    [string] ToString() {
        return 'ID: {0} OpCode: {1} RCode: {2} Flags: {3} Query: {4} Answer: {5} Authority: {6} Additional: {7}' -f @(
            $this.ID
            $this.OpCode.ToString().ToUpper()
            $this.RCode.ToString().ToUpper()
            $this.Flags.ToString().ToUpper()
            $this.QuestionCount
            $this.AnswerCount
            $this.AuthorityCount
            $this.AdditionalCount
        )
    }
}
#EndRegion '.\class\1.MessageParts\DnsHeader.ps1' 96
#Region '.\class\1.MessageParts\DnsQuestion.ps1' 0
#using namespace System.Collections.Generic

class DnsQuestion {
    <#
                                       1 1 1 1 1 1
         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       / QNAME /
       / /
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | QTYPE |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | QCLASS |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string]        $Name
    [DnsRecordType] $RecordType
    [Object]        $RecordClass

    DnsQuestion() { }

    DnsQuestion(
        [string]      $recordName,
        [RecordType]  $type,
        [RecordClass] $class
    ) {
        $this.Name = $recordName
        $this.RecordType = $type
        $this.RecordClass = $class
    }

    DnsQuestion(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Name = $binaryReader.ReadDnsDomainName()
        $this.RecordType = [DnsRecordType]$binaryReader.ReadUInt16($true)

        if ($this.RecordType -eq 'OPT') {
            $this.RecordClass = $binaryReader.ReadUInt16($true)
        } else {
            $this.RecordClass = [RecordClass]$binaryReader.ReadUInt16($true)
        }
    }

    hidden [byte[]] ToByteArray() {
        $bytes = [List[byte]]::new()

        $bytes.AddRange([EndianBinaryReader]::GetDnsDomainNameBytes($this.Name))
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.RecordType, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.RecordClass, $true))

        return $bytes.ToArray()
    }

    [string] ToString() {
        return '{0,-29} {1,-5} {2,-5}' -f @(
            $this.Name
            $this.RecordClass
            $this.RecordType
        )
    }
}
#EndRegion '.\class\1.MessageParts\DnsQuestion.ps1' 64
#Region '.\class\1.MessageParts\DnsResourceRecord.ps1' 0
#using namespace System.Collections.Generic
#using namespace System.IO

class DnsResourceRecord : IEquatable[Object] {
    <#
                                      1 1 1 1 1 1
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       / NAME /
       / /
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | TYPE |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | CLASS |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | TTL |
       | |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
       | RDLENGTH |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
       / RDATA /
       / /
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string]        $Name
    [UInt32]        $TTL
    [RecordClass]   $RecordClass      = [RecordClass]::IN
    [DnsRecordType] $RecordType       = 'EMPTY'
    [string]        $RecordData
    [UInt16]        $RecordDataLength

    hidden [bool] $IsTruncated

    DnsResourceRecord() {
        $thisTypeName = $this.GetType().Name
        if ($thisTypeName -ne 'DnsResourceRecord') {
            $this.RecordType = $thisTypeName -replace '^Dns|Record$'
        }
    }

    DnsResourceRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Name = $dnsResourceRecord.Name
        $this.RecordType = $dnsResourceRecord.RecordType

        $this.RecordClass = $binaryReader.ReadUInt16($true)
        $this.TTL = $binaryReader.ReadUInt32($true)
        $this.RecordDataLength = $binaryReader.ReadUInt16($true)

        if ($binaryReader.BaseStream.Capacity -ge ($binaryReader.BaseStream.Position + $this.RecordDataLength)) {
            $this.ReadRecordData($binaryReader)
        }
        $this.RecordData = $this.RecordDataToString()
    }

    static [DnsResourceRecord] Parse(
        [byte[]] $bytes
    ) {
        $binaryReader = [EndianBinaryReader][MemoryStream]$bytes

        return [DnsResourceRecord]::Parse($binaryReader)
    }

    static [DnsResourceRecord] Parse(
        [EndianBinaryReader] $binaryReader
    ) {
        $resourceRecord = [DnsResourceRecord]::new()
        $resourceRecord.Name = $binaryReader.ReadDnsDomainName()

        if ($binaryReader.BaseStream.Capacity -ge ($binaryReader.BaseStream.Position + 10)) {
            $resourceRecord.RecordType = [int]$binaryReader.ReadUInt16($true)
            $typeName = 'Dns{0}Record' -f $resourceRecord.RecordType

            if ($typeName -as [Type]) {
                return ($typeName -as [Type])::new(
                    $resourceRecord,
                    $binaryReader
                )
            } else {
                # Avoids a race condition when loading classes.
                return ('DnsUNKNOWNRecord' -as [Type])::new(
                    $resourceRecord,
                    $binaryReader
                )
            }
        } else {
            $resourceRecord.IsTruncated = $true
        }

        return $resourceRecord
    }

    # Child classes must override this method
    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $binaryReader.ReadBytes($this.RecordDataLength)
    }

    # Child classes must override this method
    hidden [string] RecordDataToString() {
        return ''
    }

    # Child classes should override this method if appropriate
    hidden [byte[]] RecordDataToByteArray(
        [bool] $useCompressedNames
    ) {
        return [byte[]]::new($this.RecordDataLength)
    }

    [byte[]] ToByteArray() {
        return $this.ToByteArray($true)
    }

    [byte[]] ToByteArray(
        [bool] $useCompressedNames
    ) {
        $bytes = [List[byte]]::new()

        if ($useCompressedNames) {
            $bytes.AddRange([byte[]](0xC0, 0x0C))
        } else {
            $bytes.AddRange([EndianBinaryReader]::GetDnsDomainNameBytes($this.Name))
        }

        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.RecordType, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.RecordClass, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt32]$this.TTL, $true))

        $recordDataBytes = $this.RecordDataToByteArray($useCompressedNames)

        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$recordDataBytes.Count, $true))
        $bytes.AddRange($recordDataBytes)

        return $bytes.ToArray()
    }

    [bool] Equals(
        [Object] $object
    ) {
        return $this.ToString() -eq $object.ToString()
    }

    [string] ToString() {
        return '{0,-29} {1,-10} {2,-5} {3,-10} {4}' -f @(
            $this.Name
            $this.TTL
            $this.RecordClass
            $this.RecordType
            $this.RecordData
        )
    }
}
#EndRegion '.\class\1.MessageParts\DnsResourceRecord.ps1' 158
#Region '.\class\2.RecordTypes\DnsA6Record.ps1' 0
class DnsA6Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFIX LEN | |
        +--+--+--+--+--+--+--+--+ |
        / ADDRESS SUFFIX /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PREFIX NAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [byte]      $PrefixLength
    [IPAddress] $AddressSuffix
    [string]    $PrefixName

    DnsA6Record() : base() { }
    DnsA6Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.PrefixLength = $binaryReader.ReadByte()

        $addressSuffixBytes = [byte[]]::new(16)

        $length = [Math]::Ceiling((128 - $this.PrefixLength) / 8)

        [Array]::Copy(
            $binaryReader.ReadBytes($length),
            0,
            $addressSuffixBytes,
            16 - $length,
            $length
        )

        $this.AddressSuffix = [IPAddress]::new($addressSuffixBytes)

        if ($this.RecordDataLength - $length - 1 -gt 0) {
            $this.PrefixName = $binaryReader.ReadDnsDomainName()
        }
    }

    hidden [string] RecordDataToString() {
        $ipAddress = '{0}' -f $this.AddressSuffix.IPAddressToString
        if ($ipAddress -eq '::') {
            $ipAddress = ''
        }

        return (
            '{0} {1} {2}' -f @(
                $this.PrefixLength
                $ipAddress
                $this.PrefixName
            )
        ).Trim()
    }
}
#EndRegion '.\class\2.RecordTypes\DnsA6Record.ps1' 68
#Region '.\class\2.RecordTypes\DnsAAAARecord.ps1' 0
class DnsAAAARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESS |
        | |
        | |
        | |
        | |
        | |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [IPAddress] $IPAddress

    DnsAAAARecord() : base() { }
    DnsAAAARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.IPAddress = $binaryReader.ReadIPv6Address()
    }

    hidden [string] RecordDataToString() {
        return $this.IPAddress.IPAddressToString
    }
}
#EndRegion '.\class\2.RecordTypes\DnsAAAARecord.ps1' 38
#Region '.\class\2.RecordTypes\DnsAFSDBRecord.ps1' 0
class DnsAFSDBRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SUBTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / HOSTNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1183.txt
    #>


    [AFSDBSubType] $SubType
    [UInt16]       $SubTypeValue
    [string]       $Hostname

    DnsAFSDBRecord() : base() { }
    DnsAFSDBRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.SubTypeValue = $binaryReader.ReadUInt16($true)
        if ([Enum]::IsDefined([AFSDBSubType], [int]$this.SubTypeValue)) {
            $this.SubType = [int]$this.SubTypeValue
        }
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.SubTypeValue
            $this.Hostname
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsAFSDBRecord.ps1' 45
#Region '.\class\2.RecordTypes\DnsAMTRelayRecord.ps1' 0
class DnsAMTRELAYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PRECEDENCE | D| TYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / RELAY /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://tools.ietf.org/html/draft-ietf-mboned-driad-amt-discovery-06
    #>


    [byte]         $Precedence
    [bool]      $DiscoveryOptional
    [AMTRelayType] $Type
    [string]       $Relay

    DnsAMTRELAYRecord() : base() { }
    DnsAMTRELAYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Precedence = $binaryReader.ReadByte()

        $discoveryAndType = $binaryReader.ReadByte()

        $this.DiscoveryOptional = $discoveryAndType -band 0x80
        $this.Type = $discoveryAndType -band 0x7F

        if ($this.Type -ne 'None') {
            $this.Relay = switch ($this.Type) {
                IPv4       {
                    $binaryReader.ReadIPAddress()
                    break
                }
                IPv6       {
                    $binaryReader.ReadIPv6Address()
                    break
                }
                DomainName {
                    $binaryReader.ReadDnsDomainName()
                    break
                }
            }
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.Precedence
            [byte]$this.DiscoveryOptional
            $this.Type
            $this.Relay
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsAMTRelayRecord.ps1' 66
#Region '.\class\2.RecordTypes\DnsAPLRecord.ps1' 0
class DnsAPLRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESSFAMILY |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFIX | N| AFDLENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / AFDPART /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/html/rfc3123
    #>


    [PSObject[]] $List

    DnsAPLRecord() : base() { }
    DnsAPLRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        if ($this.RecordDataLength -gt 0) {
            $listLength = $this.RecordDataLength

            $this.List = while ($listLength -gt 0) {
                $addressFamily = [IanaAddressFamily]$binaryReader.ReadUInt16($true)
                $prefix = $binaryReader.ReadByte()
                $negationAndLength = $binaryReader.ReadByte()

                $item = [PSCustomObject]@{
                    AddressFamily = $addressFamily
                    Prefix        = $prefix
                    Negation      = [bool]($negationAndLength -band 0x80)
                    AddressLength = $negationAndLength -band 0x7F
                    Address       = $null
                }
                $addressBytes = switch ($item.AddressFamily) {
                    'IPv4' { [byte[]]::new(4) }
                    'IPv6' { [byte[]]::new(16) }
                }

                [Array]::Copy(
                    $binaryReader.ReadBytes($item.AddressLength),
                    0,
                    $addressBytes,
                    0,
                    $item.AddressLength
                )
                $item.Address = [IPAddress]::new($addressBytes)

                $item

                $listLength -= 4 + $item.AddressLength
            }
        }
    }

    hidden [string] RecordDataToString() {
        $values = foreach ($item in $this.List) {
            '{0}{1:D}:{2}/{3}' -f @(
                ('', '!')[$item.Negation]
                $item.AddressFamily
                $item.Address
                $item.Prefix
            )
        }
        return $values -join ' '
    }
}
#EndRegion '.\class\2.RecordTypes\DnsAPLRecord.ps1' 79
#Region '.\class\2.RecordTypes\DnsARecord.ps1' 0
class DnsARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [IPAddress] $IPAddress

    DnsARecord() : base() { }
    DnsARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.IPAddress = $binaryReader.ReadIPAddress()
    }

    hidden [string] RecordDataToString() {
        return $this.IPAddress.IPAddressToString
    }
}
#EndRegion '.\class\2.RecordTypes\DnsARecord.ps1' 31
#Region '.\class\2.RecordTypes\DnsATMARecord.ps1' 0
#using namespace System.Text

class DnsATMARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FORMAT | |
        +--+--+--+--+--+--+--+--+ |
        / ATMADDRESS /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [ATMAFormat] $Format
    [string]     $ATMAAddress

    DnsATMARecord() : base() { }
    DnsATMARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }


    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Format = [ATMAFormat]$binaryReader.ReadByte()

        $length = $this.RecordDataLength - 1

        $this.ATMAAddress = switch ($this.Format) {
            'E164' {
                '+{0}' -f [string]::new($binaryReader.ReadChars($length))
                break
            }
            default {
                [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($length)).ToLower()
                break
            }
        }
    }

    hidden [string] RecordDataToString() {
        return $this.ATMAAddress
    }
}
#EndRegion '.\class\2.RecordTypes\DnsATMARecord.ps1' 51
#Region '.\class\2.RecordTypes\DnsAVCRecord.ps1' 0
class DnsAVCRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / AVC-DATA /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string[]]   $Data

    DnsAVCRecord() : base() { }
    DnsAVCRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = $this.RecordDataLength
        if ($length -gt 0) {
            $this.Data = do {
                $entryLength = 0

                $binaryReader.ReadDnsCharacterString([ref]$entryLength)

                $length -= $entryLength
            } until ($length -le 0)
        }
    }

    hidden [string] RecordDataToString() {
        return '"{0}"' -f ($this.Data -join '" "')
    }
}
#EndRegion '.\class\2.RecordTypes\DnsAVCRecord.ps1' 40
#Region '.\class\2.RecordTypes\DnsCAARecord.ps1' 0
class DnsCAARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS | /
        +--+--+--+--+--+--+--+--+ /
        / TAG /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / VALUE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/html/rfc6844
    #>


    [CAAFlag] $CAAFlag
    [string]  $Tag
    [string]  $Value

    DnsCAARecord() : base() { }
    DnsCAARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.CAAFlag = $binaryReader.ReadByte()

        $length = 0
        $this.Tag = $binaryReader.ReadDnsCharacterString([ref]$length)

        $this.Value = [string]::new(
            $binaryReader.ReadChars(
                $this.RecordDataLength - $length - 1
            )
        )
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1} "{2}"' -f @(
            $this.CAAFlag
            $this.Tag
            $this.Value
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCAARecord.ps1' 54
#Region '.\class\2.RecordTypes\DnsCDNSKEYRecord.ps1' 0
class DnsCDNSKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PROTOCOL | ALGORITHM |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLIC KEY /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        The flags field takes the following format, discussed in RFC 4034 2.1.1:
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | | Z| | S|
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        Where Z represents the ZoneKey bit, and S the SecureEntryPoint bit.
 
        http://www.ietf.org/rfc/rfc7344.txt
    #>


    [UInt16]              $Flags
    [bool]             $ZoneKey
    [bool]             $SecureEntryPoint
    [KEYProtocol]         $Protocol
    [EncryptionAlgorithm] $Algorithm
    [string]              $PublicKey

    DnsCDNSKEYRecord() : base() { }
    DnsCDNSKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Flags = $binaryReader.ReadUInt16($true)
        $this.ZoneKey = $this.Flags -band 0x0100
        $this.SecureEntryPoint = $this.Flags -band 0x0001
        $this.Protocol = $binaryReader.ReadByte()
        $this.Algorithm = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 4)
        $this.PublicKey = [Convert]::ToBase64String($bytes)

    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.Flags
            $this.Protocol
            $this.Algorithm
            $this.PublicKey -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCDNSKEYRecord.ps1' 67
#Region '.\class\2.RecordTypes\DnsCDSRecord.ps1' 0
class DnsCDSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEYTAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | DIGESTTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DIGEST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc7344.txt
    #>


    [UInt16]              $KeyTag
    [EncryptionAlgorithm] $Algorithm
    [DigestType]          $DigestType
    [string]              $Digest

    DnsCDSRecord() : base() { }
    DnsCDSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.KeyTag = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.DigestType = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 4)
        $this.Digest = [EndianBitConverter]::ToHexadecimal($bytes)
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.KeyTag
            $this.Algorithm
            $this.DigestType
            $this.Digest -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCDSRecord.ps1' 51
#Region '.\class\2.RecordTypes\DnsCERTRecord.ps1' 0
class DnsCERTRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | TYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEY TAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | |
        +--+--+--+--+--+--+--+--+ |
        / CERTIFICATE or CRL /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc4398.txt
    #>


    [CertificateType]     $CertificateType
    [UInt16]              $KeyTag
    [EncryptionAlgorithm] $Algorithm
    [string]              $Certificate

    DnsCERTRecord() : base() { }
    DnsCERTRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.CertificateType = $binaryReader.ReadUInt16($true)
        $this.KeyTag = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 5)
        $this.Certificate = [Convert]::ToBase64String($bytes)
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1:D} {2} {3}' -f @(
            $this.CertificateType
            $this.KeyTag
            $this.Algorithm
            $this.Certificate -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCERTRecord.ps1' 53
#Region '.\class\2.RecordTypes\DnsCNAMERecord.ps1' 0
class DnsCNAMERecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / CNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string] $Hostname

    DnsCNAMERecord() : base() { }
    DnsCNAMERecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCNAMERecord.ps1' 32
#Region '.\class\2.RecordTypes\DnsCSYNCRecord.ps1' 0
class DnsCSYNCRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SERIAL |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TYPE BIT MAP /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc7477.txt
    #>


    [UInt32]          $Serial
    [CSYNCFlags]      $Flags
    [DnsRecordType[]] $TypesToProcess


    DnsCSYNCRecord() : base() { }
    DnsCSYNCRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Serial = $binaryReader.ReadUInt32($true)
        $this.Flags = $binaryReader.ReadUInt16($true)

        $this.TypesToProcess = $binaryReader.ReadBitMap($this.RecordDataLength - 6)
    }

    hidden [string] RecordDataToString() {
        if ($this.TypesToProcess.Count -gt 0) {
            return '{0} {1:D} {2}' -f @(
                $this.Serial
                $this.Flags
                $this.TypesToProcess -join ' '
            )
        } else {
            return '{0} {1:D}' -f @(
                $this.Serial
                $this.Flags
            )
        }
    }
}
#EndRegion '.\class\2.RecordTypes\DnsCSYNCRecord.ps1' 56
#Region '.\class\2.RecordTypes\DnsDHCIDRecord.ps1' 0
class DnsDHCIDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / <anything> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc4701.txt
    #>


    [byte[]] $BinaryData

    DnsDHCIDRecord() : base() { }
    DnsDHCIDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.BinaryData = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return [Convert]::ToBase64String($this.BinaryData)
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDHCIDRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsDLVRecord.ps1' 0
class DnsDLVRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEYTAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | DIGESTTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DIGEST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc4431.txt
    #>


    [UInt16]              $KeyTag
    [EncryptionAlgorithm] $Algorithm
    [DigestType]          $DigestType
    [string]              $Digest

    DnsDLVRecord() : base() { }
    DnsDLVRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.KeyTag = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.DigestType = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 4)
        $this.Digest = [EndianBitConverter]::ToHexadecimal($bytes)
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.KeyTag
            $this.Algorithm
            $this.DigestType
            $this.Digest
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDLVRecord.ps1' 51
#Region '.\class\2.RecordTypes\DnsDNAMERecord.ps1' 0
class DnsDNAMERecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TARGET /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2672.txt
    #>


    [string] $Target

    DnsDNAMERecord() : base() { }
    DnsDNAMERecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Target = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Target
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDNAMERecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsDNSKEYRecord.ps1' 0
class DnsDNSKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PROTOCOL | ALGORITHM |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLIC KEY /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        The flags field takes the following format, discussed in RFC 4034 2.1.1:
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | | Z| | S|
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        Where Z represents the ZoneKey bit, and S the SecureEntryPoint bit.
 
        http://www.ietf.org/rfc/rfc3755.txt
        http://www.ietf.org/rfc/rfc4034.txt
    #>


    [UInt16]              $Flags
    [bool]             $ZoneKey
    [bool]             $SecureEntryPoint
    [KEYProtocol]         $Protocol
    [EncryptionAlgorithm] $Algorithm
    [string]              $PublicKey

    DnsDNSKEYRecord() : base() { }
    DnsDNSKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Flags = $binaryReader.ReadUInt16($true)
        $this.ZoneKey = $this.Flags -band 0x0100
        $this.SecureEntryPoint = $this.Flags -band 0x0001
        $this.Protocol = $binaryReader.ReadByte()
        $this.Algorithm = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 4)
        $this.PublicKey = [Convert]::ToBase64String($bytes)

    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.Flags
            $this.Protocol
            $this.Algorithm
            $this.PublicKey -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDNSKEYRecord.ps1' 68
#Region '.\class\2.RecordTypes\DnsDOARecord.ps1' 0
class DnsDOARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | DOA-ENTERPRISE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | DOA-TYPE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | DOA-LOCATION | /
        +--+--+--+--+--+--+--+--+ /
        / DOA-MEDIA-TYPE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DOA-DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://tools.ietf.org/html/draft-durand-doa-over-dns-03
 
        DOA Enterprise values are defined by:
 
        https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
    #>


    [UInt32]      $Enterprise
    [UInt32]      $Type
    [DOALocation] $Location
    [string]      $MediaType
    [string]      $Data

    DnsDOARecord() : base() { }
    DnsDOARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Enterprise = $binaryReader.ReadUInt32($true)
        $this.Type = $binaryReader.ReadUInt32($true)
        $this.Location = $binaryReader.ReadByte()

        $length = 0
        $this.MediaType = $binaryReader.ReadDnsCharacterString([ref]$length)

        $length = $this.RecordDataLength - 9 - $length
        $this.Data = [Convert]::ToBase64String($binaryReader.ReadBytes($length))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} {2:D} "{3}" {4}' -f @(
            $this.Enterprise
            $this.Type
            $this.Location
            $this.MediaType
            $this.Data
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDOARecord.ps1' 67
#Region '.\class\2.RecordTypes\DnsDSRecord.ps1' 0
class DnsDSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEYTAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | DIGESTTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DIGEST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc3658.txt
        http://www.ietf.org/rfc/rfc4034.txt
    #>


    [UInt16]              $KeyTag
    [EncryptionAlgorithm] $Algorithm
    [DigestType]          $DigestType
    [string]              $Digest

    DnsDSRecord() : base() { }
    DnsDSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.KeyTag = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.DigestType = $binaryReader.ReadByte()

        $bytes = $binaryReader.ReadBytes($this.RecordDataLength - 4)
        $this.Digest = [EndianBitConverter]::ToHexadecimal($bytes)
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.KeyTag
            $this.Algorithm
            $this.DigestType
            $this.Digest -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsDSRecord.ps1' 52
#Region '.\class\2.RecordTypes\DnsEIDRecord.ps1' 0
class DnsEIDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / EID /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 
        http://cpansearch.perl.org/src/MIKER/Net-DNS-Codes-0.11/extra_docs/draft-ietf-nimrod-dns-02.txt
    #>


    [string] $EID

    DnsEIDRecord() : base() { }
    DnsEIDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.EID = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength))
    }

    hidden [string] RecordDataToString() {
        return $this.EID
    }
}
#EndRegion '.\class\2.RecordTypes\DnsEIDRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsEUI48Record.ps1' 0
class DnsEUI48Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESS |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 
        http://cpansearch.perl.org/src/MIKER/Net-DNS-Codes-0.11/extra_docs/draft-ietf-nimrod-dns-02.txt
    #>


    [string] $Address

    DnsEUI48Record() : base() { }
    DnsEUI48Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Address = [BitConverter]::ToString($binaryReader.ReadBytes(6)).ToLower()
    }

    hidden [string] RecordDataToString() {
        return $this.Address
    }
}
#EndRegion '.\class\2.RecordTypes\DnsEUI48Record.ps1' 36
#Region '.\class\2.RecordTypes\DnsEUI64Record.ps1' 0
class DnsEUI64Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESS |
        | |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 
        http://cpansearch.perl.org/src/MIKER/Net-DNS-Codes-0.11/extra_docs/draft-ietf-nimrod-dns-02.txt
    #>


    [string] $Address

    DnsEUI64Record() : base() { }
    DnsEUI64Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Address = [BitConverter]::ToString($binaryReader.ReadBytes(8)).ToLower()
    }

    hidden [string] RecordDataToString() {
        return $this.Address
    }
}
#EndRegion '.\class\2.RecordTypes\DnsEUI64Record.ps1' 37
#Region '.\class\2.RecordTypes\DnsGIDRecord.ps1' 0
class DnsGIDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / GID /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        IANA-Reserved
    #>


    [byte[]] $Data

    DnsGIDRecord() : base() { }
    DnsGIDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Data = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return '\# {0} {1}' -f @(
            $this.Data.Length
            [EndianBitConverter]::ToHexadecimal($this.Data)
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsGIDRecord.ps1' 36
#Region '.\class\2.RecordTypes\DnsGPOSRecord.ps1' 0
class DnsGPOSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / LONGITUDE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / LATITUDE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ALTITUDE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1712.txt
    #>


    [string] $Longitude
    [string] $Latitude
    [string] $Altitude

    DnsGPOSRecord() : base() { }
    DnsGPOSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Longitude = $binaryReader.ReadDnsCharacterString()
        $this.Latitude = $binaryReader.ReadDnsCharacterString()
        $this.Altitude = $binaryReader.ReadDnsCharacterString()
    }

    hidden [string] RecordDataToString() {
        return '"{0}" "{1}" "{2}"' -f @(
            $this.Longitude
            $this.Latitude
            $this.Altitude
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsGPOSRecord.ps1' 48
#Region '.\class\2.RecordTypes\DnsHINFORecord.ps1' 0
class DnsHINFORecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / CPU /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / OS /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $CPU
    [string] $OS

    DnsHINFORecord() : base() { }
    DnsHINFORecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.CPU = $binaryReader.ReadDnsCharacterString()
        $this.OS = $binaryReader.ReadDnsCharacterString()
    }

    hidden [string] RecordDataToString() {
        return '"{0}" "{1}"' -f @(
            $this.CPU
            $this.OS
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsHINFORecord.ps1' 40
#Region '.\class\2.RecordTypes\DnsHIPRecord.ps1' 0
class DnsHIPRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | HIT LENGTH | PK ALGORITHM |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PUBLIC KEY LENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / HIT /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLIC KEY /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / RENDEZVOUS SERVERS /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc5205.txt
    #>


    [IPSECAlgorithm] $PublicKeyAlgorithm
    [string]         $HIT
    [string]         $PublicKey
    [string[]]       $RendezvousServers


    DnsHIPRecord() : base() { }
    DnsHIPRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $hitLength = $binaryReader.ReadByte()

        $this.PublicKeyAlgorithm = $binaryReader.ReadByte()

        $publicKeyLength = $binaryReader.ReadUInt16($true)

        $this.HIT = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($hitLength))
        $this.PublicKey = [Convert]::ToBase64String($binaryReader.ReadBytes($publicKeyLength))

        $length = $this.RecordDataLength - 4 - $hitLength - $publicKeyLength
        if ($length -gt 0) {
            $this.RendezvousServers = do {
                $entryLength = 0

                $binaryReader.ReadDnsDomainName([ref]$entryLength)

                $length -= $entryLength
            } until ($length -le 0)
        }
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1} {2} {3}' -f @(
            $this.PublicKeyAlgorithm
            $this.HIT
            $this.PublicKey
            $this.RendezvousServers -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsHIPRecord.ps1' 71
#Region '.\class\2.RecordTypes\DnsIPSECKEYRecord.ps1' 0
class DnsIPSECKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PRECEDENCE | GATEWAYTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | /
        +--+--+--+--+--+--+--+--+ /
        / GATEWAY /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLICKEY /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc4025.txt
    #>


    [byte]             $Precedence
    [IPSECGatewayType] $GatewayType
    [IPSECAlgorithm]   $Algorithm
    [string]           $Gateway
    [string]           $PublicKey

    DnsIPSECKEYRecord() : base() { }
    DnsIPSECKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Precedence = $binaryReader.ReadByte()
        $this.GatewayType = $binaryReader.ReadByte()
        $this.Algorithm = $binaryReader.ReadByte()

        $length = 0
        $this.Gateway = switch ($this.GatewayType) {
            IPv4       {
                $binaryReader.ReadIPAddress()
                $length = 4
                break
            }
            IPv6       {
                $binaryReader.ReadIPv6Address()
                $length = 16
                break
            }
            DomainName {
                $binaryReader.ReadDnsDomainName([ref]$length)
                break
            }
        }
        if ($this.Gateway.Length -eq 0) {
            $this.Gateway = '.'
        }

        $publicKeyLength = $this.RecordDataLength - $length - 3
        $this.PublicKey = [Convert]::ToBase64String($binaryReader.ReadBytes($publicKeyLength))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3} {4}' -f @(
            $this.Precedence
            $this.GatewayType
            $this.Algorithm
            $this.Gateway
            $this.PublicKey
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsIPSECKEYRecord.ps1' 77
#Region '.\class\2.RecordTypes\DnsISDNRecord.ps1' 0
class DnsISDNRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ISDNADDRESS /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SUBADDRESS /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1183.txt
    #>


    [string]     $ISDNAddress
    [string]     $SubAddress

    DnsISDNRecord() : base() { }
    DnsISDNRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = 0
        $this.ISDNAddress = $binaryReader.ReadDnsCharacterString([ref]$length)

        if ($this.RecordDataLength - $length -gt 0) {
            $this.SubAddress = $binaryReader.ReadDnsCharacterString()
        }
    }

    hidden [string] RecordDataToString() {
        if ($this.SubAddress) {
            return '"{0}" "{1}"' -f @(
                $this.ISDNAddress
                $this.SubAddress
            )
        } else {
            return '"{0}"' -f @(
                $this.ISDNAddress
            )
        }
    }
}
#EndRegion '.\class\2.RecordTypes\DnsISDNRecord.ps1' 50
#Region '.\class\2.RecordTypes\DnsKEYRecord.ps1' 0
class DnsKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PROTOCOL | ALGORITHM |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLIC KEY /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        The flags field takes the following format, discussed in RFC 2535 3.1.2:
 
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
        | A/C | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z | SIG |
        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    #>


    [UInt16]              $Flags
    [KEYAC]               $AuthenticationConfidentiality
    [UInt16]              $FlagsExtension
    [KEYNameType]         $NameType
    [bool]             $SignatoryField
    [KEYProtocol]         $Protocol
    [EncryptionAlgorithm] $Algorithm
    [string]              $PublicKey

    DnsKEYRecord() : base() { }
    DnsKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Flags = $binaryReader.ReadUInt16($true)
        $this.AuthenticationConfidentiality = [byte]($this.Flags -shr 14)

        if (($this.Flags -band 0x1000) -eq 0x1000) {
            $this.FlagsExtension = $binaryReader.ReadUInt16($true)
        }

        $this.NameType = ($this.Flags -band 0x0300) -shr 9
        $this.SignatoryField = $this.Flags -band 0x000F
        $this.Protocol = $binaryReader.ReadByte()
        $this.Algorithm = $binaryReader.ReadByte()

        $length = $this.RecordDataLength - 4
        if ($this.AuthenticationConfidentiality -ne 'NoKey' -and $length -gt 0) {
            $this.PublicKey = [Convert]::ToBase64String($binaryReader.ReadBytes($length))
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.Flags
            $this.Protocol
            $this.Algorithm
            $this.PublicKey -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsKEYRecord.ps1' 71
#Region '.\class\2.RecordTypes\DnsKXRecord.ps1' 0
class DnsKXRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / EXCHANGER /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2230.txt
    #>


    [UInt16] $Preference
    [string] $Exchanger

    DnsKXRecord() : base() { }
    DnsKXRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.Exchanger = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.Exchanger
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsKXRecord.ps1' 41
#Region '.\class\2.RecordTypes\DnsL32Record.ps1' 0
class DnsL32Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOCATOR |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://www.ietf.org/rfc/rfc6742.txt
    #>


    [UInt16] $Preference
    [string] $Locator

    DnsL32Record() : base() { }
    DnsL32Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.Locator = $binaryReader.ReadIPAddress()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.Locator
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsL32Record.ps1' 41
#Region '.\class\2.RecordTypes\DnsL64Record.ps1' 0
class DnsL64Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOCATOR |
        | |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://www.ietf.org/rfc/rfc6742.txt
    #>


    [UInt16] $Preference
    [string] $Locator

    DnsL64Record() : base() { }
    DnsL64Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)

        $bytes = $binaryReader.ReadBytes(8)
        $address = for ($i = 0; $i -lt $bytes.Count; $i += 2) {
            ('{0:x2}{1:x2}' -f $bytes[$i], $bytes[$i + 1]).TrimStart('0')
        }
        $this.Locator = $address -join ':'
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.Locator
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsL64Record.ps1' 48
#Region '.\class\2.RecordTypes\DnsLOCRecord.ps1' 0
class DnsLOCRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | VERSION | SIZE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | HORIZ PRE | VERT PRE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LATITUDE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LONGITUDE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALTITUDE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1876.txt
    #>


    [byte]            $Version
    [Decimal]         $Size
    [Decimal]         $HorizontalPrecision
    [Decimal]         $VerticalPrecision
    [AngularDistance] $Latitude
    [AngularDistance] $Longitude
    [Decimal]         $Altitude

    DnsLOCRecord() : base() { }
    DnsLOCRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [Double] ConvertFromIntegerPair($byte) {
        return 0 + (
            '{0}e{1}' -f @(
                ($byte -band 0xF0) -shr 4
                $byte -band 0x0F
            )
        ) / 100
    }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Version = $binaryReader.ReadByte()

        $this.Size = $this.ConvertFromIntegerPair($binaryReader.ReadByte())
        $this.HorizontalPrecision = $this.ConvertFromIntegerPair($binaryReader.ReadByte())
        $this.VerticalPrecision = $this.ConvertFromIntegerPair($binaryReader.ReadByte())

        $this.Latitude = [AngularDistance]::new($binaryReader.ReadUInt32($true), 'Latitude')
        $this.Longitude = [AngularDistance]::new($binaryReader.ReadUInt32($true), 'Longitude')
        $this.Altitude = (-10000000 + $binaryReader.ReadUInt32($true)) / 100
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} {2:N2}m {3}m {4}m {5}m' -f @(
            $this.Latitude
            $this.Longitude
            $this.Altitude
            $this.Size
            $this.HorizontalPrecision
            $this.VerticalPrecision
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsLOCRecord.ps1' 74
#Region '.\class\2.RecordTypes\DnsLPRecord.ps1' 0
class DnsLPRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / FQDN /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2230.txt
    #>


    [UInt16] $Preference
    [string] $FQDN

    DnsLPRecord() : base() { }
    DnsLPRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.FQDN = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.FQDN
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsLPRecord.ps1' 41
#Region '.\class\2.RecordTypes\DnsMBRecord.ps1' 0
class DnsMBRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MADNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $Hostname

    DnsMBRecord() : base() { }
    DnsMBRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMBRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsMDRecord.ps1' 0
class DnsMDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MADNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $Hostname

    DnsMDRecord() : base() { }
    DnsMDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMDRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsMFRecord.ps1' 0
class DnsMFRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MADNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $Hostname

    DnsMFRecord() : base() { }
    DnsMFRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMFRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsMGRecord.ps1' 0
class DnsMGRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MGMNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $MailboxName

    DnsMGRecord() : base() { }
    DnsMGRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.MailboxName = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.MailboxName
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMGRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsMINFORecord.ps1' 0
#using namespace Indented.IO


class DnsMINFORecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / RMAILBX /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / EMAILBX /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $ResponsibleMailbox
    [string] $ErrorMailbox

    DnsMINFORecord() : base() { }
    DnsMINFORecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.ResponsibleMailbox = $binaryReader.ReadDnsDomainName()
        $this.ErrorMailbox = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.ResponsibleMailbox
            $this.ErrorMailbox
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMINFORecord.ps1' 43
#Region '.\class\2.RecordTypes\DnsMRRecord.ps1' 0
class DnsMRRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / NEWNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $MailboxName

    DnsMRRecord() : base() { }
    DnsMRRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.MailboxName = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.MailboxName
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMRRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsMXRecord.ps1' 0
class DnsMXRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / EXCHANGE /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [UInt16] $Preference
    [string] $Exchange

    DnsMXRecord() : base() { }
    DnsMXRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.Exchange = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.Exchange
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsMXRecord.ps1' 41
#Region '.\class\2.RecordTypes\DnsNAPTRRecord.ps1' 0
class DnsNAPTRRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ORDER |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / FLAGS /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SERVICES /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / REGEXP /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / REPLACEMENT /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2915.txt
    #>


    [UInt16] $Order
    [UInt16] $Preference
    [string] $Flags
    [string] $Service
    [string] $RegularExpression
    [string] $Replacement

    DnsNAPTRRecord() : base() { }
    DnsNAPTRRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Order = $binaryReader.ReadUInt16($true)
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.Flags = $binaryReader.ReadDnsCharacterString()
        $this.Service = $binaryReader.ReadDnsCharacterString()
        $this.RegularExpression = $binaryReader.ReadDnsCharacterString()
        $this.Replacement = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} "{2}" "{3}" "{4}" {5}' -f @(
            $this.Order
            $this.Preference
            $this.Flags
            $this.Service
            $this.RegularExpression
            $this.Replacement
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNAPTRRecord.ps1' 61
#Region '.\class\2.RecordTypes\DnsNIDRecord.ps1' 0
class DnsNIDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | NODEID |
        | |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://www.ietf.org/rfc/rfc6742.txt
    #>


    [UInt16] $Preference
    [string] $NodeID

    DnsNIDRecord() : base() { }
    DnsNIDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)

        $bytes = $binaryReader.ReadBytes(8)
        $address = for ($i = 0; $i -lt $bytes.Count; $i += 2) {
            ('{0:x2}{1:x2}' -f $bytes[$i], $bytes[$i + 1]).TrimStart('0')
        }
        $this.NodeID = $address -join ':'
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference
            $this.NodeID
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNIDRecord.ps1' 48
#Region '.\class\2.RecordTypes\DnsNIMLOCRecord.ps1' 0
class DnsNIMLOCRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / BinaryData /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
    #>


    [byte[]] $BinaryData

    DnsNIMLOCRecord() : base() { }
    DnsNIMLOCRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.BinaryData = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return [EndianBitConverter]::ToHexadecimal($this.BinaryData)
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNIMLOCRecord.ps1' 33
#Region '.\class\2.RecordTypes\DnsNINFORecord.ps1' 0
#using namespace System.Collections.Generic
#using namespace System.Text

class DnsNINFORecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ZS-DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/html/draft-lewis-dns-undocumented-types-01
        http://tools.ietf.org/html/draft-reid-dnsext-zs-01
    #>


    [string[]] $ZSData

    DnsNINFORecord() : base() { }
    DnsNINFORecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = $this.RecordDataLength
        if ($length -gt 0) {
            $this.ZSData = do {
                $entryLength = 0

                $binaryReader.ReadDnsCharacterString([ref]$entryLength)

                $length -= $entryLength
            } until ($length -le 0)
        }
    }

    hidden [string] RecordDataToString() {
        return '"{0}"' -f ($this.ZSData -join '" "')
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNINFORecord.ps1' 47
#Region '.\class\2.RecordTypes\DnsNSAPPTRRecord.ps1' 0
class DnsNSAPPTRRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / OWNER /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1348.txt
    #>


    [string] $Owner

    DnsNSAPPTRRecord() : base() { }
    DnsNSAPPTRRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Owner = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Owner
    }

    [string] ToString() {
        return '{0,-29} {1,-10} {2,-5} {3,-10} {4}' -f @(
            $this.Name
            $this.TTL
            $this.RecordClass
            'NSAP-PTR'
            $this.RecordData
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSAPPTRRecord.ps1' 44
#Region '.\class\2.RecordTypes\DnsNSAPRecord.ps1' 0
class DnsNSAPRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / NSAP /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1706.txt
    #>


    [string] $Text
    [string] $Data

    DnsNSAPRecord() : base() { }
    DnsNSAPRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Data = '0x{0}' -f @(
            [EndianBitConverter]::ToHexadecimal(
                $binaryReader.ReadBytes($this.RecordDataLength)
            )
        )
    }

    hidden [string] RecordDataToString() {
        return $this.Data
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSAPRecord.ps1' 38
#Region '.\class\2.RecordTypes\DnsNSEC3PARAMRecord.ps1' 0
class DnsNSEC3PARAMRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | HASH ALG | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ITERATIONS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SALT LEN | /
        +--+--+--+--+--+--+--+--+ /
        / SALT /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc5155.txt
    #>


    [NSEC3HashAlgorithm] $HashAlgorithm
    [byte]               $Flags
    [UInt16]             $Iterations
    [string]             $Salt = '-'

    DnsNSEC3PARAMRecord() : base() { }
    DnsNSEC3PARAMRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.HashAlgorithm = $binaryReader.ReadByte()
        $this.Flags = $binaryReader.ReadByte()
        $this.Iterations = $binaryReader.ReadUInt16($true)

        $saltLength = $binaryReader.ReadByte()
        if ($saltLength -gt 0) {
            $this.Salt = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($saltLength))
        }
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1} {2} {3}' -f @(
            $this.HashAlgorithm
            $this.Flags
            $this.Iterations
            $this.Salt
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSEC3PARAMRecord.ps1' 54
#Region '.\class\2.RecordTypes\DnsNSEC3Record.ps1' 0
class DnsNSEC3Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | HASH ALG | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ITERATIONS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SALT LEN | /
        +--+--+--+--+--+--+--+--+ /
        / SALT /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | HASH LEN | /
        +--+--+--+--+--+--+--+--+ /
        / HASH /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / <BIT MAP> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        The flags field takes the following format, discussed in RFC 5155 3.2:
 
          0 1 2 3 4 5 6 7
        +--+--+--+--+--+--+--+--+
        | |O |
        +--+--+--+--+--+--+--+--+
 
        Where O, bit 7, represents the Opt-Out Flag.
 
        http://www.ietf.org/rfc/rfc5155.txt
    #>


    [NSEC3HashAlgorithm] $HashAlgorithm
    [byte]               $Flags
    [bool]               $OptOut
    [UInt16]             $Iterations
    [string]             $Salt
    [string]             $Hash
    [DnsRecordType[]]    $RRType

    DnsNSEC3Record() : base() { }
    DnsNSEC3Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.HashAlgorithm = $binaryReader.ReadByte()
        $this.Flags = $binaryReader.ReadByte()
        $this.OptOut = $this.Flags -band [NSEC3Flags]::OptOut
        $this.Iterations = $binaryReader.ReadUInt16($true)

        $saltLength = $binaryReader.ReadByte()
        if ($saltLength -gt 0) {
            $this.Salt = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($saltLength))
        }

        $hashLength = $binaryReader.ReadByte()
        $this.Hash = [EndianBitConverter]::ToBase32String($binaryReader.ReadBytes($hashLength))

        $this.RRType = $binaryReader.ReadBitMap(
            $this.RecordDataLength - 6 - $saltLength - $hashLength
        )
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1} {2} {3} {4} {5}' -f @(
            $this.HashAlgorithm
            $this.Flags
            $this.Iterations
            $this.Salt
            $this.Hash
            $this.RRType -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSEC3Record.ps1' 84
#Region '.\class\2.RecordTypes\DnsNSECRecord.ps1' 0
class DnsNSECRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DOMAINNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / <BIT MAP> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string]          $DomainName
    [DnsRecordType[]] $RRType

    DnsNSECRecord() : base() { }
    DnsNSECRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = 0
        $this.DomainName = $binaryReader.ReadDnsDomainName([ref]$length)

        $this.RRType = $binaryReader.ReadBitMap(
            $this.RecordDataLength - $length
        )
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.DomainName
            $this.RRType -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSECRecord.ps1' 44
#Region '.\class\2.RecordTypes\DnsNSRecord.ps1' 0
class DnsNSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / NSDNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [string] $Hostname

    DnsNSRecord() : base() { }
    DnsNSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNSRecord.ps1' 32
#Region '.\class\2.RecordTypes\DnsNULLRecord.ps1' 0
class DnsNULLRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / <anything> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [byte[]] $BinaryData

    DnsNULLRecord() : base() { }
    DnsNULLRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.BinaryData = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return [Convert]::ToBase64String($this.BinaryData)
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNULLRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsNXTRecord.ps1' 0
#using namespace System.Text

class DnsNXTRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DOMAINNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / <BIT MAP> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2535.txt
        http://www.ietf.org/rfc/rfc3755.txt
    #>


    [string]          $DomainName
    [DnsRecordType[]] $RRType

    DnsNXTRecord() : base() { }
    DnsNXTRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = 0
        $this.DomainName = $binaryReader.ReadDnsDomainName([ref]$length)

        $bitMapLength = $this.RecordDataLength - $length
        $bitMap = $binaryReader.ReadBytes($bitMapLength)

        $this.RRType = for ($i = 0; $i -lt $bitMapLength; $i++) {
            for ($j = 7; $j -ge 0; $j--) {
                if ($bitMap[$i] -band 1 -shl $j) {
                    8 * $i + 7 - $j
                }
            }
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.DomainName
            $this.RRType -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsNXTRecord.ps1' 56
#Region '.\class\2.RecordTypes\DnsOPENPGPKEYRecord.ps1' 0
class DnsOPENPGPKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TXT-DATA /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $Key

    DnsOPENPGPKEYRecord() : base() { }
    DnsOPENPGPKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Key = [Convert]::ToBase64String($binaryReader.ReadBytes($this.RecordDataLength))
    }

    hidden [string] RecordDataToString() {
        return $this.Key -split '(?<=\G.{56})' -join ' '
    }
}
#EndRegion '.\class\2.RecordTypes\DnsOPENPGPKEYRecord.ps1' 33
#Region '.\class\2.RecordTypes\DnsOPTRecord.ps1' 0
#using namespace System.Collections.Generic
#using namespace System.Text

class DnsOPTRecord : DnsResourceRecord {
    <#
        OPT records make the following changes to standard resource record fields:
 
        Field Name Field Type Description
        ---------- ---------- -----------
        NAME domain name empty (root domain)
        TYPE u_int16_t OPT
        CLASS u_int16_t sender's UDP payload size
        TTL u_int32_t extended RCODE and flags
        RDLEN u_int16_t describes RDATA
        RDATA octet stream {attribute,value} pairs
 
        The Extended RCODE (stored in the TTL) is formatted as follows:
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | EXTENDED-RCODE | VERSION |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | Z |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        RR data structure:
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-CODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-LENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / OPTION-DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        Processing for each option assigned by IANA has been added as described below.
 
        LLQ
        ---
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-CODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-LENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | VERSION |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LLQ-OPCODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ERROR-CODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LLQ-ID |
        | |
        | |
        | |
        | |
        | |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LEASE-LIFE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        NSID
        ----
 
        Option data is returned as a byte array (NSIDBytes) and an ASCII string (NSIDString).
 
        DUA, DHU and N3U
        ----------------
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-CODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LIST-LENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALG-CODE | ... /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        EDNS-client-subnet
        ------------------
 
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-CODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OPTION-LENGTH |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESSFAMILY |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SOURCE NETMASK | SCOPE NETMASK |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ADDRESS /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2671.txt
        http://files.dns-sd.org/draft-sekar-dns-llq.txt
        http://files.dns-sd.org/draft-sekar-dns-ul.txt
        http://www.ietf.org/rfc/rfc5001.txt
        http://www.ietf.org/rfc/rfc6975.txt
        https://tools.ietf.org/html/rfc7871
    #>


    [UInt16]       $MaximumPayloadSize
    [UInt16]       $ExtendedRCode
    [UInt32]       $Version
    [EDnsDNSSECOK] $Z
    [PSObject[]]   $OptionData

    DnsOPTRecord() : base() {
        $this.RecordType = 'OPT'
    }
    DnsOPTRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Name = $dnsResourceRecord.Name
        $this.RecordType = $dnsResourceRecord.RecordType

        $this.MaximumPayloadSize = $binaryReader.ReadUInt16($true)
        $this.ExtendedRCode = $binaryReader.ReadByte()
        $this.Version = $binaryReader.ReadByte()

        $this.Z = $binaryReader.ReadUInt16($true)
        $this.RecordDataLength = $binaryReader.ReadUInt16($true)

        if ($binaryReader.BaseStream.Capacity -ge ($binaryReader.BaseStream.Position + $this.RecordDataLength)) {
            $this.ReadRecordData($binaryReader)
        }
    }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $optionsLength = $this.RecordDataLength

        $this.OptionData = while ($optionsLength -gt 0) {
            $optionCode   = [EDnsOptionCode]$binaryReader.ReadUInt16($true)
            $optionLength = $binaryReader.ReadUInt16($true)
            $optionsLength -= $optionLength

            switch ($optionCode) {
                'LLQ' {
                    [PSCustomObject]@{
                        OptionCode   = $optionCode
                        OptionLength = $optionLength
                        Version      = $binaryReader.ReadUInt16($true)
                        OpCode       = [LLQOpCode]$binaryReader.ReadUInt16($true)
                        ErrorCode    = [LLQErrorCode]$binaryReader.ReadUInt16($true)
                        ID           = $binaryReader.ReadUInt64($true)
                        LeaseLife    = $binaryReader.ReadUInt32($true)
                    }
                    break
                }
                'UL' {
                    [PSCustomObject]@{
                        OptionCode   = $optionCode
                        OptionLength = $optionLength
                        Lease        = $binaryReader.ReadInt32($true)
                    }
                    break
                }
                'NSID' {
                    $bytes = $binaryReader.ReadBytes($this.OptionLength)
                    [PSCustomObject]@{
                        OptionCode   = $optionCode
                        OptionLength = $optionLength
                        Bytes        = $bytes
                        String       = [Encoding]::UTF8.GetString($bytes)
                    }
                    break
                }
                'EDNSClientSubnet' {
                    $option = [PSCustomObject]@{
                        OptionCode    = $optionCode
                        OptionLength  = $optionLength
                        AddressFamily = [IanaAddressFamily]$binaryReader.ReadUInt16($true)
                        SourceNetMask = $binaryReader.ReadByte()
                        ScopeNetMask  = $binaryReader.ReadByte()
                        Address       = $null
                    }

                    $addressLength = [Math]::Ceiling($option.SourceNetMask / 8)
                    $addressBytes = $binaryReader.ReadBytes($addressLength)

                    $length = switch ($option.AddressFamily) {
                        'IPv4' { 4 }
                        'IPv6' { 16 }
                    }
                    if ($length) {
                        while ($addressBytes.Length -lt $length) {
                            $addressBytes = @([byte]0) + $addressBytes
                        }
                        $option.Address = [IPAddress]::new($addressBytes)
                    } else {
                        $option.Address = $addressBytes
                    }
                    $option

                    break
                }
                { $_ -in 'DAU', 'DHU', 'N3U' } {
                    [PSCustomObject]@{
                        OptionCode   = $optionCode
                        OptionLength = $optionLength
                        Algorithm    = [EncryptionAlgorithm]$binaryReader.ReadByte()
                        HashBytes    = [Convert]::ToBase64String($binaryReader.ReadBytes($optionLength - 1))
                    }
                    break
                }
                default {
                    [PSCustomObject]@{
                        OptionCode   = $optionCode
                        OptionLength = $optionLength
                        OptionData   = $binaryReader.ReadBytes($optionLength)
                    }
                }
            }
        }
    }

    hidden [IEnumerable[byte]] RecordDataToByteArray() {
        return [byte[]]::new(0)
    }

    [byte[]] ToByteArray(
        [bool] $useCompressedNames
    ) {
        $bytes = [List[byte]]::new()

        $bytes.Add(0)
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.RecordType, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes($this.MaximumPayloadSize, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes($this.ExtendedRCode, $true))
        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$this.Z, $true))

        $recordDataBytes = $this.RecordDataToByteArray()

        $bytes.AddRange([EndianBitConverter]::GetBytes([UInt16]$recordDataBytes.Count, $true))
        $bytes.AddRange($recordDataBytes)

        return $bytes.ToArray()
    }
}
#EndRegion '.\class\2.RecordTypes\DnsOPTRecord.ps1' 255
#Region '.\class\2.RecordTypes\DnsPTRRecord.ps1' 0
class DnsPTRRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PTRDNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $Hostname

    DnsPTRRecord() : base() { }
    DnsPTRRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return $this.Hostname
    }
}
#EndRegion '.\class\2.RecordTypes\DnsPTRRecord.ps1' 34
#Region '.\class\2.RecordTypes\DnsPXRecord.ps1' 0
class DnsPXRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MAP822 /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MAPX400 /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2163.txt
    #>


    [UInt16] $Preference
    [string] $MAP822
    [string] $MAPX400

    DnsPXRecord() : base() { }
    DnsPXRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.MAP822 = $binaryReader.ReadDnsDomainName()
        $this.MAPX400 = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0,-5} {1} {2}' -f @(
            $this.Preference
            $this.MAP822
            $this.MAPX400
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsPXRecord.ps1' 47
#Region '.\class\2.RecordTypes\DnsRKEYRecord.ps1' 0
#using namespace System.Collections.Generic

class DnsRKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FLAGS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PROTOCOL | ALGORITHM |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PUBLIC KEY /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/html/draft-reid-dnsext-rkey-00
    #>


    [UInt16]              $Flags
    [KEYProtocol]         $Protocol
    [EncryptionAlgorithm] $Algorithm
    [string]              $PublicKey

    DnsRKEYRecord() : base() { }
    DnsRKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Flags = $binaryReader.ReadUInt16($true)
        $this.Protocol = $binaryReader.ReadByte()
        $this.Algorithm = $binaryReader.ReadByte()

        $keyLength = $this.RecordDataLength - 4
        $this.PublicKey = [Convert]::ToBase64String($binaryReader.ReadBytes($keyLength))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.Flags
            $this.Protocol
            $this.Algorithm
            $this.PublicKey -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsRKEYRecord.ps1' 54
#Region '.\class\2.RecordTypes\DnsRPRecord.ps1' 0
class DnsRPRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / RMAILBX /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TXTDNAME /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1183.txt
    #>


    [string] $ResponsibleMailbox
    [string] $DomainName

    DnsRPRecord() : base() { }
    DnsRPRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.ResponsibleMailbox = $binaryReader.ReadDnsDomainName()
        $this.DomainName = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.ResponsibleMailbox
            $this.DomainName
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsRPRecord.ps1' 40
#Region '.\class\2.RecordTypes\DnsRRSIGRecord.ps1' 0
class DnsRRSIGRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | TYPE COVERED |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | LABELS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ORIGINAL TTL |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SIGNATURE EXPIRATION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SIGNATURE INCEPTION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEY TAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SIGNER'S NAME /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SIGNATURE /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc3755.txt
        http://www.ietf.org/rfc/rfc4034.txt
    #>


    [DnsRecordType]       $TypeCovered
    [EncryptionAlgorithm] $Algorithm
    [byte]                $Labels
    [UInt32]              $OriginalTTL
    [DateTime]            $SignatureExpiration
    [DateTime]            $SignatureInception
    [UInt16]              $KeyTag
    [string]              $SignersName
    [string]              $Signature

    DnsRRSIGRecord() : base() { }
    DnsRRSIGRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.TypeCovered = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.Labels = $binaryReader.ReadByte()
        $this.OriginalTTL = $binaryReader.ReadUInt32($true)
        $this.SignatureExpiration = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.SignatureInception = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.KeyTag = $binaryReader.ReadUInt16($true)

        $length = 0
        $this.SignersName = $binaryReader.ReadDnsDomainName([ref]$length)
        $this.Signature = [Convert]::ToBase64String($binaryReader.ReadBytes($this.RecordDataLength - 18 - $length))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2} {3} {4:yyyyMMddHHmmss} {5:yyyyMMddHHmmss} {6} {7} {8}' -f @(
            $this.TypeCovered
            $this.Algorithm
            $this.Labels
            $this.OriginalTTL
            $this.SignatureExpiration
            $this.SignatureInception
            $this.KeyTag
            $this.SignersName
            $this.Signature -split '(?<=\G.{56})' -join ' '
        )
    }

    [string] ToLongString() {
        return (
            @(
                '{0} {1:D} {2} ( ; type-cov={0}, alg={1}, labels={2}'
                ' {3,-16} ; OriginalTTL'
                ' {4,-16:yyyyMMddHHmmss} ; Signature expiration ({4:u})'
                ' {5,-16:yyyyMMddHHmmss} ; Signature inception ({5:u})'
                ' {6,-16} ; Key identifier'
                ' {7,-16} ; Signer'
                ' {8,-16} ; Signature'
                ')'
            ) -join "`n"
        ) -f @(
            $this.TypeCovered
            $this.Algorithm
            $this.Labels
            $this.OriginalTTL
            $this.SignatureExpiration
            $this.SignatureInception
            $this.KeyTag
            $this.SignersName
            $this.Signature -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsRRSIGRecord.ps1' 108
#Region '.\class\2.RecordTypes\DnsRTRecord.ps1' 0
class DnsRTRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PREFERENCE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / INTERMEDIATEHOST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 
        http://www.ietf.org/rfc/rfc1183.txt
    #>


    [UInt16] $Preference
    [string] $IntermediateHost

    DnsRTRecord() : base() { }
    DnsRTRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Preference = $binaryReader.ReadUInt16($true)
        $this.IntermediateHost = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Preference,
            $this.IntermediateHost
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsRTRecord.ps1' 42
#Region '.\class\2.RecordTypes\DnsSIGRecord.ps1' 0
#using namespace Indented.IO
#using namespace Indented.Net.Dns

class DnsSIGRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | TYPE COVERED |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | LABELS |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ORIGINAL TTL |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SIGNATURE EXPIRATION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SIGNATURE INCEPTION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEY TAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SIGNER'S NAME /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SIGNATURE /
        / /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2535.txt
        http://www.ietf.org/rfc/rfc2931.txt
    #>


    [DnsRecordType]       $TypeCovered
    [EncryptionAlgorithm] $Algorithm
    [byte]                $Labels
    [UInt32]              $OriginalTTL
    [DateTime]            $SignatureExpiration
    [DateTime]            $SignatureInception
    [UInt16]              $KeyTag
    [string]              $SignersName
    [string]              $Signature

    DnsSIGRecord() : base() { }
    DnsSIGRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.TypeCovered = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.Labels = $binaryReader.ReadByte()
        $this.OriginalTTL = $binaryReader.ReadUInt32($true)
        $this.SignatureExpiration = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.SignatureInception = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.KeyTag = $binaryReader.ReadUInt16($true)

        $length = 0
        $this.SignersName = $binaryReader.ReadDnsDomainName([ref]$length)
        $this.Signature = [Convert]::ToBase64String($binaryReader.ReadBytes($this.RecordDataLength - 18 - $length))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2} {3} {4:yyyyMMddHHmmss} {5:yyyyMMddHHmmss} {6} {7} {8}' -f @(
            $this.TypeCovered
            $this.Algorithm
            $this.Labels
            $this.OriginalTTL
            $this.SignatureExpiration
            $this.SignatureInception
            $this.KeyTag
            $this.SignersName
            $this.Signature -split '(?<=\G.{56})' -join ' '
        )
    }

    [string] ToLongString() {
        return (
            @(
                '{0} {1:D} {2} ( ; type-cov={0}, alg={1}, labels={2}'
                ' {3,-16} ; OriginalTTL'
                ' {4,-16:yyyyMMddHHmmss} ; Signature expiration ({4:u})'
                ' {5,-16:yyyyMMddHHmmss} ; Signature inception ({5:u})'
                ' {6,-16} ; Key identifier'
                ' {7,-16} ; Signer'
                ' {8,-16} ; Signature'
                ')'
            ) -join "`n"
        ) -f @(
            $this.TypeCovered
            $this.Algorithm
            $this.Labels
            $this.OriginalTTL
            $this.SignatureExpiration
            $this.SignatureInception
            $this.KeyTag
            $this.SignersName
            $this.Signature -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSIGRecord.ps1' 111
#Region '.\class\2.RecordTypes\DnsSINKRecord.ps1' 0
class DnsSINKRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | CODING | SUBCODING |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/id/draft-eastlake-kitchen-sink-02.txt
 
        The structure above is modified to match dig. Adding a meaning byte.
    #>


    [byte]   $Meaning
    [byte]   $Coding
    [byte]   $Subcoding
    [string] $Data

    DnsSINKRecord() : base() { }
    DnsSINKRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Meaning = $binaryReader.ReadByte()
        $this.Coding = $binaryReader.ReadByte()
        $this.Subcoding = $binaryReader.ReadByte()

        $dataLength = $this.RecordDataLength - 3
        if ($dataLength -gt 0) {
            $this.Data = [Convert]::ToBase64String($binaryReader.ReadBytes($dataLength))
        }
    }

    hidden [string] RecordDataToString() {
        if ($this.Data) {
            return '{0:D} {1:D} {2:D} {3}' -f @(
                $this.Meaning
                $this.Coding
                $this.Subcoding
                $this.Data
            )
        } else {
            return '{0:D} {1:D} {2:D}' -f @(
                $this.Meaning
                $this.Coding
                $this.Subcoding
            )
        }
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSINKRecord.ps1' 61
#Region '.\class\2.RecordTypes\DnsSMIMEARecord.ps1' 0
class DnsSMIMEARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | CERT USAGE | SELECTOR |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | MATCHING TYPE | /
        +--+--+--+--+--+--+--+--+ /
        / CERT ASSOCIATION DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://tools.ietf.org/html/rfc8162
    #>


    [CertificateUsage] $CertificateUsage
    [Selector]         $Selector
    [MatchingType]     $MatchingType
    [string]           $CertificateAssociation

    DnsSMIMEARecord() : base() { }
    DnsSMIMEARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.CertificateUsage = $binaryReader.ReadByte()
        $this.Selector = $binaryReader.ReadByte()
        $this.MatchingType = $binaryReader.ReadByte()
        $this.CertificateAssociation = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength - 3))
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1:D} {2:D} {3}' -f @(
            $this.CertificateUsage
            $this.Selector
            $this.MatchingType
            $this.CertificateAssociation -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSMIMEARecord.ps1' 49
#Region '.\class\2.RecordTypes\DnsSOARecord.ps1' 0
#using namespace System.Collections.Generic

class DnsSOARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / RNAME /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SERIAL |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | REFRESH |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | RETRY |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | EXPIRE |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | MINIMUM |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $NameServer
    [string] $ResponsiblePerson
    [UInt32] $Serial
    [UInt32] $Refresh
    [UInt32] $Retry
    [UInt32] $Expire
    [UInt32] $MinimumTTL

    DnsSOARecord() : base() { }
    DnsSOARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.NameServer = $binaryReader.ReadDnsDomainName()
        $this.ResponsiblePerson = $binaryReader.ReadDnsDomainName()
        $this.Serial = $binaryReader.ReadUInt32($true)
        $this.Refresh = $binaryReader.ReadUInt32($true)
        $this.Retry = $binaryReader.ReadUInt32($true)
        $this.Expire = $binaryReader.ReadUInt32($true)
        $this.MinimumTTL = $binaryReader.ReadUInt32($true)
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} {2} {3} {4} {5} {6}' -f @(
            $this.NameServer
            $this.ResponsiblePerson
            $this.Serial
            $this.Refresh
            $this.Retry
            $this.Expire
            $this.MinimumTTL
        )
    }

    hidden [byte[]] RecordDataToByteArray(
        [bool] $useCompressedNames
    ) {
        $bytes = [List[byte]]::new()

        if ($useCompressedNames) {
            # MNAME
            $bytes.AddRange([byte[]](0xC0, 0x0C))
            # RNAME
            $bytes.AddRange([byte[]](0xC0, 0x0C))
        } else {
            $bytes.AddRange([EndianBinaryReader]::GetDnsDomainNameBytes($this.NameServer))
            # RNAME
            $bytes.AddRange([EndianBinaryReader]::GetDnsDomainNameBytes($this.ResponsiblePerson))
        }

        # SerialNumber
        $bytes.AddRange([EndianBitConverter]::GetBytes($this.Serial, $true))
        $bytes.AddRange([byte[]]::new(16))

        return $bytes.ToArray()
    }

    [string] ToLongString() {
        return (
            @(
                '{0} {1} ('
                ' {2,-10} ; serial'
                ' {3,-10} ; refresh ({4})'
                ' {5,-10} ; retry ({6})'
                ' {7,-10} ; expire ({8})'
                ' {9,-10} ; minimum ttl ({10})'
                ')'
            ) -join "`n"
        ) -f @(
            $this.NameServer
            $this.ResponsiblePerson
            $this.Serial
            $this.Refresh
            (ConvertToTimeSpanString -Seconds $this.Refresh)
            $this.Retry
            (ConvertToTimeSpanString -Seconds $this.Retry)
            $this.Expire
            (ConvertToTimeSpanString -Seconds $this.Expire)
            $this.MinimumTTL
            (ConvertToTimeSpanString -Seconds $this.MinimumTTL)
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSOARecord.ps1' 123
#Region '.\class\2.RecordTypes\DnsSPFRecord.ps1' 0
class DnsSPFRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TXT-DATA /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string[]] $SPF

    DnsSPFRecord() : base() { }
    DnsSPFRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = $this.RecordDataLength
        if ($length -gt 0) {
            $this.SPF = do {
                $entryLength = 0

                $binaryReader.ReadDnsCharacterString([ref]$entryLength)

                $length -= $entryLength
            } until ($length -le 0)
        }
    }

    hidden [string] RecordDataToString() {
        return '"{0}"' -f ($this.SPF -join '" "')
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSPFRecord.ps1' 42
#Region '.\class\2.RecordTypes\DnsSRVRecord.ps1' 0

class DnsSRVRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PRIORITY |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | WEIGHT |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PORT |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TARGET /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2782.txt
    #>


    [UInt16] $Priority
    [UInt16] $Weight
    [UInt16] $Port
    [string] $Hostname

    DnsSRVRecord() : base() { }
    DnsSRVRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Priority = $binaryReader.ReadUInt16($true)
        $this.Weight = $binaryReader.ReadUInt16($true)
        $this.Port = $binaryReader.ReadUInt16($true)
        $this.Hostname = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} {2} {3}' -f @(
            $this.Priority
            $this.Weight
            $this.Port
            $this.Hostname
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSRVRecord.ps1' 52
#Region '.\class\2.RecordTypes\DnsSSHFPRecord.ps1' 0
class DnsSSHFPRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | FPTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / FINGERPRINT /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc4255.txt
    #>


    [SSHAlgorithm] $Algorithm
    [SSHFPType]    $FPType
    [string]       $Fingerprint

    DnsSSHFPRecord() : base() { }
    DnsSSHFPRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Algorithm = $binaryReader.ReadByte()
        $this.FPType = $binaryReader.ReadByte()
        $this.FingerPrint = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength - 2))
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1:D} {2}' -f @(
            $this.Algorithm
            $this.FPType
            $this.Fingerprint -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsSSHFPRecord.ps1' 44
#Region '.\class\2.RecordTypes\DnsTALINKRecord.ps1' 0
class DnsTALINKRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / PREV /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / NEXT /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template
    #>


    [string] $Previous
    [string] $Next

    DnsTALINKRecord() : base() { }
    DnsTALINKRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Previous = $binaryReader.ReadDnsDomainName()
        $this.Next = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        return '{0} {1}' -f @(
            $this.Previous
            $this.Next
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTALINKRecord.ps1' 42
#Region '.\class\2.RecordTypes\DnsTARecord.ps1' 0
class DnsTARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEYTAG |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ALGORITHM | DIGESTTYPE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DIGEST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://tools.ietf.org/html/draft-lewis-dns-undocumented-types-01
    #>


    [UInt16]              $KeyTag
    [EncryptionAlgorithm] $Algorithm
    [DigestType]          $DigestType
    [string]              $Digest

    DnsTARecord() : base() { }
    DnsTARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.KeyTag = $binaryReader.ReadUInt16($true)
        $this.Algorithm = $binaryReader.ReadByte()
        $this.DigestType = $binaryReader.ReadByte()
        $this.Digest = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength - 4))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2:D} {3}' -f @(
            $this.KeyTag
            $this.Algorithm
            $this.DigestType
            $this.Digest
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTARecord.ps1' 49
#Region '.\class\2.RecordTypes\DnsTKEYRecord.ps1' 0
class DnsTKEYRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ALGORITHM /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | INCEPTION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | EXPIRATION |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | MODE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ERROR |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | KEYSIZE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / KEYDATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OTHERSIZE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / OTHERDATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2930.txt
    #>


    [string]   $Algorithm
    [DateTime] $Inception
    [DateTime] $Expiration
    [TKEYMode] $Mode
    [RCode]    $TKEYError
    [string]   $KeyData
    [string]   $OtherData

    DnsTKEYRecord() : base() { }
    DnsTKEYRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Algorithm = $binaryReader.ReadDnsDomainName()
        $this.Inception = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.Expiration = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt32($true))
        $this.Mode = $binaryReader.ReadUInt16($true)
        $this.TKEYError = $binaryReader.ReadUInt16($true)

        $keySize = $binaryReader.ReadUInt16($true)
        $this.KeyData = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($keySize))

        $otherSize = $binaryReader.ReadUInt16($true)
        if ($otherSize -gt 0) {
            $this.OtherData = [EndianBitConverter]::ToHexadecimal($BinaryReader.ReadBytes($otherSize))
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:yyyyMMddHHmmss} {2:yyyyMMddHHmmss} {3:D} {4} {5}' -f @(
            $this.Algorithm
            $this.Inception
            $this.Expiration
            $this.Mode
            $this.KeyData
            $this.OtherData
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTKEYRecord.ps1' 79
#Region '.\class\2.RecordTypes\DnsTLSARecord.ps1' 0
class DnsTLSARecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | CERT USAGE | SELECTOR |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | MATCHING TYPE | /
        +--+--+--+--+--+--+--+--+ /
        / CERT ASSOCIATION DATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc6698.txt
    #>


    [CertificateUsage] $CertificateUsage
    [Selector]         $Selector
    [MatchingType]     $MatchingType
    [string]           $CertificateAssociation

    DnsTLSARecord() : base() { }
    DnsTLSARecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.CertificateUsage = $binaryReader.ReadByte()
        $this.Selector = $binaryReader.ReadByte()
        $this.MatchingType = $binaryReader.ReadByte()
        $this.CertificateAssociation = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength - 3))
    }

    hidden [string] RecordDataToString() {
        return '{0:D} {1:D} {2:D} {3}' -f @(
            $this.CertificateUsage
            $this.Selector
            $this.MatchingType
            $this.CertificateAssociation -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTLSARecord.ps1' 49
#Region '.\class\2.RecordTypes\DnsTSIGRecord.ps1' 0
class DnsTSIGRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / ALGORITHM /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | TIMESIGNED |
        | |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | FUDGE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | MACSIZE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / MAC /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ORIGINALID |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ERROR |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | OTHERSIZE |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / OTHERDATA /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc2845.txt
    #>


    [string]   $Algorithm
    [DateTime] $TimeSigned
    [UInt16]   $Fudge
    [string]   $MAC
    [UInt16]   $OriginalID
    [RCode]    $TSIGError
    [string]   $OtherData

    DnsTSIGRecord() : base() { }
    DnsTSIGRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Algorithm = $binaryReader.ReadDnsDomainName()
        $this.TimeSigned = (Get-Date '01/01/1970').AddSeconds($binaryReader.ReadUInt48($true))
        $this.Fudge = $binaryReader.ReadUInt16($true)

        $macSize = $binaryReader.ReadUInt16($true)
        $this.MAC =  [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($macSize))

        $this.OriginalID = $binaryReader.ReadUInt16($true)
        $this.TSIGError = $binaryReader.ReadUInt16($true)

        $otherSize = $binaryReader.ReadUInt16($true)

        if ($otherSize -gt 0) {
            $this.OtherData = [EndianBitConverter]::ToHexadecimal($BinaryReader.ReadBytes($otherSize))
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:yyyyMMddHHmmss} {2} {3} {4} {5:D} {6}' -f @(
            $this.Algorithm
            $this.TimeSigned
            $this.Fudge
            $this.MAC
            $this.OriginalID
            $this.TSIGError
            $this.OtherData
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTSIGRecord.ps1' 82
#Region '.\class\2.RecordTypes\DnsTXTRecord.ps1' 0
class DnsTXTRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TXT-DATA /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string[]] $Text

    DnsTXTRecord() : base() { }
    DnsTXTRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $length = $this.RecordDataLength
        if ($length -gt 0) {
            $this.Text = do {
                $entryLength = 0

                $binaryReader.ReadDnsCharacterString([ref]$entryLength)

                $length -= $entryLength
            } until ($length -le 0)
        }
    }

    hidden [string] RecordDataToString() {
        return '"{0}"' -f ($this.Text -join '" "')
    }
}
#EndRegion '.\class\2.RecordTypes\DnsTXTRecord.ps1' 42
#Region '.\class\2.RecordTypes\DnsUIDRecord.ps1' 0
class DnsUIDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / UID /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        IANA-Reserved
    #>


    [byte[]] $Data

    DnsUIDRecord() : base() { }
    DnsUIDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Data = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return '\# {0} {1}' -f @(
            $this.Data.Length
            [EndianBitConverter]::ToHexadecimal($this.Data)
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsUIDRecord.ps1' 36
#Region '.\class\2.RecordTypes\DnsUINFORecord.ps1' 0
class DnsUINFORecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / UINFO /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        IANA-Reserved
    #>


    [byte[]] $Data

    DnsUINFORecord() : base() { }
    DnsUINFORecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Data = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return '\# {0} {1}' -f @(
            $this.Data.Length
            [EndianBitConverter]::ToHexadecimal($this.Data)
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsUINFORecord.ps1' 36
#Region '.\class\2.RecordTypes\DnsUNKNOWNRecord.ps1' 0
class DnsUNKNOWNRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / <anything> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [byte[]] $BinaryData

    DnsUNKNOWNRecord() : base() { }
    DnsUNKNOWNRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.BinaryData = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return [Convert]::ToBase64String($this.BinaryData)
    }
}
#EndRegion '.\class\2.RecordTypes\DnsUNKNOWNRecord.ps1' 32
#Region '.\class\2.RecordTypes\DnsUNSPECRecord.ps1' 0
class DnsUNSPECRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / UNSPEC /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        IANA-Reserved
    #>


    [byte[]] $Data

    DnsUNSPECRecord() : base() { }
    DnsUNSPECRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Data = $binaryReader.ReadBytes($this.RecordDataLength)
    }

    hidden [string] RecordDataToString() {
        return '\# {0} {1}' -f @(
            $this.Data.Length
            [EndianBitConverter]::ToHexadecimal($this.Data)
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsUNSPECRecord.ps1' 36
#Region '.\class\2.RecordTypes\DnsUriRecord.ps1' 0
class DnsURIRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PRIORITY |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | WEIGHT |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TARGET /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://tools.ietf.org/html/rfc7553
    #>


    [UInt16] $Priority
    [UInt16] $Weight
    [string] $Target

    DnsURIRecord() : base() { }
    DnsURIRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Priority = $binaryReader.ReadUInt16($true)
        $this.Weight = $binaryReader.ReadUInt16($true)

        $this.Target = [string]::new(
            $binaryReader.ReadChars(
                $this.RecordDataLength - 4
            )
        )
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} "{2}"' -f @(
            $this.Priority
            $this.Weight
            $this.Target
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsUriRecord.ps1' 51
#Region '.\class\2.RecordTypes\DnsWINSRecord.ps1' 0
class DnsWINSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOCAL FLAG |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOOKUP TIMEOUT |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | CACHE TIMEOUT |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | NUMBER OF SERVERS |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / SERVER IP LIST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://msdn.microsoft.com/en-us/library/ms682748%28VS.85%29.aspx
    #>


    [WINSMappingFlag] $MappingFlag
    [UInt32]          $LookupTimeout
    [UInt32]          $CacheTimeout
    [IPAddress[]]     $ServerList

    DnsWINSRecord() : base() { }
    DnsWINSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.MappingFlag = $binaryReader.ReadUInt32($true)
        $this.LookupTimeout = $binaryReader.ReadUInt32($true)
        $this.CacheTimeout = $binaryReader.ReadUInt32($true)

        $numberOfServers = $binaryReader.ReadUInt32($true)

        $this.ServerList = for ($i = 0; $i -lt $numberOfServers; $i++) {
            $binaryReader.ReadIPAddress()
        }
    }

    hidden [string] RecordDataToString() {
        $value = 'L{0} C{1} ( {2} )' -f @(
            $this.LookupTimeout
            $this.CacheTimeout
            $this.ServerList -join ' '
        )
        if ($this.MappingFlag -eq 0x10000) {
            return 'LOCAL {0}' -f $value
        }
        return $value
    }
}
#EndRegion '.\class\2.RecordTypes\DnsWINSRecord.ps1' 65
#Region '.\class\2.RecordTypes\DnsWINSRRecord.ps1' 0
class DnsWINSRRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOCAL FLAG |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | LOOKUP TIMEOUT |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | CACHE TIMEOUT |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | NUMBER OF DOMAINS |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DOMAIN NAME LIST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://msdn.microsoft.com/en-us/library/ms682748%28VS.85%29.aspx
    #>


    [WINSMappingFlag] $MappingFlag
    [UInt32]          $LookupTimeout
    [UInt32]          $CacheTimeout
    [string]          $DomainToAppend

    DnsWINSRRecord() : base() { }
    DnsWINSRRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.MappingFlag = $binaryReader.ReadUInt32($true)
        $this.LookupTimeout = $binaryReader.ReadUInt32($true)
        $this.CacheTimeout = $binaryReader.ReadUInt32($true)

        $this.DomainToAppend = $binaryReader.ReadDnsDomainName()
    }

    hidden [string] RecordDataToString() {
        $value = 'L{0} C{1} ( {2} )' -f @(
            $this.LookupTimeout
            $this.CacheTimeout
            $this.DomainToAppend
        )
        if ($this.MappingFlag -eq 0x10000) {
            return 'LOCAL {0}' -f $value
        }
        return $value
    }
}
#EndRegion '.\class\2.RecordTypes\DnsWINSRRecord.ps1' 61
#Region '.\class\2.RecordTypes\DnsWKSRecord.ps1' 0
#using namespace System.Net.Sockets
#using namespace System.Text

class DnsWKSRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | ADDRESS |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | PROTOCOL | /
        +--+--+--+--+--+--+--+--+ /
        / /
        / <BIT MAP> /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
        http://www.ietf.org/rfc/rfc1010.txt
    #>


    [IPAddress]    $IPAddress
    [byte]         $IPProtocolNumber
    [ProtocolType] $IPProtocolType
    [string]       $BitMap
    [UInt16[]]     $Ports

    DnsWKSRecord() : base() { }
    DnsWKSRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.IPAddress = $binaryReader.ReadIPAddress()
        $this.IPProtocolNumber = $binaryReader.ReadByte()
        $this.IPProtocolType = $this.IPProtocolNumber

        $bitmapBytes = $binaryReader.ReadBytes($this.RecordDataLength - 5)
        foreach ($byte in $bitmapBytes) {
            $this.BitMap += [Convert]::ToString($byte, 2).PadLeft(8, '0')
        }

        $this.Ports = for ($i = 0; $i -lt $this.BitMap.Length; $i++) {
            if ($this.BitMap[$i] -eq '1') {
                $i
            }
        }
    }

    hidden [string] RecordDataToString() {
        return '{0} {1} {2}' -f @(
            $this.IPAddress
            $this.IPProtocolNumber
            $this.Ports -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsWKSRecord.ps1' 65
#Region '.\class\2.RecordTypes\DnsX25Record.ps1' 0
class DnsX25Record : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / TXT-DATA /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        http://www.ietf.org/rfc/rfc1035.txt
    #>


    [string] $PSDNAddress

    DnsX25Record() : base() { }
    DnsX25Record(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.PSDNAddress = $binaryReader.ReadDnsCharacterString()
    }

    hidden [string] RecordDataToString() {
        return '"{0}"' -f $this.PSDNAddress
    }
}
#EndRegion '.\class\2.RecordTypes\DnsX25Record.ps1' 33
#Region '.\class\2.RecordTypes\DnsZONEMDRecord.ps1' 0
class DnsZONEMDRecord : DnsResourceRecord {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | SERIAL |
        | |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        | DIGEST-TYPE | RESERVED |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / DIGEST /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
        https://tools.ietf.org/html/draft-wessels-dns-zone-digest-06
    #>


    [UInt32]           $Serial
    [ZONEMDDigestType] $DigestType
    [byte]             $Reserved
    [string]           $Digest

    DnsZONEMDRecord() : base() { }
    DnsZONEMDRecord(
        [DnsResourceRecord]  $dnsResourceRecord,
        [EndianBinaryReader] $binaryReader
    ) : base(
        $dnsResourceRecord,
        $binaryReader
    ) { }

    hidden [void] ReadRecordData(
        [EndianBinaryReader] $binaryReader
    ) {
        $this.Serial = $binaryReader.ReadUInt32($true)
        $this.DigestType = $binaryReader.ReadByte()
        $this.Reserved = $binaryReader.ReadByte()
        $this.Digest = [EndianBitConverter]::ToHexadecimal($binaryReader.ReadBytes($this.RecordDataLength - 6))
    }

    hidden [string] RecordDataToString() {
        return '{0} {1:D} {2} {3}' -f @(
            $this.Serial
            $this.DigestType
            $this.Reserved
            $this.Digest -split '(?<=\G.{56})' -join ' '
        )
    }
}
#EndRegion '.\class\2.RecordTypes\DnsZONEMDRecord.ps1' 50
#Region '.\class\3.Message\DnsMessage.ps1' 0
#using namespace System.Collections
#using namespace System.Collections.Generic
#using namespace System.Text
#using namespace System.IO

class DnsMessage {
    <#
                                        1 1 1 1 1 1
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / HEADER /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / QUESTION /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / ANSWER /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / AUTHORITY /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        / /
        / ADDITIONAL /
        / /
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    #>


    [DnsHeader]           $Header
    [DnsQuestion[]]       $Question
    [DnsResourceRecord[]] $Answer
    [DnsResourceRecord[]] $Authority
    [DnsResourceRecord[]] $Additional
    [Int]                 $Size
    [Int64]               $TimeTaken
    [string]              $ComputerName

    DnsMessage() { }

    DnsMessage(
        [string]      $name,
        [RecordType]  $recordType
    ) {
        $this.Header = [DnsHeader]::new($true, 1)
        $this.Question = [DnsQuestion]::new($name, $recordType, 'IN')
    }

    DnsMessage(
        [string]      $name,
        [RecordType]  $recordType,
        [RecordClass] $recordClass
    ) {
        $this.Header = [DnsHeader]::new($true, 1)
        $this.Question = [DnsQuestion]::new($name, $recordType, $recordClass)
    }

    DnsMessage(
        [string]      $name,
        [RecordType]  $recordType,
        [RecordClass] $recordClass,
        [UInt32]      $Serial
    ) {
        $this.Header = [DnsHeader]::new($true, 1)
        $this.Question = [DnsQuestion]::new($name, $recordType, $recordClass)

        $this.Header.AuthorityCount = 1
        $this.Authority = [DnsSOARecord]@{ Serial = $Serial }
    }

    DnsMessage(
        [byte[]] $message
    ) {
        $this.ReadDnsMessage($message, $true)
    }

    DnsMessage(
        [byte[]]  $message,
        [bool] $convertIdnToUnicode
    ) {
        $this.ReadDnsMessage($message, $convertIdnToUnicode)
    }

    hidden [void] ReadDnsMessage(
        [byte[]]  $message,
        [bool] $convertIdnToUnicode
    ) {
        $binaryReader = [EndianBinaryReader][MemoryStream]$message
        $binaryReader.ConvertIdnToUnicode = $convertIdnToUnicode

        $this.Size = $message.Length

        $this.Header = [DnsHeader]$binaryReader

        $this.Question = for ($i = 0; $i -lt $this.Header.QuestionCount; $i++) {
            [DnsQuestion]$binaryReader
        }
        $this.Answer = for ($i = 0; $i -lt $this.Header.AnswerCount; $i++) {
            [DnsResourceRecord]::Parse($binaryReader)
        }
        $this.Authority = for ($i = 0; $i -lt $this.Header.AuthorityCount; $i++) {
            [DnsResourceRecord]::Parse($binaryReader)
        }
        $this.Additional = for ($i = 0; $i -lt $this.Header.AdditionalCount; $i++) {
            [DnsResourceRecord]::Parse($binaryReader)
        }
    }

    hidden [string] RecordSetToString(
        [DnsResourceRecord[]] $resourceRecords
    ) {
        if ($resourceRecords.Count -gt 0) {
            $string = [StringBuilder]::new()
            foreach ($resourceRecord in $resourceRecords) {
                if ($resourceRecord.RecordType -ne [RecordType]::OPT) {
                    $string.AppendLine($resourceRecord.ToString())
                }
            }
            return $string.ToString().TrimEnd()
        }
        return ''
    }

    [string] QuestionToString() {
        $string = [StringBuilder]::new()
        foreach ($question in $this.Question) {
            $string.AppendLine($question.ToString())
        }
        return $string.ToString().TrimEnd()
    }

    [string] AnswerToString() {
        return $this.RecordSetToString($this.Answer)
    }

    [string] AuthorityToString() {
        return $this.RecordSetToString($this.Authority)
    }

    [string] AdditionalToString() {
        return $this.RecordSetToString($this.Additional)
    }

    [void] SetEDnsBufferSize() {
        $this.SetEDnsBufferSize(4096)
    }

    [void] SetEDnsBufferSize([UInt16]$EDnsBufferSize) {
        $this.Header.AdditionalCount = 1
        $this.Additional = [DnsOPTRecord]@{
            MaximumPayloadSize = $EDnsBufferSize
            Z                  = [EDnsDNSSECOK]::DO
        }
    }

    [void] SetAcceptDnsSec() {
        $this.Header.Flags = $this.Header.Flags -bor [HeaderFlags]::AD
    }

    [void] DisableRecursion() {
        $this.Header.Flags = [UInt16]$this.Header.Flags -bxor [UInt16][HeaderFlags]::RD
    }

    [byte[]] ToByteArray() {
        return $this.ToByteArray($false, $true)
    }

    [byte[]] ToByteArray(
        [bool] $useCompressedNames
    ) {
        return $this.ToByteArray($false, $useCompressedNames)
    }

    [byte[]] ToByteArray(
        [bool] $tcp,
        [bool] $useCompressedNames
    ) {
        $bytes = [List[byte]]::new()

        $bytes.AddRange($this.Header.ToByteArray())
        $bytes.AddRange([byte[]]$this.Question.ToByteArray())

        if ($this.Header.AuthorityCount -gt 0) {
            foreach ($resourceRecord in $this.Authority) {
                $bytes.AddRange($resourceRecord.ToByteArray($useCompressedNames))
            }
        }
        if ($this.Header.AdditionalCount -gt 0) {
            foreach ($resourceRecord in $this.Additional) {
                $bytes.AddRange($resourceRecord.ToByteArray())
            }
        }

        if ($tcp) {
            $length = [BitConverter]::GetBytes([UInt16]$bytes.Count)
            [Array]::Reverse($length)
            $bytes.InsertRange(0, $length)
        }

        return $bytes.ToArray()
    }
}
#EndRegion '.\class\3.Message\DnsMessage.ps1' 206
#Region '.\class\4.Client\DnsClient.ps1' 0
#using namespace System.Collections.Generic
#using namespace System.Diagnostics
#using namespace System.Net
#using namespace System.Net.Sockets

class DnsClient {
    [int]     $BufferSize = 4096
    [EndPoint]  $RemoteEndPoint
    [Timespan]  $TimeTaken

    hidden [Socket] $socket

    DnsClient() {
        $this.Initialize($false, $false, 5, 5)
    }

    DnsClient(
        [bool] $useTcp,
        [bool] $useIPv6
    ) {
        $this.Initialize($useTcp, $useIPv6, 5, 5)
    }

    DnsClient(
        [bool] $useTcp,
        [bool] $useIPv6,
        [int]   $receiveTimeout,
        [int]   $sendTimeout
    ) {
        $this.Initialize($useTcp, $useIPv6, $receiveTimeout, $sendTimeout)
    }

    hidden [void] Initialize(
        [bool] $useTcp,
        [bool] $useIPv6,
        [int]   $receiveTimeout,
        [int]   $sendTimeout
    ) {
        $addressFamily = 'InterNetwork'
        if ($useIPv6) {
            $addressFamily = 'InterNetworkV6'
        }
        if ($useTcp) {
            $this.Socket = [Socket]::new($addressFamily, 'Stream', 'Tcp')
        } else {
            $this.Socket = [Socket]::new($addressFamily, 'Dgram', 'Udp')
        }
        $this.Socket.ReceiveTimeout = $receiveTimeout * 1000
        $this.Socket.SendTimeout = $sendTimeout * 1000
    }

    [void] SendQuestion(
        [DnsMessage] $message,
        [IPAddress]  $ipAddress
    ) {
        $this.SendQuestion(
            $message,
            $ipAddress,
            53
        )
    }

    [void] SendQuestion(
        [DnsMessage] $message,
        [IPAddress]  $ipAddress,
        [UInt16]     $port
    ) {
        try {
            $stopWatch = [StopWatch]::StartNew()

            $this.RemoteEndPoint = [EndPoint][IPEndPoint]::new($ipAddress, $port)

            if ($this.socket.ProtocolType -eq 'Tcp') {
                try {
                    $this.socket.Connect($this.RemoteEndPoint)
                    $this.socket.Send($message.ToByteArray($true, $true))
                } catch {
                    throw
                }
            } else {
                $null = $this.socket.SendTo(
                    $message.ToByteArray($false, $true),
                    $this.RemoteEndPoint
                )
            }
        } catch {
            throw
        } finally {
            $stopWatch.Stop()

            $this.TimeTaken = $stopWatch.Elapsed
        }
    }

    [DnsMessage] ReceiveAnswer() {
        return $this.ReceiveAnswer($true)
    }

    [DnsMessage] ReceiveAnswer(
        [bool] $convertIdnToUnicode
    ) {
        try {
            $stopWatch = [StopWatch]::StartNew()

            $messageBytes = $this.ReceiveBytes()

            return [DnsMessage]::new($messageBytes, $convertIdnToUnicode)
        } catch {
            throw
        } finally {
            $stopWatch.Stop()

            $this.TimeTaken += $stopWatch.Elapsed
        }
    }

    [byte[]] ReceiveBytes() {
        try {
            $buffer = [byte[]]::new($this.bufferSize)

            if ($this.socket.ProtocolType -eq 'Tcp') {
                $bytesReceived = $this.socket.Receive($buffer)
                $length = [BitConverter]::ToUInt16(($buffer[1, 0]), 0)
                $messageBytes = [byte[]]::new($length)
                [Array]::Copy(
                    $buffer,
                    2,
                    $messageBytes,
                    0,
                    $bytesReceived - 2
                )

                $totalBytesReceived = $bytesReceived

                while ($totalBytesReceived -lt $length) {
                    $bytesReceived = $this.socket.Receive($buffer)
                    [Array]::Copy(
                        $buffer,
                        0,
                        $messageBytes,
                        $totalBytesReceived - 2,
                        $bytesReceived
                    )
                    $totalBytesReceived += $bytesReceived
                }

                $this.RemoteEndPoint = $this.socket.RemoteEndPoint
            } else {
                if ($this.socket.AddressFamily -eq 'InterNetwork') {
                    $endPoint = [IPEndPoint]::new([IPAddress]::Any, 0)
                } else {
                    $endPoint = [IPEndPoint]::new([IPAddress]::IPv6Any, 0)
                }

                $bytesReceived = $this.socket.ReceiveFrom($buffer, [ref]$endPoint)
                $this.RemoteEndPoint = $endPoint

                $messageBytes = [byte[]]::new($bytesReceived)
                [Array]::Copy(
                    $buffer,
                    $messageBytes,
                    $bytesReceived
                )
            }

            return $messageBytes
        } catch {
            throw
        }
    }

    [void] Close() {
        if ($this.socket.ProtocolType -eq 'Tcp') {
            $this.socket.Shutdown([SocketShutdown]::Both)
            $this.socket.Disconnect($true)
        }
        $this.socket.Close()
    }
}
#EndRegion '.\class\4.Client\DnsClient.ps1' 180
#Region '.\class\5.Cache\DnsCacheRecord.ps1' 0
class DnsCacheRecord {
    [string]            $Name
    [UInt32]            $TTL
    [DnsRecordType]     $RecordType
    [IPAddress]         $IPAddress
    [CacheResourceType] $ResourceType = 'Address'
    [DateTime]          $TimeAdded = (Get-Date)
    [bool]           $IsPermanent

    DnsCacheRecord() { }

    DnsCacheRecord(
        [DnsARecord] $dnsRecord
    ) {
        $this.Initialize($dnsRecord)
    }

    DnsCacheRecord(
        [DnsAAAARecord] $dnsRecord
    ) {
        $this.Initialize($dnsRecord)
    }

    hidden Initialize(
        $dnsRecord
    ) {
        $this.Name = $dnsRecord.Name
        $this.TTL = $dnsRecord.TTL
        $this.RecordType = $dnsRecord.RecordType
        $this.IPAddress = $dnsRecord.IPAddress
    }

    static [DnsCacheRecord] Parse(
        [string] $recordData
    ) {
        if ($recordData -match '(?<Name>\S+)\s+(?<TTL>\d+)\s+(IN)?\s*(?<RecordType>A|AAAA)\s+(?<IPAddress>\S+)') {
            $matches.Remove(0)
            return [DnsCacheRecord]$matches
        } else {
            throw 'Invalid record data format'
        }
    }

    [bool] HasExpired() {
        if ($this.IsPermanent) {
            return $false
        }

        return $this.TimeAdded.AddSeconds($this.TTL) -lt (Get-Date)
    }
}
#EndRegion '.\class\5.Cache\DnsCacheRecord.ps1' 52
#Region '.\private\ConvertToTimeSpanString.ps1' 0
function ConvertToTimeSpanString {
    <#
    .SYNOPSIS
        Converts a number of seconds to a string.
    .DESCRIPTION
        ConvertToTimeSpanString accepts values in seconds then uses integer division to represent that time as a string.
 
        ConvertToTimeSpanString accepts UInt32 values, overcoming the Int32 type limitation built into New-TimeSpan.
 
        The format below is used, omitting any values of 0:
 
        # weeks # days # hours # minutes # seconds
    .INPUTS
        System.UInt32
    .EXAMPLE
        ConvertToTimeSpanString 28800
    .EXAMPLE
        [UInt32]::MaxValue | ConvertToTimeSpanString
    .EXAMPLE
        86400, 700210 | ConvertToTimeSpanString
    #>


    [CmdletBinding()]
    [OutputType([string])]
    param (
        # A number of seconds as an unsigned 32-bit integer.
        [Parameter(Mandatory, ValueFromPipeline)]
        [UInt32]$Seconds
    )

    begin {
        # Time periods described in seconds
        $formats = [Ordered]@{
            week   = 604800
            day    = 86400
            hour   = 3600
            minute = 60
            second = 1
        }
    }

    process {
        $values = foreach ($key in $formats.Keys) {
            $remainder = $Seconds % $formats[$key]
            $value = ($Seconds - $Remainder) / $formats[$key]
            $Seconds = $remainder

            if ($value) {
                '{0} {1}{2}' -f @(
                    $value
                    $Key
                    ('', 's')[$value -gt 1]
                )
            }
        }
        return $values -join ' '
    }
}
#EndRegion '.\private\ConvertToTimeSpanString.ps1' 59
#Region '.\private\GetDnsSuffixSearchList.ps1' 0
function GetDnsSuffixSearchList {
    <#
    .SYNOPSIS
        Attempt to discover a DNS suffix search list.
    .DESCRIPTION
        Attempt to discover a DNS suffix search list.
    #>


    [CmdletBinding()]
    param (
        [string]$Name
    )

    if (-not $Name.EndsWith('.')) {
        if (-not $psversiontable.Platform -or $psversiontable.Platform -eq 'Win32NT') {
            $params = @{
                ClassName = 'Win32_NetworkAdapterConfiguration'
                Property  = 'DNSDomainSuffixSearchOrder'
            }
            (Get-CimInstance @params).DNSDomainSuffixSearchOrder
        } elseif (Test-Path '/etc/resolv.conf') {
            Get-Content '/etc/resolv.conf' | Where-Object { $_ -match '^search (.+)' } | ForEach-Object {
                $matches[1] -split '\s+'
            }
        }
    }
}
#EndRegion '.\private\GetDnsSuffixSearchList.ps1' 28
#Region '.\private\ResolveDnsServer.ps1' 0
#using namespace System.Management.Automation

function ResolveDnsServer {
    [CmdletBinding()]
    [OutputType([IPAddress])]
    param (
        # The name or IP address of a DNS server to use.
        [string]$ComputerName,

        # Whether or not IPv6 will be used.
        [switch]$IPv6
    )

    $ipAddress = [IPAddress]::Any
    if ([IPAddress]::TryParse($ComputerName, [ref]$ipAddress)) {
        return $ipAddress
    } else {
        if ($IPv6) {
            $serverRecordType = [RecordType]::AAAA
        } else {
            $serverRecordType = [RecordType]::A
        }

        if ($cachedServer = Get-InternalDnsCacheRecord -Name $ComputerName -RecordType $ServerRecordType) {
            Write-Debug ('Resolve-DnsServer: Cache: Using Server ({0}) from cache.' -f $ComputerName)

            return $cachedServer | Select-Object -First 1 | Select-Object -ExpandProperty IPAddress
        } else {
            $dnsResponse = Get-Dns -Name $ComputerName -RecordType $ServerRecordType

            if ($dnsResponse.Answer) {
                $ipAddress = $dnsResponse.Answer | Select-Object -First 1 | Select-Object -ExpandProperty IPAddress

                Write-Debug ('Resolve-DnsServer: Cache: Adding Server ({0}) to cache.' -f $ComputerName)
                $dnsResponse.Answer | Add-InternalDnsCacheRecord

                return $ipAddress
            }
        }
    }

    $errorRecord = [ErrorRecord]::new(
        [ArgumentException]::new('Unable to find an IP address for the specified name server ({0})' -f $ComputerName),
        'ArgumentException',
        [ErrorCategory]::InvalidArgument,
        $ComputerName
    )
    $PSCmdlet.ThrowTerminatingError($errorRecord)
}
#EndRegion '.\private\ResolveDnsServer.ps1' 50
#Region '.\public\Add-InternalDnsCacheRecord.ps1' 0
function Add-InternalDnsCacheRecord {
    <#
    .SYNOPSIS
        Add a new CacheRecord to the DNS cache object.
 
    .DESCRIPTION
        The DNS cache is used to reduce the effort required to resolve DNS server names used with the ComputerName parameter.
 
    .INPUTS
        DnsCacheRecord
        DnsResourceRecord
 
    .EXAMPLE
        $CacheRecord | Add-InternalDnsCacheRecord
    #>


    [CmdletBinding(DefaultParameterSetName = 'CacheRecord')]
    [OutputType('DnsCacheRecord')]
    param (
        # A record to add to the cache.
        [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'CacheRecord')]
        [DnsCacheRecord]$CacheRecord,

        # A resource record to add to the cache.
        [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ResourceRecord')]
        [DnsResourceRecord]$ResourceRecord,

        # The cache object type.
        [CacheResourceType]$ResourceType = 'Address',

        # A time property is used to age entries out of the cache. If permanent is set the time is not, the value will not be purged based on the TTL.
        [switch]$Permanent
    )

    process {
        if ($ResourceRecord) {
            $CacheRecord = $ResourceRecord
        }

        $CacheRecord.ResourceType = $ResourceType
        if ($Permanent) {
            $CacheRecord.IsPermanent = $true
        }

        if ($Script:dnsCache.Contains($CacheRecord.Name)) {
            if ($Script:dnsCache.Contains($CacheRecord.Name)) {
                $Script:dnsCache[$CacheRecord.Name] += $CacheRecord
            }
        } else {
            $Script:dnsCache.Add($CacheRecord.Name, @($CacheRecord))
        }
    }
}
#EndRegion '.\public\Add-InternalDnsCacheRecord.ps1' 54
#Region '.\public\Clear-InternalDnsCache.ps1' 0
function Clear-InternalDnsCache {
    <#
    .SYNOPSIS
        Clears expired entries from the internal DNS cache.
 
    .DESCRIPTION
        Clear expired entries from the internal DNS cache.
 
    .EXAMPLE
        Clear-InternalDnsCacheRecord
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param (
        [switch]$ExpiredOnly
    )

    if ($ExpiredOnly) {
        (Get-InternalDnsCacheRecord | Where-Object { $_.HasExpired() }) |
            Remove-InternalDnsCacheRecord
    } else {
        if ($PSCmdlet.ShouldProcess('Clearing DNS cache')) {
            $Script:dnsCache.Clear()
        }
    }
}
#EndRegion '.\public\Clear-InternalDnsCache.ps1' 27
#Region '.\public\Format-DnsResponse.ps1' 0
function Format-DnsResponse {
    <#
    .SYNOPSIS
        Format a DNS message section for display.
 
    .DESCRIPTION
        Format a DNS message section for display.
    #>


    [CmdletBinding()]
    param (
        # The DnsMessage to format.
        [Parameter(Mandatory)]
        [DnsMessage]$DnsMessage,

        # The section to format and return as a string.
        [Parameter(Mandatory)]
        [string]$Section
    )

    $maximumLength = $host.UI.RawUI.BufferSize.Width - 15

    $recordStrings = if ($DnsMessage.$Section.Count -gt 0) {
        foreach ($resourceRecord in $DnsMessage.$Section) {
            $string = $resourceRecord.ToString()
            if ($string.Length -gt $maximumLength) {
                '{0}...' -f $string.Substring(0, $maximumLength - 4)
            } else {
                $string
            }
        }
    }

    $recordStrings -join "`n"
}
#EndRegion '.\public\Format-DnsResponse.ps1' 36
#Region '.\public\Get-Dns.ps1' 0
#using namespace System.Management.Automation
#using namespace System.Net.Sockets

function Get-Dns {
    <#
    .SYNOPSIS
        Get a DNS resource record from a DNS server.
 
    .DESCRIPTION
        Get-Dns is a debugging resolver tool similar to dig and nslookup.
 
    .EXAMPLE
        Get-Dns hostname
 
        Attempt to resolve hostname using the system-configured search list.
 
    .EXAMPLE
        Get-Dns www.domain.example
 
        The system-configured search list will be appended to this query before it is executed.
 
    .EXAMPLE
        Get-Dns www.domain.example.
 
        The name is fully-qualified (or root terminated), no additional suffixes will be appended.
 
    .EXAMPLE
        Get-Dns example. -DnsSec
 
        Request ANY record for the co.uk domain, advertising DNSSEC support.
    #>


    [CmdletBinding()]
    [OutputType('DnsMessage')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '')]
    param (
        # A resource name to query, by default Get-Dns will use '.' as the name. IP addresses (IPv4 and IPv6) are automatically converted into an appropriate format to aid PTR queries.
        [Parameter(Position = 1, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [TransformDnsName()]
        [ValidateDnsName()]
        [string]$Name = '.',

        # Any resource record type, by default a query for ANY will be sent.
        [Parameter(Position = 2, ValueFromPipelineByPropertyName)]
        [Alias('Type')]
        [RecordType[]]$RecordType = @('A', 'AAAA'),

        # By default the class is IN. CH (Chaos) may be used to query for name server information. HS (Hesoid) may be used if the name server supports it.
        [RecordClass]$RecordClass = [RecordClass]::IN,

        # Remove the Recursion Desired (RD) flag from a query. Recursion is requested by default.
        [Alias('NoRecurse')]
        [switch]$NoRecursion,

        # Advertise support for DNSSEC when executing a query.
        [switch]$DnsSec,

        # Enable EDNS support, suppresses OPT RR advertising client support in DNS question. Automatically enabled if DNSSEC is requested.
        [switch]$EDns,

        # By default the EDns buffer size is set to 4096 bytes.
        [UInt16]$EDnsBufferSize = 4096,

        # Disables conversion of international domain names to unicode in responses.
        [switch]$DisableIdnConversion,

        # Disable the use of TCP if a truncated response (TC flag) is seen when using UDP.
        [Alias('Ignore')]
        [switch]$NoTcpFallback,

        # If a name is not root terminated (does not end with '.') a SearchList will be used for recursive queries. If this parameter is not defined Get-Dns will attempt to retrieve a SearchList from the hosts network configuration.
        #
        # An empty search list by be specified by providing an empty array for this parameter.
        [AllowEmptyCollection()]
        [string[]]$SearchList = (GetDnsSuffixSearchList),

        # Recursive, or version, queries can be forced to use TCP by setting the TCP switch parameter.
        [Alias('vc')]
        [switch]$Tcp,

        # By default, DNS uses TCP or UDP port 53. The port used to send queries may be changed if a server is listening on a different port.
        [UInt16]$Port = 53,

        # By default, queries will timeout after 5 seconds. The value may be set between 1 and 30 seconds.
        [ValidateRange(1, 30)]
        [byte]$Timeout = 5,

        # Force the use of IPv6 for queries, if this parameter is set and the ComputerName is set to a name (e.g. ns1.domain.example), Get-Dns will attempt to locate an AAAA record for the server.
        [switch]$IPv6,

        # A server name or IP address to execute a query against. If an IPv6 address is used Get-Dns will attempt the query using IPv6 (enables the IPv6 parameter).
        #
        # If a name is used another lookup will be required to resolve the name to an IP. Get-Dns caches responses for queries performed involving the Server parameter. The cache may be viewed and maintained using the *-InternalDnsCache CmdLets.
        #
        # If no server name is defined, the Get-DnsServerList command is used to discover locally configured DNS servers.
        [Alias('Server')]
        [string]$ComputerName = (Get-DnsServerList -IPv6:$IPv6 | Select-Object -First 1),

        # Forces Get-Dns to output intermediate requests which would normally be hidden, such as NXDomain replies when using a SearchList.
        [switch]$DnsDebug
    )

    begin {
        Clear-InternalDnsCache -ExpiredOnly
    }

    process {
        try {
            $serverIPAddress = ResolveDnsServer -ComputerName $ComputerName -IPv6:$IPv6
            if ($serverIPAdddress.AddressFamily -eq [AddressFamily]::InterNetworkv6) {
                Write-Verbose 'Resolve-DnsServer: IPv6 server value used. Using IPv6 transport.'
                $IPv6 = $true
            }
            $ComputerName = $serverIPAddress
        } catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }

        $querySearchList = $SearchList
        if ($Name.EndsWith('.')) {
            $querySearchList = ''
        } elseif ($Name.IndexOf('.') -ne $Name.LastIndexOf('.')) {
            $querySearchList += ''
        }

        $querySearchListPosition = 0
        :searchList foreach ($suffix in $querySearchList) {
            $querySearchListPosition++

            foreach ($rrType in $RecordType) {
                if ($suffix) {
                    $fullName = '{0}.{1}' -f $Name, $suffix
                } else {
                    $fullName = $Name
                }

                $dnsMessage = [DnsMessage]::new(
                    $fullName,
                    $rrType,
                    $RecordClass
                )

                if ($EDns -or $DnsSec) {
                    $dnsMessage.SetEDnsBufferSize($EDnsBufferSize)
                }
                if ($DnsSec) {
                    $dnsMessage.SetAcceptDnsSec()
                }
                if ($NoRecursion) {
                    $dnsMessage.DisableRecursion()
                }

                try {
                    $dnsClient = [DnsClient]::new(
                        $Tcp.IsPresent,
                        ([IPAddress]$ComputerName).AddressFamily -eq 'InterNetworkV6',
                        $Timeout,
                        $Timeout
                    )

                    $dnsClient.SendQuestion(
                        $dnsMessage,
                        $ComputerName,
                        $Port
                    )

                    $dnsResponse = $dnsClient.ReceiveAnswer(-not $DisableIdnConversion)
                    $dnsResponse.ComputerName = $dnsClient.RemoteEndPoint
                    $dnsResponse.TimeTaken = $dnsClient.TimeTaken.TotalMilliseconds
                    $dnsClient.Close()

                    if ($dnsResponse.Header.RCode -ne 'NXDOMAIN' -or
                        $querySearchListPosition -eq $querySearchList.Count -or
                        $dnsDebug) {

                        if ($dnsResponse.Header.Flags -band 'TC' -and -not $NoTcpFallback) {
                            Write-Debug 'Response is truncated. Resending using TCP'
                            Get-Dns @PSBoundParameters -Tcp

                            break searchList
                        } else {
                            $dnsResponse
                        }

                        if (-not $dnsDebug) {
                            break searchList
                        }
                    }
                } catch [SocketException] {
                    $errorRecord = [ErrorRecord]::new(
                        $_.Exception,
                        'Timeout',
                        [ErrorCategory]::ConnectionError,
                        $Socket
                    )
                    $PSCmdlet.ThrowTerminatingError($errorRecord)
                } catch {
                    $PSCmdlet.ThrowTerminatingError($_)
                }
            }
        }
    }
}
#EndRegion '.\public\Get-Dns.ps1' 205
#Region '.\public\Get-DnsServerList.ps1' 0
#using namespace System.Management.Automation
#using namespace System.Net.NetworkInformation
#using namespace System.Net.Sockets

function Get-DnsServerList {
    <#
    .SYNOPSIS
        Gets a list of network interfaces and attempts to return a list of DNS server IP addresses.
 
    .DESCRIPTION
        Get-DnsServerList uses System.Net.NetworkInformation to return a list of operational ethernet or wireless interfaces. IP properties are returned, and an attempt to return a list of DNS server addresses is made. If successful, the DNS server list is returned.
 
    .EXAMPLE
        Get-DnsServerList
 
        Get a list of DNS servers.
    .EXAMPLE
        Get-DnsServerList -IPv6
 
        Get a list of IPv6 DNS servers.
    #>


    [CmdletBinding()]
    [OutputType([IPAddress])]
    param (
        # Find DNS servers which support IPv6.
        [switch]$IPv6
    )

    if ($IPv6) {
        $AddressFamily = [AddressFamily]::InterNetworkv6
    } else {
        $AddressFamily = [AddressFamily]::InterNetwork
    }

    if ([NetworkInterface]::GetIsNetworkAvailable()) {
        [NetworkInterface]::GetAllNetworkInterfaces() |
            Where-Object { $_.OperationalStatus -eq 'Up' -and $_.NetworkInterfaceType -match 'Ethernet|Wireless' } |
            ForEach-Object { $_.GetIPProperties().DnsAddresses } |
            Where-Object AddressFamily -eq $AddressFamily
    } else {
        $errorRecord = [ErrorRecord]::new(
            [InvalidOperationException]::new('Failed to locate an available network'),
            'NoDnsServersAvailable',
            'InvalidOperation',
            $null
        )
        $PSCmdlet.ThrowTerminatingError($errorRecord)
    }
}
#EndRegion '.\public\Get-DnsServerList.ps1' 51
#Region '.\public\Get-DnsVersion.ps1' 0
function Get-DnsVersion {
    <#
    .SYNOPSIS
        Get the DNS server version.
 
    .DESCRIPTION
        Attempt to get the DNS server version by sending a request for version.bind. using the CH class.
 
        DNS servers often refuse queries for the version number.
 
    .EXAMPLE
        Get-DnsVersion
 
        Get the version of the default DNS server.
 
    .EXAMPLE
        Get-DnsVersion -ComputerName 127.0.0.1
 
        Get the version of the DNS server running on 127.0.0.1.
 
    #>


    [CmdletBinding()]
    param (
        # Recursive, or version, queries can be forced to use TCP by setting the TCP switch parameter.
        [Alias('vc')]
        [switch]$Tcp,

        # By default, DNS uses TCP or UDP port 53. The port used to send queries may be changed if a server is listening on a different port.
        [UInt16]$Port = 53,

        # By default, queries will timeout after 5 seconds. The value may be set between 1 and 30 seconds.
        [ValidateRange(1, 30)]
        [byte]$Timeout = 5,

        # Force the use of IPv6 for queries, if this parameter is set and the ComputerName is set to a name (e.g. ns1.domain.example), Get-Dns will attempt to locate an AAAA record for the server.
        [switch]$IPv6,

        # A server name or IP address to execute a query against. If an IPv6 address is used Get-Dns will attempt the query using IPv6 (enables the IPv6 parameter).
        #
        # If a name is used another lookup will be required to resolve the name to an IP. Get-Dns caches responses for queries performed involving the Server parameter. The cache may be viewed and maintained using the *-InternalDnsCache CmdLets.
        #
        # If no server name is defined, the Get-DnsServerList command is used to discover locally configured DNS servers.
        [Alias('Server')]
        [string]$ComputerName
    )

    $params = @{
        Name        = 'version.bind.'
        RecordType  = 'TXT'
        RecordClass = 'CH'
    }
    Get-Dns @params @psboundparameters
}
#EndRegion '.\public\Get-DnsVersion.ps1' 55
#Region '.\public\Get-DnsZoneTransfer.ps1' 0
function Get-DnsZoneTransfer {
    <#
    .SYNOPSIS
        Get the content of a DNS zone using zone transfer.
 
    .DESCRIPTION
        Get the content of a DNS zone using zone transfer.
    #>


    [CmdletBinding()]
    param (
        # The name of the zone to transfer.
        [Parameter(Mandatory, Position = 1, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [TransformDnsName()]
        [ValidateDnsName()]
        [string]$ZoneName,

        # If the serial number is set, an incremental zone transfer is performed.
        [UInt32]$SerialNumber,

        # By default, DNS uses TCP or UDP port 53. The port used to send queries may be changed if a server is listening on a different port.
        [UInt16]$Port = 53,

        # By default, queries will timeout after 5 seconds. The value may be set between 1 and 30 seconds.
        [ValidateRange(1, 30)]
        [byte]$Timeout = 5,

        # Force the use of IPv6 for queries, if this parameter is set and the ComputerName is set to a name (e.g. ns1.domain.example), Get-Dns will attempt to locate an AAAA record for the server.
        [switch]$IPv6,

        # A server name or IP address to execute a query against. If an IPv6 address is used Get-Dns will attempt the query using IPv6 (enables the IPv6 parameter).
        #
        # If a name is used another lookup will be required to resolve the name to an IP. Get-Dns caches responses for queries performed involving the Server parameter. The cache may be viewed and maintained using the *-InternalDnsCache CmdLets.
        #
        # If no server name is defined, the Get-DnsServerList command is used to discover locally configured DNS servers.
        [Alias('Server')]
        [string]$ComputerName
    )

    begin {
        try {
            $serverIPAddress = ResolveDnsServer -ComputerName $ComputerName -IPv6:$IPv6
            if ($serverIPAdddress.AddressFamily -eq [AddressFamily]::InterNetworkv6) {
                Write-Verbose 'IPv6 server value used. Using IPv6 transport.'
                $IPv6 = $true
            }
            $ComputerName = $serverIPAddress
        } catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }

    process {
        if ($SerialNumber) {
            $dnsMessage = [DnsMessage]::new(
                $ZoneName,
                'IXFR',
                'IN',
                $SerialNumber
            )
        } else {
            $dnsMessage = [DnsMessage]::new(
                $ZoneName,
                'AXFR',
                'IN'
            )
        }

        $dnsClient = [DnsClient]::new(
            $true,
            ([IPAddress]$ComputerName).AddressFamily -eq 'InterNetworkV6',
            $Timeout,
            $Timeout
        )

        $dnsClient.SendQuestion(
            $dnsMessage,
            $ComputerName,
            $Port
        )

        $dnsResponse = $dnsClient.ReceiveAnswer()
        $dnsResponse.ComputerName = $dnsClient.RemoteEndPoint
        $dnsResponse.TimeTaken = $dnsClient.TimeTaken.TotalMilliseconds
        $dnsClient.Close()

        $dnsResponse
    }
}
#EndRegion '.\public\Get-DnsZoneTransfer.ps1' 90
#Region '.\public\Get-InternalDnsCacheRecord.ps1' 0
function Get-InternalDnsCacheRecord {
    <#
    .SYNOPSIS
        Get the content of the internal DNS cache used by Get-Dns.
 
    .DESCRIPTION
        Get-InternalDnsCacheRecord displays records held in the cache.
 
    .INPUTS
        Indented.Net.Dns.CacheRecord
 
    .EXAMPLE
        Get-InternalDnsCacheRecord
 
    .EXAMPLE
        Get-InternalDnsCacheRecord a.root-servers.net A
    #>


    [CmdletBinding()]
    [OutputType('DnsCacheRecord')]
    param (
        # The name of the record to retrieve.
        [Parameter(Position = 1, ValueFromPipelineByPropertyName)]
        [string]$Name,

        # The record type to retrieve.
        [Parameter(Position = 2, ValueFromPipelineByPropertyName)]
        [string]$RecordType,

        # The resource type to retrieve.
        [ValidateSet('Address', 'Hint')]
        [string]$ResourceType
    )

    process {
        if ($Name) {
            if (-not $Name.EndsWith('.')) {
                $Name += '.'
            }
            if ($Script:dnsCache.Contains($Name)) {
                $Script:dnsCache[$Name] | Where-Object {
                    -not $RecordType -or $_.RecordType -eq $RecordType
                }
            }
        } else {
            $Script:dnsCache.Values | ForEach-Object { $_ } | Where-Object {
                (-not $RecordType -or $_.RecordType -eq $RecordType) -and
                (-not $ResourceType -or $_.ResourceType -eq $ResourceType)
            }
        }
    }
}
#EndRegion '.\public\Get-InternalDnsCacheRecord.ps1' 53
#Region '.\public\Initialize-InternalDnsCache.ps1' 0
function Initialize-InternalDnsCache {
    <#
    .SYNOPSIS
        Initializes a basic DNS cache for use by Get-Dns.
 
    .DESCRIPTION
        Get-Dns maintains a limited DNS cache, capturing A and AAAA records, to assist name server resolution (for values passed using the Server parameter).
 
        The cache may be manipulated using *-InternalDnsCacheRecord Cmdlets.
 
    .EXAMPLE
        Initialize-InternalDnsCache
 
        Initialize the cache.
    #>


    [CmdletBinding()]
    param( )

    $Script:dnsCache = @{}

    $path = Join-Path $MyInvocation.MyCommand.Module.ModuleBase 'var\named.root'
    if (Test-Path $path) {
        Get-Content $path |
            Where-Object { -not $_.StartsWith(';') -and $_ -cmatch '\d+\s+A' } |
            ForEach-Object { [DnsCacheRecord]::Parse($_) } |
            Add-InternalDnsCacheRecord -ResourceType Hint -Permanent
    }
}
#EndRegion '.\public\Initialize-InternalDnsCache.ps1' 30
#Region '.\public\Remove-InternalDnsCacheRecord.ps1' 0
function Remove-InternalDnsCacheRecord {
    <#
    .SYNOPSIS
        Remove a single entry from the internal DNS cache.
 
    .DESCRIPTION
        Remove a single entry from the internal DNS cache.
 
    .EXAMPLE
        Remove-InternalDnsCacheRecord someName -RecordType A
 
        Remove someName from the cache.
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param (
        # The name of the record to retrieve.
        [Parameter(Position = 1, ValueFromPipelineByPropertyName)]
        [string]$Name,

        # The record type to retrieve.
        [Parameter(Position = 2, ValueFromPipelineByPropertyName)]
        [ValidateSet('A', 'AAAA')]
        [RecordType]$RecordType
    )

    process {
        if (-not $Name.EndsWith('.')) {
            $Name += '.'
        }

        if ($Script:dnsCache.Contains($Name)) {
            if ($PSCmdlet.ShouldProcess('Removing {0} from cache' -f $Name)) {
                if ($RecordType) {
                    $Script:dnsCache[$Name] = $Script:dnsCache[$Name] | Where-Object {
                        $_.RecordType -ne $RecordType
                    }

                    if ($Script:dnsCache[$Name].Count -eq 0) {
                        $Script:dnsCache.Remove($Name)
                    }
                } else {
                    $Script:dnsCache.Remove($Name)
                }
            }
        }
    }
}
#EndRegion '.\public\Remove-InternalDnsCacheRecord.ps1' 49
#Region '.\public\Search-Dns.ps1' 0
function Search-Dns {
    <#
    .SYNOPSIS
        Search all name servers for a specific record.
 
    .DESCRIPTION
        Search-Dns may be used to retrieve a resource record from all name servers for a given domain.
    #>


    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]
    [CmdletBinding()]
    param (
        # The name of the record to search for. The name can either be fully-qualified or relative to the zone name.
        [Parameter(Mandatory, Position = 1, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [AllowEmptyString()]
        [TransformDnsName()]
        [string]$Name,

        # The zone name is used to ensure the correct zone is searched for records. This avoids the need for tricks to discover the authority for record types such as CNAME.
        [Parameter(Mandatory, Position = 2, ValueFromPipelineByPropertyName)]
        [TransformDnsName()]
        [ValidateDnsName()]
        [string]$ZoneName,

        # The record type to search for.
        [Parameter(Position = 3, ValueFromPipelineByPropertyName)]
        [RecordType]$RecordType = 'ANY',

        # Advertise support for DNSSEC when executing a query.
        [switch]$DnsSec,

        # Recursive, or version, queries can be forced to use TCP by setting the TCP switch parameter.
        [Alias('vc')]
        [switch]$Tcp,

        # By default, DNS uses TCP or UDP port 53. The port used to send queries may be changed if a server is listening on a different port.
        [UInt16]$Port = 53,

        # By default, queries will timeout after 5 seconds. The value may be set between 1 and 30 seconds.
        [ValidateRange(1, 30)]
        [byte]$Timeout = 5,

        # Force the use of IPv6 for queries, if this parameter is set and the ComputerName is set to a name (e.g. ns1.domain.example), Get-Dns will attempt to locate an AAAA record for the server.
        [switch]$IPv6,

        # A server name or IP address to execute a query against. If an IPv6 address is used Get-Dns will attempt the query using IPv6 (enables the IPv6 parameter).
        #
        # If a name is used another lookup will be required to resolve the name to an IP. Get-Dns caches responses for queries performed involving the Server parameter. The cache may be viewed and maintained using the *-InternalDnsCache CmdLets.
        #
        # If no server name is defined, the Get-DnsServerList command is used to discover locally configured DNS servers.
        [Alias('Server')]
        [string]$ComputerName
    )

    process {
        $null = $PSBoundParameters.Remove('Name')
        $null = $PSBoundParameters.Remove('ZoneName')
        $null = $PSBoundParameters.Remove('RecordType')

        $params = @{
            Name       = $ZoneName = '{0}.' -f $ZoneName.TrimEnd('.')
            RecordType = 'NS'
        }
        $dnsResponse = Get-Dns @params @psboundparameters

        $Name = '{0}.' -f $Name.TrimEnd('.')
        if (-not $Name.EndsWith($ZoneName, 'InvariantCultureIgnoreCase')) {
            $Name = '{0}{1}' -f $Name, $ZoneName
        }
        $Name = $Name.TrimStart('.')

        foreach ($answer in $dnsResponse.Answer) {
            $nameServer = $answer.HostName

            $params = @{
                Name         = $Name
                RecordType   = $RecordType
                ComputerName = $nameServer
            }
            Get-Dns @params @psboundparameters
        }
    }
}
#EndRegion '.\public\Search-Dns.ps1' 84
#Region '.\public\Trace-Dns.ps1' 0
function Trace-Dns {
    <#
    .SYNOPSIS
        Iteratively trace resolution of a name from a root or specified name server.
 
    .DESCRIPTION
        Trace-Dns attempts to resolve a name from a root or specified name server by following authority records.
 
    .EXAMPLE
        Trace-Dns www.google.com.
 
        Trace resolution of www.googl.com from the root servers down.
    #>


    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]
    [CmdletBinding()]
    param (
        # The name of the record to search for. The name can either be fully-qualified or relative to the zone name.
        [Parameter(Mandatory, Position = 1, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [TransformDnsName()]
        [ValidateDnsName()]
        [string]$Name,

        # The record type to search for.
        [Parameter(Position = 3, ValueFromPipelineByPropertyName)]
        [RecordType]$RecordType = 'ANY',

        # Advertise support for DNSSEC when executing a query.
        [switch]$DnsSec,

        # Recursive, or version, queries can be forced to use TCP by setting the TCP switch parameter.
        [Alias('vc')]
        [switch]$Tcp,

        # By default, DNS uses TCP or UDP port 53. The port used to send queries may be changed if a server is listening on a different port.
        [UInt16]$Port = 53,

        # By default, queries will timeout after 5 seconds. The value may be set between 1 and 30 seconds.
        [ValidateRange(1, 30)]
        [byte]$Timeout = 5,

        # Force the use of IPv6 for queries, if this parameter is set and the ComputerName is set to a name (e.g. ns1.domain.example), Get-Dns will attempt to locate an AAAA record for the server.
        [switch]$IPv6,

        # A server name or IP address to execute a query against. If an IPv6 address is used Get-Dns will attempt the query using IPv6 (enables the IPv6 parameter).
        #
        # If a name is used another lookup will be required to resolve the name to an IP. Get-Dns caches responses for queries performed involving the Server parameter. The cache may be viewed and maintained using the *-InternalDnsCache CmdLets.
        #
        # If no server name is defined, the Get-DnsServerList command is used to discover locally configured DNS servers.
        [Alias('Server')]
        [string]$ComputerName
    )

    begin {
        if (-not $ComputerName) {
            $nameServerRecordType = 'A'
            if ($IPv6) {
                $nameServerRecordType = 'AAAA'
            }

            $rootHints = Get-InternalDnsCacheRecord -RecordType $nameServerRecordType -ResourceType Hint
            $ComputerName = $rootHints.Name | Sort-Object { Get-Random } | Select-Object -First 1
        }
    }

    process {
        do {
            $null = $PSBoundParameters.Remove('ComputerName')
            $dnsResponse = Get-Dns @PSBoundParameters -NoRecursion -ComputerName $ComputerName

            if ($dnsResponse.Header.AuthorityCount -gt 0) {
                $ComputerName = $dnsResponse.Authority[0].Hostname
            }

            $dnsResponse
        } until ($dnsResponse.Header.AnswerCount -gt 0 -or $dnsResponse.Header.RCode -ne 'NOERROR')
    }
}
#EndRegion '.\public\Trace-Dns.ps1' 79
#Region '.\public\Update-InternalRootHint.ps1' 0
function Update-InternalRootHint {
    <#
    .SYNOPSIS
        Updates the root hints file from InterNIC then re-initializes the internal cache.
 
    .DESCRIPTION
        The root hints file is used as the basis of an internal DNS cache. The content of the root hints file is used during iterative name resolution.
 
    .PARAMETER Source
        Update-InternalRootHints attempts to download a named.root file from InterNIC by default. An alternative root hints source may be specified here.
 
    .EXAMPLE
        Update-InternalRootHints
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Uri]$Source = 'http://www.internic.net/domain/named.root'
    )

    $path = Join-Path $MyInvocation.MyCommand.Module.ModuleBase 'var\named.root'
    if ($PSCmdlet.ShouldProcess('Updating {0}' -f $path)) {
        Invoke-WebRequest -Uri $Source -OutFile $path
        Initialize-InternalDnsCache
    }
}
#EndRegion '.\public\Update-InternalRootHint.ps1' 27
#Region '.\InitializeModule.ps1' 0
# Resolver (Message): Initialize the DNS cache for Get-Dns
Initialize-InternalDnsCache

# Resolver (Message): Set a variable to store TC state.
New-Variable DnsTCEndFound -Scope Script -Value $false
#EndRegion '.\InitializeModule.ps1' 6