1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

use std::ffi::CStr;
use crate::error::Error;
use libresolv_sys::__ns_rr as Rr;
use libresolv_sys::__ns_msg as Message;

mod class;
pub use self::class::Class;

/// For internal use.
pub trait RecordData: Sized {
    /// Get type of record
    fn get_record_type() -> RecordType;

    /// Convert from low level resource record.  For internal use.
    fn extract(msg: &mut Message, rr: &Rr) -> Result<Self, Error>;
}

/// A DNS response record of a particular type
#[derive(Debug, Clone)]
pub struct Record<T: RecordData> {
    pub name: String,
    pub class: Class,
    pub ttl: u32,
    pub data: T
}

impl<T: RecordData> Record<T> {
    /// For internal use.
    pub fn extract(msg: &mut Message, rr: &Rr) -> Result<Record<T>, Error> {
        Ok(Record {
            name: unsafe { CStr::from_ptr(rr.name.as_ptr()).to_string_lossy().into_owned() },
            class: Class::from_rr_class(rr.rr_class)?,
            ttl: rr.ttl,
            data: <T as RecordData>::extract(msg, rr)?,
        })
    }
}

/// This is a simple u16 value indicating the type of a resource record, and is equal in
/// value to `::libresolv_sys::__ns_type`, but we have extended it with record types not
/// present or supported by the underlying library
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(non_camel_case_types)]
#[repr(u16)]
pub enum RecordType {
    /// RFC 1035 - Host Address
    A = 1,
    /// RFC 1035 - Authoritative Name Server
    NS = 2,
    /// RFC 1035 - Mail Destination (Obsolete, use MX)
    MD = 3,
    /// RFC 1035 - Mail Forwarder (Obsolete, use MX)
    MF = 4,
    /// RFC 1035, 4035, 6604 - Canonical Name for an Alias
    CNAME = 5,
    /// RFC 1035, 1982, 2181, 2308 - Start of a Zone of Authority
    SOA = 6,
    /// RFC 1035 - Mailbox Domain Name (EXPERIMENTAL)
    MB = 7,
    /// RFC 1035 - Mail Group Member (EXPERIMENTAL)
    MG = 8,
    /// RFC 1035 - Mail Rename Domain Name (EXPERIMENTAL)
    MR = 9,
    /// RFC 1035 - A null resource record (EXPERIMENTAL)
    NULL = 10,
    /// RFC 1035 - A well known service description
    WKS = 11,
    /// RFC 1035 - A domain name pointer
    PTR = 12,
    /// RFC 1035 - Host information
    HINFO = 13,
    /// RFC 1035 - Mailbox or mail list information
    MINFO = 14,
    /// RFC 1035 - Mail exchange
    MX = 15,
    /// RFC 1035 - Text strings
    TXT = 16,
    /// RFC 1183 - Responsible Person
    RP = 17,
    /// RFC 1183, 6895 - AFS Database Location (Deprecated by RFC5864)
    AFSDB = 18,
    /// RFC 1183 - X.25 Addresses (EXPERIMENTAL)
    X25 = 19,
    /// RFC 1183 - ISDN Addresses (EXPERIMENTAL)
    ISDN = 20,
    /// RFC 1183 - Route Through (EXPERIMENTAL)
    RT = 21,
    /// RFC 1706 - Network Service Access Protocol
    NSAP = 22,
    /// RFC 1706 - Network Service Access Protocol PTR
    NSAP_PTR = 23,
    /// RFC 2535 (Obsolete), 2931 - Signautre
    SIG = 24,
    /// RFC 2535 (Obsolete) - Key
    KEY = 25,
    /// RFC 2163, 3597 - Pointer to X.400/RFC822 mapping information
    PX = 26,
    /// RFC 1712 - Geographical location
    GPOS = 27,
    /// RFC 3596 - IPv6 Address
    AAAA = 28,
    /// RFC 1876 - Location Information
    LOC = 29,
    /// RFC 2535 (Obsolete) - Non-existant Names and Types
    NXT = 30,
    /// https://tools.ietf.org/html/draft-ietf-nimrod-dns-00 - Endpoint Identifier
    EID = 31,
    /// https://tools.ietf.org/html/draft-ietf-nimrod-dns-00 - Nimrod Locator
    NIMLOC = 32,
    /// RFC 2782, 6335 - Service Location
    SRV = 33,
    ATMA = 34,
    NAPTR = 35,
    KX = 36,
    CERT = 37,
    A6 = 38,
    /// RFC 2672, 6604 - Delegation Name
    DNAME = 39,
    SINK = 40,
    /// RFC 6891, 6895 - Option
    OPT = 41,
    APL = 42,
    /// RFC 4033, 4034, 4035, 4509 - Delegation signer
    DS = 43,
    /// RFC 4255 -SSH Public Key Fingerprint
    SSHFP = 44,
    /// IPsec Key
    IPSECKEY = 45,
    /// RFC 4033, 4034, 4035, 5702 - DNSSEC signature
    RRSIG = 46,
    /// RFC 4033, 4034, 4035, 4470 - Next Secure record
    NSEC = 47,
    /// RFC 4033, 4034, 4035, 5702 - DNS Key
    DNSKEY = 48,
    /// RFC 4701 - DHCP identifier
    DHCID = 49,
    /// RFC 5155 - Next Secure record version 3
    NSEC3 = 50,
    /// RFC 5155 - NSEC3 parameters
    NSEC3PARAM = 51,
    /// RFC 6698 - DNS-Based Authentication for TLS
    TLSA = 52,
    /// RFC 5205 - Host Identity Protocol
    HIP = 55,
    /// Child DS - RFC 7344
    CDS = 59,
    /// Child DNSKEY - RFC 7344
    CDNSKEY = 60,
    /// RFC 2930 - Transtion Key record
    TKEY = 249,
    /// RFC 2845, 3645, 4635, 6895 - Transaction Signature
    TSIG = 250,
    /// RFC 1995 - Incremental Zone Transfer
    IXFR = 251,
    /// RFC 1035, 5936 - A request for a transfer of an entire zone
    AXFR = 252,
    /// RFC 1035 - A request for mailbox-related records (MB, MG or MR)
    MAILB = 253,
    /// RFC 1035 - A request for mail agent RRs (Obsolete - see MX)
    MAILA = 254,
    /// RFC 1035 - A request for all records
    ANY = 255,
    /// ALSO URI=256, see RFC 7553
    ZXFR = 256,
    /// RFC 6844 - Certification Authority Authorization
    CAA = 257,
    /// DNSSEC Trust Authorities
    TA = 32768,
    /// RFC 4431 - DNSSEC Lookaside Validation record
    DLV = 32769,
}

// FIXME: Add the other record types
pub use self::a::A;
pub use self::ns::NS;
pub use self::cname::CNAME;
pub use self::soa::SOA;
pub use self::ptr::PTR;
pub use self::mx::MX;
pub use self::txt::TXT;
pub use self::aaaa::AAAA;
pub use self::tlsa::TLSA;

// FIXME: Add the other record types
mod a;
mod ns;
mod cname;
mod soa;
mod ptr;
mod mx;
mod txt;
mod aaaa;
mod tlsa;