Skip to main content

c_ares/dns/
enums.rs

1use std::ffi::CString;
2use std::fmt;
3use std::str::FromStr;
4
5use bitflags::bitflags;
6
7use crate::error::{Error, Result};
8use crate::utils::dns_string_as_str;
9
10/// DNS record types handled by c-ares.
11#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
12#[allow(clippy::upper_case_acronyms, non_camel_case_types)]
13pub enum DnsRecordType {
14    /// Host address (A).
15    A,
16    /// Authoritative server (NS).
17    NS,
18    /// Canonical name (CNAME).
19    CNAME,
20    /// Start of authority zone (SOA).
21    SOA,
22    /// Domain name pointer (PTR).
23    PTR,
24    /// Host information (HINFO).
25    HINFO,
26    /// Mail routing information (MX).
27    MX,
28    /// Text strings (TXT).
29    TXT,
30    /// SIG record (RFC 2535 / RFC 2931).
31    SIG,
32    /// IPv6 address (AAAA, RFC 3596).
33    AAAA,
34    /// Server selection (SRV, RFC 2782).
35    SRV,
36    /// Naming authority pointer (NAPTR, RFC 3403).
37    NAPTR,
38    /// EDNS0 option (OPT, RFC 6891).
39    OPT,
40    /// DANE TLSA (RFC 6698).
41    TLSA,
42    /// General purpose service binding (SVCB, RFC 9460).
43    SVCB,
44    /// HTTPS service binding (RFC 9460).
45    HTTPS,
46    /// Wildcard match (requests only).
47    ANY,
48    /// URI (RFC 7553).
49    URI,
50    /// Certification authority authorization (CAA, RFC 6844).
51    CAA,
52    /// Raw/unparsed RR record.
53    RAW_RR,
54    /// Unknown record type, carrying the raw wire value.
55    UNKNOWN(u32),
56}
57
58impl From<DnsRecordType> for c_ares_sys::ares_dns_rec_type_t {
59    fn from(val: DnsRecordType) -> Self {
60        match val {
61            DnsRecordType::A => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_A,
62            DnsRecordType::NS => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_NS,
63            DnsRecordType::CNAME => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_CNAME,
64            DnsRecordType::SOA => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SOA,
65            DnsRecordType::PTR => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_PTR,
66            DnsRecordType::HINFO => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_HINFO,
67            DnsRecordType::MX => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_MX,
68            DnsRecordType::TXT => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_TXT,
69            DnsRecordType::SIG => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SIG,
70            DnsRecordType::AAAA => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_AAAA,
71            DnsRecordType::SRV => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SRV,
72            DnsRecordType::NAPTR => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_NAPTR,
73            DnsRecordType::OPT => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_OPT,
74            DnsRecordType::TLSA => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_TLSA,
75            DnsRecordType::SVCB => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SVCB,
76            DnsRecordType::HTTPS => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_HTTPS,
77            DnsRecordType::ANY => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_ANY,
78            DnsRecordType::URI => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_URI,
79            DnsRecordType::CAA => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_CAA,
80            DnsRecordType::RAW_RR => c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_RAW_RR,
81            DnsRecordType::UNKNOWN(raw) => c_ares_sys::ares_dns_rec_type_t(raw),
82        }
83    }
84}
85
86impl From<c_ares_sys::ares_dns_rec_type_t> for DnsRecordType {
87    fn from(val: c_ares_sys::ares_dns_rec_type_t) -> Self {
88        match val {
89            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_A => DnsRecordType::A,
90            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_NS => DnsRecordType::NS,
91            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_CNAME => DnsRecordType::CNAME,
92            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SOA => DnsRecordType::SOA,
93            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_PTR => DnsRecordType::PTR,
94            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_HINFO => DnsRecordType::HINFO,
95            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_MX => DnsRecordType::MX,
96            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_TXT => DnsRecordType::TXT,
97            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SIG => DnsRecordType::SIG,
98            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_AAAA => DnsRecordType::AAAA,
99            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SRV => DnsRecordType::SRV,
100            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_NAPTR => DnsRecordType::NAPTR,
101            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_OPT => DnsRecordType::OPT,
102            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_TLSA => DnsRecordType::TLSA,
103            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_SVCB => DnsRecordType::SVCB,
104            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_HTTPS => DnsRecordType::HTTPS,
105            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_ANY => DnsRecordType::ANY,
106            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_URI => DnsRecordType::URI,
107            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_CAA => DnsRecordType::CAA,
108            c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_RAW_RR => DnsRecordType::RAW_RR,
109            other => DnsRecordType::UNKNOWN(other.0),
110        }
111    }
112}
113
114impl fmt::Display for DnsRecordType {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        if let DnsRecordType::UNKNOWN(raw) = self {
117            return write!(f, "TYPE{raw}");
118        }
119        let ptr = unsafe { c_ares_sys::ares_dns_rec_type_tostr((*self).into()) };
120        f.write_str(unsafe { dns_string_as_str(ptr) })
121    }
122}
123
124impl FromStr for DnsRecordType {
125    type Err = Error;
126
127    fn from_str(s: &str) -> Result<Self> {
128        let c_str = CString::new(s).map_err(|_| Error::EBADSTR)?;
129        let mut qtype = c_ares_sys::ares_dns_rec_type_t::ARES_REC_TYPE_A;
130        let ok = unsafe { c_ares_sys::ares_dns_rec_type_fromstr(&raw mut qtype, c_str.as_ptr()) };
131        if ok == c_ares_sys::ares_bool_t::ARES_TRUE {
132            Ok(DnsRecordType::from(qtype))
133        } else {
134            Err(Error::EFORMERR)
135        }
136    }
137}
138
139/// DNS classes for requests and responses.
140#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
141pub enum DnsCls {
142    /// Internet.
143    IN,
144    /// CHAOS.
145    CHAOS,
146    /// Hesiod.
147    HESIOD,
148    /// None (RFC 2136).
149    NONE,
150    /// Any class (requests only).
151    ANY,
152    /// Unknown class, carrying the raw wire value.
153    UNKNOWN(u32),
154}
155
156impl From<DnsCls> for c_ares_sys::ares_dns_class_t {
157    fn from(val: DnsCls) -> Self {
158        match val {
159            DnsCls::IN => c_ares_sys::ares_dns_class_t::ARES_CLASS_IN,
160            DnsCls::CHAOS => c_ares_sys::ares_dns_class_t::ARES_CLASS_CHAOS,
161            DnsCls::HESIOD => c_ares_sys::ares_dns_class_t::ARES_CLASS_HESOID,
162            DnsCls::NONE => c_ares_sys::ares_dns_class_t::ARES_CLASS_NONE,
163            DnsCls::ANY => c_ares_sys::ares_dns_class_t::ARES_CLASS_ANY,
164            DnsCls::UNKNOWN(raw) => c_ares_sys::ares_dns_class_t(raw),
165        }
166    }
167}
168
169impl From<c_ares_sys::ares_dns_class_t> for DnsCls {
170    fn from(val: c_ares_sys::ares_dns_class_t) -> Self {
171        match val {
172            c_ares_sys::ares_dns_class_t::ARES_CLASS_IN => DnsCls::IN,
173            c_ares_sys::ares_dns_class_t::ARES_CLASS_CHAOS => DnsCls::CHAOS,
174            c_ares_sys::ares_dns_class_t::ARES_CLASS_HESOID => DnsCls::HESIOD,
175            c_ares_sys::ares_dns_class_t::ARES_CLASS_NONE => DnsCls::NONE,
176            c_ares_sys::ares_dns_class_t::ARES_CLASS_ANY => DnsCls::ANY,
177            other => DnsCls::UNKNOWN(other.0),
178        }
179    }
180}
181
182impl fmt::Display for DnsCls {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        if let DnsCls::UNKNOWN(raw) = self {
185            return write!(f, "CLASS{raw}");
186        }
187        let ptr = unsafe { c_ares_sys::ares_dns_class_tostr((*self).into()) };
188        f.write_str(unsafe { dns_string_as_str(ptr) })
189    }
190}
191
192impl FromStr for DnsCls {
193    type Err = Error;
194
195    fn from_str(s: &str) -> Result<Self> {
196        let c_str = CString::new(s).map_err(|_| Error::EBADSTR)?;
197        let mut qclass = c_ares_sys::ares_dns_class_t::ARES_CLASS_IN;
198        let ok = unsafe { c_ares_sys::ares_dns_class_fromstr(&raw mut qclass, c_str.as_ptr()) };
199        if ok == c_ares_sys::ares_bool_t::ARES_TRUE {
200            Ok(DnsCls::from(qclass))
201        } else {
202            Err(Error::EFORMERR)
203        }
204    }
205}
206
207/// DNS message sections.
208#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
209pub enum DnsSection {
210    /// Answer section.
211    Answer,
212    /// Authority section.
213    Authority,
214    /// Additional information section.
215    Additional,
216}
217
218impl From<DnsSection> for c_ares_sys::ares_dns_section_t {
219    fn from(val: DnsSection) -> Self {
220        match val {
221            DnsSection::Answer => c_ares_sys::ares_dns_section_t::ARES_SECTION_ANSWER,
222            DnsSection::Authority => c_ares_sys::ares_dns_section_t::ARES_SECTION_AUTHORITY,
223            DnsSection::Additional => c_ares_sys::ares_dns_section_t::ARES_SECTION_ADDITIONAL,
224        }
225    }
226}
227
228impl From<c_ares_sys::ares_dns_section_t> for DnsSection {
229    fn from(val: c_ares_sys::ares_dns_section_t) -> Self {
230        match val {
231            c_ares_sys::ares_dns_section_t::ARES_SECTION_ANSWER => DnsSection::Answer,
232            c_ares_sys::ares_dns_section_t::ARES_SECTION_AUTHORITY => DnsSection::Authority,
233            c_ares_sys::ares_dns_section_t::ARES_SECTION_ADDITIONAL => DnsSection::Additional,
234        }
235    }
236}
237
238impl fmt::Display for DnsSection {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        let ptr = unsafe { c_ares_sys::ares_dns_section_tostr((*self).into()) };
241        f.write_str(unsafe { dns_string_as_str(ptr) })
242    }
243}
244
245/// DNS header opcodes.
246#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
247pub enum DnsOpcode {
248    /// Standard query.
249    Query,
250    /// Inverse query (obsolete).
251    IQuery,
252    /// Name server status query.
253    Status,
254    /// Zone change notification (RFC 1996).
255    Notify,
256    /// Zone update message (RFC 2136).
257    Update,
258}
259
260impl From<DnsOpcode> for c_ares_sys::ares_dns_opcode_t {
261    fn from(val: DnsOpcode) -> Self {
262        match val {
263            DnsOpcode::Query => c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_QUERY,
264            DnsOpcode::IQuery => c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_IQUERY,
265            DnsOpcode::Status => c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_STATUS,
266            DnsOpcode::Notify => c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_NOTIFY,
267            DnsOpcode::Update => c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_UPDATE,
268        }
269    }
270}
271
272impl From<c_ares_sys::ares_dns_opcode_t> for DnsOpcode {
273    fn from(val: c_ares_sys::ares_dns_opcode_t) -> Self {
274        match val {
275            c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_QUERY => DnsOpcode::Query,
276            c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_IQUERY => DnsOpcode::IQuery,
277            c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_STATUS => DnsOpcode::Status,
278            c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_NOTIFY => DnsOpcode::Notify,
279            c_ares_sys::ares_dns_opcode_t::ARES_OPCODE_UPDATE => DnsOpcode::Update,
280        }
281    }
282}
283
284impl fmt::Display for DnsOpcode {
285    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286        let ptr = unsafe { c_ares_sys::ares_dns_opcode_tostr((*self).into()) };
287        f.write_str(unsafe { dns_string_as_str(ptr) })
288    }
289}
290
291/// DNS response codes.
292#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
293pub enum DnsRcode {
294    /// Success.
295    NoError,
296    /// Format error.
297    FormErr,
298    /// Server failure.
299    ServFail,
300    /// Name error (NXDOMAIN).
301    NXDomain,
302    /// Not implemented.
303    NotImp,
304    /// Refused.
305    Refused,
306    /// Name exists when it should not (RFC 2136).
307    YXDomain,
308    /// RR set exists when it should not (RFC 2136).
309    YXRRSet,
310    /// RR set that should exist does not (RFC 2136).
311    NXRRSet,
312    /// Server not authoritative for zone (RFC 2136).
313    NotAuth,
314    /// Name not in zone (RFC 2136).
315    NotZone,
316    /// DSO-TYPE not implemented (RFC 8490).
317    DSOTypeI,
318    /// TSIG signature failure (RFC 8945).
319    BadSig,
320    /// Key not recognized (RFC 8945).
321    BadKey,
322    /// Signature out of time window (RFC 8945).
323    BadTime,
324    /// Bad TKEY mode (RFC 2930).
325    BadMode,
326    /// Duplicate key name (RFC 2930).
327    BadName,
328    /// Algorithm not supported (RFC 2930).
329    BadAlg,
330    /// Bad truncation (RFC 8945).
331    BadTrunc,
332    /// Bad/missing server cookie (RFC 7873).
333    BadCookie,
334}
335
336impl From<DnsRcode> for c_ares_sys::ares_dns_rcode_t {
337    fn from(val: DnsRcode) -> Self {
338        match val {
339            DnsRcode::NoError => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOERROR,
340            DnsRcode::FormErr => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_FORMERR,
341            DnsRcode::ServFail => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_SERVFAIL,
342            DnsRcode::NXDomain => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NXDOMAIN,
343            DnsRcode::NotImp => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTIMP,
344            DnsRcode::Refused => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_REFUSED,
345            DnsRcode::YXDomain => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_YXDOMAIN,
346            DnsRcode::YXRRSet => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_YXRRSET,
347            DnsRcode::NXRRSet => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NXRRSET,
348            DnsRcode::NotAuth => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTAUTH,
349            DnsRcode::NotZone => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTZONE,
350            DnsRcode::DSOTypeI => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_DSOTYPEI,
351            DnsRcode::BadSig => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADSIG,
352            DnsRcode::BadKey => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADKEY,
353            DnsRcode::BadTime => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADTIME,
354            DnsRcode::BadMode => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADMODE,
355            DnsRcode::BadName => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADNAME,
356            DnsRcode::BadAlg => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADALG,
357            DnsRcode::BadTrunc => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADTRUNC,
358            DnsRcode::BadCookie => c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADCOOKIE,
359        }
360    }
361}
362
363impl From<c_ares_sys::ares_dns_rcode_t> for DnsRcode {
364    fn from(val: c_ares_sys::ares_dns_rcode_t) -> Self {
365        match val {
366            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOERROR => DnsRcode::NoError,
367            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_FORMERR => DnsRcode::FormErr,
368            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_SERVFAIL => DnsRcode::ServFail,
369            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NXDOMAIN => DnsRcode::NXDomain,
370            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTIMP => DnsRcode::NotImp,
371            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_REFUSED => DnsRcode::Refused,
372            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_YXDOMAIN => DnsRcode::YXDomain,
373            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_YXRRSET => DnsRcode::YXRRSet,
374            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NXRRSET => DnsRcode::NXRRSet,
375            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTAUTH => DnsRcode::NotAuth,
376            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_NOTZONE => DnsRcode::NotZone,
377            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_DSOTYPEI => DnsRcode::DSOTypeI,
378            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADSIG => DnsRcode::BadSig,
379            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADKEY => DnsRcode::BadKey,
380            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADTIME => DnsRcode::BadTime,
381            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADMODE => DnsRcode::BadMode,
382            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADNAME => DnsRcode::BadName,
383            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADALG => DnsRcode::BadAlg,
384            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADTRUNC => DnsRcode::BadTrunc,
385            c_ares_sys::ares_dns_rcode_t::ARES_RCODE_BADCOOKIE => DnsRcode::BadCookie,
386        }
387    }
388}
389
390impl fmt::Display for DnsRcode {
391    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392        let ptr = unsafe { c_ares_sys::ares_dns_rcode_tostr((*self).into()) };
393        f.write_str(unsafe { dns_string_as_str(ptr) })
394    }
395}
396
397bitflags!(
398    /// DNS message header flags.
399    #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
400    pub struct DnsFlags: u16 {
401        /// QR — if set, this is a response.
402        const QR = c_ares_sys::ares_dns_flags_t::ARES_FLAG_QR as u16;
403        /// AA — authoritative answer.
404        const AA = c_ares_sys::ares_dns_flags_t::ARES_FLAG_AA as u16;
405        /// TC — truncation.
406        const TC = c_ares_sys::ares_dns_flags_t::ARES_FLAG_TC as u16;
407        /// RD — recursion desired.
408        const RD = c_ares_sys::ares_dns_flags_t::ARES_FLAG_RD as u16;
409        /// RA — recursion available.
410        const RA = c_ares_sys::ares_dns_flags_t::ARES_FLAG_RA as u16;
411        /// AD — authentic data (RFC 2065).
412        const AD = c_ares_sys::ares_dns_flags_t::ARES_FLAG_AD as u16;
413        /// CD — checking disabled (RFC 2065).
414        const CD = c_ares_sys::ares_dns_flags_t::ARES_FLAG_CD as u16;
415    }
416);
417
418bitflags!(
419    /// Flags controlling DNS message parsing behaviour.
420    #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
421    pub struct DnsParseFlags: u32 {
422        /// Parse answers from RFC 1035 (name-compressed) as raw.
423        const AN_BASE_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_AN_BASE_RAW as u32;
424        /// Parse authority from RFC 1035 (name-compressed) as raw.
425        const NS_BASE_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_NS_BASE_RAW as u32;
426        /// Parse additional from RFC 1035 (name-compressed) as raw.
427        const AR_BASE_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_AR_BASE_RAW as u32;
428        /// Parse answers from later RFCs (no name compression) as raw.
429        const AN_EXT_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_AN_EXT_RAW as u32;
430        /// Parse authority from later RFCs (no name compression) as raw.
431        const NS_EXT_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_NS_EXT_RAW as u32;
432        /// Parse additional from later RFCs (no name compression) as raw.
433        const AR_EXT_RAW = c_ares_sys::ares_dns_parse_flags_t::ARES_DNS_PARSE_AR_EXT_RAW as u32;
434    }
435);
436
437/// DNS resource record field keys.
438///
439/// Each variant identifies a specific field within a specific record type.
440/// The key determines which getter/setter method is appropriate (e.g.
441/// `get_addr` for `INADDR` fields, `get_str` for `NAME`/`STR` fields).
442#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
443#[allow(clippy::upper_case_acronyms, non_camel_case_types)]
444pub enum DnsRrKey {
445    /// A record: address (INADDR).
446    A_ADDR,
447    /// NS record: name server domain name (NAME).
448    NS_NSDNAME,
449    /// CNAME record: canonical name (NAME).
450    CNAME_CNAME,
451    /// SOA record: primary source of data (NAME).
452    SOA_MNAME,
453    /// SOA record: responsible mailbox (NAME).
454    SOA_RNAME,
455    /// SOA record: serial number (U32).
456    SOA_SERIAL,
457    /// SOA record: refresh interval (U32).
458    SOA_REFRESH,
459    /// SOA record: retry interval (U32).
460    SOA_RETRY,
461    /// SOA record: expire limit (U32).
462    SOA_EXPIRE,
463    /// SOA record: minimum TTL (U32).
464    SOA_MINIMUM,
465    /// PTR record: pointer domain name (NAME).
466    PTR_DNAME,
467    /// HINFO record: CPU (STR).
468    HINFO_CPU,
469    /// HINFO record: OS (STR).
470    HINFO_OS,
471    /// MX record: preference (U16).
472    MX_PREFERENCE,
473    /// MX record: exchange domain (NAME).
474    MX_EXCHANGE,
475    /// TXT record: data (ABINP).
476    TXT_DATA,
477    /// SIG record: type covered (U16).
478    SIG_TYPE_COVERED,
479    /// SIG record: algorithm (U8).
480    SIG_ALGORITHM,
481    /// SIG record: labels (U8).
482    SIG_LABELS,
483    /// SIG record: original TTL (U32).
484    SIG_ORIGINAL_TTL,
485    /// SIG record: signature expiration (U32).
486    SIG_EXPIRATION,
487    /// SIG record: signature inception (U32).
488    SIG_INCEPTION,
489    /// SIG record: key tag (U16).
490    SIG_KEY_TAG,
491    /// SIG record: signer's name (NAME).
492    SIG_SIGNERS_NAME,
493    /// SIG record: signature data (BIN).
494    SIG_SIGNATURE,
495    /// AAAA record: IPv6 address (INADDR6).
496    AAAA_ADDR,
497    /// SRV record: priority (U16).
498    SRV_PRIORITY,
499    /// SRV record: weight (U16).
500    SRV_WEIGHT,
501    /// SRV record: port (U16).
502    SRV_PORT,
503    /// SRV record: target domain (NAME).
504    SRV_TARGET,
505    /// NAPTR record: order (U16).
506    NAPTR_ORDER,
507    /// NAPTR record: preference (U16).
508    NAPTR_PREFERENCE,
509    /// NAPTR record: flags (STR).
510    NAPTR_FLAGS,
511    /// NAPTR record: services (STR).
512    NAPTR_SERVICES,
513    /// NAPTR record: regexp (STR).
514    NAPTR_REGEXP,
515    /// NAPTR record: replacement (NAME).
516    NAPTR_REPLACEMENT,
517    /// OPT record: UDP size (U16).
518    OPT_UDP_SIZE,
519    /// OPT record: version (U8).
520    OPT_VERSION,
521    /// OPT record: flags (U16).
522    OPT_FLAGS,
523    /// OPT record: options (OPT).
524    OPT_OPTIONS,
525    /// TLSA record: certificate usage (U8).
526    TLSA_CERT_USAGE,
527    /// TLSA record: selector (U8).
528    TLSA_SELECTOR,
529    /// TLSA record: matching type (U8).
530    TLSA_MATCH,
531    /// TLSA record: certificate association data (BIN).
532    TLSA_DATA,
533    /// SVCB record: priority (U16).
534    SVCB_PRIORITY,
535    /// SVCB record: target name (NAME).
536    SVCB_TARGET,
537    /// SVCB record: service parameters (OPT).
538    SVCB_PARAMS,
539    /// HTTPS record: priority (U16).
540    HTTPS_PRIORITY,
541    /// HTTPS record: target name (NAME).
542    HTTPS_TARGET,
543    /// HTTPS record: service parameters (OPT).
544    HTTPS_PARAMS,
545    /// URI record: priority (U16).
546    URI_PRIORITY,
547    /// URI record: weight (U16).
548    URI_WEIGHT,
549    /// URI record: target (NAME).
550    URI_TARGET,
551    /// CAA record: critical flag (U8).
552    CAA_CRITICAL,
553    /// CAA record: tag/property (STR).
554    CAA_TAG,
555    /// CAA record: value (BINP).
556    CAA_VALUE,
557    /// RAW record: RR type (U16).
558    RAW_RR_TYPE,
559    /// RAW record: RR data (BIN).
560    RAW_RR_DATA,
561}
562
563impl From<DnsRrKey> for c_ares_sys::ares_dns_rr_key_t {
564    fn from(val: DnsRrKey) -> Self {
565        match val {
566            DnsRrKey::A_ADDR => c_ares_sys::ares_dns_rr_key_t::ARES_RR_A_ADDR,
567            DnsRrKey::NS_NSDNAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NS_NSDNAME,
568            DnsRrKey::CNAME_CNAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_CNAME_CNAME,
569            DnsRrKey::SOA_MNAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_MNAME,
570            DnsRrKey::SOA_RNAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_RNAME,
571            DnsRrKey::SOA_SERIAL => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_SERIAL,
572            DnsRrKey::SOA_REFRESH => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_REFRESH,
573            DnsRrKey::SOA_RETRY => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_RETRY,
574            DnsRrKey::SOA_EXPIRE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_EXPIRE,
575            DnsRrKey::SOA_MINIMUM => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_MINIMUM,
576            DnsRrKey::PTR_DNAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_PTR_DNAME,
577            DnsRrKey::HINFO_CPU => c_ares_sys::ares_dns_rr_key_t::ARES_RR_HINFO_CPU,
578            DnsRrKey::HINFO_OS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_HINFO_OS,
579            DnsRrKey::MX_PREFERENCE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_MX_PREFERENCE,
580            DnsRrKey::MX_EXCHANGE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_MX_EXCHANGE,
581            DnsRrKey::TXT_DATA => c_ares_sys::ares_dns_rr_key_t::ARES_RR_TXT_DATA,
582            DnsRrKey::SIG_TYPE_COVERED => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_TYPE_COVERED,
583            DnsRrKey::SIG_ALGORITHM => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_ALGORITHM,
584            DnsRrKey::SIG_LABELS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_LABELS,
585            DnsRrKey::SIG_ORIGINAL_TTL => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_ORIGINAL_TTL,
586            DnsRrKey::SIG_EXPIRATION => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_EXPIRATION,
587            DnsRrKey::SIG_INCEPTION => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_INCEPTION,
588            DnsRrKey::SIG_KEY_TAG => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_KEY_TAG,
589            DnsRrKey::SIG_SIGNERS_NAME => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_SIGNERS_NAME,
590            DnsRrKey::SIG_SIGNATURE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_SIGNATURE,
591            DnsRrKey::AAAA_ADDR => c_ares_sys::ares_dns_rr_key_t::ARES_RR_AAAA_ADDR,
592            DnsRrKey::SRV_PRIORITY => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_PRIORITY,
593            DnsRrKey::SRV_WEIGHT => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_WEIGHT,
594            DnsRrKey::SRV_PORT => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_PORT,
595            DnsRrKey::SRV_TARGET => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_TARGET,
596            DnsRrKey::NAPTR_ORDER => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_ORDER,
597            DnsRrKey::NAPTR_PREFERENCE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_PREFERENCE,
598            DnsRrKey::NAPTR_FLAGS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_FLAGS,
599            DnsRrKey::NAPTR_SERVICES => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_SERVICES,
600            DnsRrKey::NAPTR_REGEXP => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_REGEXP,
601            DnsRrKey::NAPTR_REPLACEMENT => c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_REPLACEMENT,
602            DnsRrKey::OPT_UDP_SIZE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_UDP_SIZE,
603            DnsRrKey::OPT_VERSION => c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_VERSION,
604            DnsRrKey::OPT_FLAGS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_FLAGS,
605            DnsRrKey::OPT_OPTIONS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_OPTIONS,
606            DnsRrKey::TLSA_CERT_USAGE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_CERT_USAGE,
607            DnsRrKey::TLSA_SELECTOR => c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_SELECTOR,
608            DnsRrKey::TLSA_MATCH => c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_MATCH,
609            DnsRrKey::TLSA_DATA => c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_DATA,
610            DnsRrKey::SVCB_PRIORITY => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_PRIORITY,
611            DnsRrKey::SVCB_TARGET => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_TARGET,
612            DnsRrKey::SVCB_PARAMS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_PARAMS,
613            DnsRrKey::HTTPS_PRIORITY => c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_PRIORITY,
614            DnsRrKey::HTTPS_TARGET => c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_TARGET,
615            DnsRrKey::HTTPS_PARAMS => c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_PARAMS,
616            DnsRrKey::URI_PRIORITY => c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_PRIORITY,
617            DnsRrKey::URI_WEIGHT => c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_WEIGHT,
618            DnsRrKey::URI_TARGET => c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_TARGET,
619            DnsRrKey::CAA_CRITICAL => c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_CRITICAL,
620            DnsRrKey::CAA_TAG => c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_TAG,
621            DnsRrKey::CAA_VALUE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_VALUE,
622            DnsRrKey::RAW_RR_TYPE => c_ares_sys::ares_dns_rr_key_t::ARES_RR_RAW_RR_TYPE,
623            DnsRrKey::RAW_RR_DATA => c_ares_sys::ares_dns_rr_key_t::ARES_RR_RAW_RR_DATA,
624        }
625    }
626}
627
628impl From<c_ares_sys::ares_dns_rr_key_t> for DnsRrKey {
629    fn from(val: c_ares_sys::ares_dns_rr_key_t) -> Self {
630        match val {
631            c_ares_sys::ares_dns_rr_key_t::ARES_RR_A_ADDR => DnsRrKey::A_ADDR,
632            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NS_NSDNAME => DnsRrKey::NS_NSDNAME,
633            c_ares_sys::ares_dns_rr_key_t::ARES_RR_CNAME_CNAME => DnsRrKey::CNAME_CNAME,
634            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_MNAME => DnsRrKey::SOA_MNAME,
635            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_RNAME => DnsRrKey::SOA_RNAME,
636            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_SERIAL => DnsRrKey::SOA_SERIAL,
637            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_REFRESH => DnsRrKey::SOA_REFRESH,
638            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_RETRY => DnsRrKey::SOA_RETRY,
639            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_EXPIRE => DnsRrKey::SOA_EXPIRE,
640            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SOA_MINIMUM => DnsRrKey::SOA_MINIMUM,
641            c_ares_sys::ares_dns_rr_key_t::ARES_RR_PTR_DNAME => DnsRrKey::PTR_DNAME,
642            c_ares_sys::ares_dns_rr_key_t::ARES_RR_HINFO_CPU => DnsRrKey::HINFO_CPU,
643            c_ares_sys::ares_dns_rr_key_t::ARES_RR_HINFO_OS => DnsRrKey::HINFO_OS,
644            c_ares_sys::ares_dns_rr_key_t::ARES_RR_MX_PREFERENCE => DnsRrKey::MX_PREFERENCE,
645            c_ares_sys::ares_dns_rr_key_t::ARES_RR_MX_EXCHANGE => DnsRrKey::MX_EXCHANGE,
646            c_ares_sys::ares_dns_rr_key_t::ARES_RR_TXT_DATA => DnsRrKey::TXT_DATA,
647            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_TYPE_COVERED => DnsRrKey::SIG_TYPE_COVERED,
648            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_ALGORITHM => DnsRrKey::SIG_ALGORITHM,
649            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_LABELS => DnsRrKey::SIG_LABELS,
650            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_ORIGINAL_TTL => DnsRrKey::SIG_ORIGINAL_TTL,
651            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_EXPIRATION => DnsRrKey::SIG_EXPIRATION,
652            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_INCEPTION => DnsRrKey::SIG_INCEPTION,
653            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_KEY_TAG => DnsRrKey::SIG_KEY_TAG,
654            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_SIGNERS_NAME => DnsRrKey::SIG_SIGNERS_NAME,
655            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SIG_SIGNATURE => DnsRrKey::SIG_SIGNATURE,
656            c_ares_sys::ares_dns_rr_key_t::ARES_RR_AAAA_ADDR => DnsRrKey::AAAA_ADDR,
657            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_PRIORITY => DnsRrKey::SRV_PRIORITY,
658            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_WEIGHT => DnsRrKey::SRV_WEIGHT,
659            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_PORT => DnsRrKey::SRV_PORT,
660            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SRV_TARGET => DnsRrKey::SRV_TARGET,
661            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_ORDER => DnsRrKey::NAPTR_ORDER,
662            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_PREFERENCE => DnsRrKey::NAPTR_PREFERENCE,
663            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_FLAGS => DnsRrKey::NAPTR_FLAGS,
664            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_SERVICES => DnsRrKey::NAPTR_SERVICES,
665            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_REGEXP => DnsRrKey::NAPTR_REGEXP,
666            c_ares_sys::ares_dns_rr_key_t::ARES_RR_NAPTR_REPLACEMENT => DnsRrKey::NAPTR_REPLACEMENT,
667            c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_UDP_SIZE => DnsRrKey::OPT_UDP_SIZE,
668            c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_VERSION => DnsRrKey::OPT_VERSION,
669            c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_FLAGS => DnsRrKey::OPT_FLAGS,
670            c_ares_sys::ares_dns_rr_key_t::ARES_RR_OPT_OPTIONS => DnsRrKey::OPT_OPTIONS,
671            c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_CERT_USAGE => DnsRrKey::TLSA_CERT_USAGE,
672            c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_SELECTOR => DnsRrKey::TLSA_SELECTOR,
673            c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_MATCH => DnsRrKey::TLSA_MATCH,
674            c_ares_sys::ares_dns_rr_key_t::ARES_RR_TLSA_DATA => DnsRrKey::TLSA_DATA,
675            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_PRIORITY => DnsRrKey::SVCB_PRIORITY,
676            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_TARGET => DnsRrKey::SVCB_TARGET,
677            c_ares_sys::ares_dns_rr_key_t::ARES_RR_SVCB_PARAMS => DnsRrKey::SVCB_PARAMS,
678            c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_PRIORITY => DnsRrKey::HTTPS_PRIORITY,
679            c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_TARGET => DnsRrKey::HTTPS_TARGET,
680            c_ares_sys::ares_dns_rr_key_t::ARES_RR_HTTPS_PARAMS => DnsRrKey::HTTPS_PARAMS,
681            c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_PRIORITY => DnsRrKey::URI_PRIORITY,
682            c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_WEIGHT => DnsRrKey::URI_WEIGHT,
683            c_ares_sys::ares_dns_rr_key_t::ARES_RR_URI_TARGET => DnsRrKey::URI_TARGET,
684            c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_CRITICAL => DnsRrKey::CAA_CRITICAL,
685            c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_TAG => DnsRrKey::CAA_TAG,
686            c_ares_sys::ares_dns_rr_key_t::ARES_RR_CAA_VALUE => DnsRrKey::CAA_VALUE,
687            c_ares_sys::ares_dns_rr_key_t::ARES_RR_RAW_RR_TYPE => DnsRrKey::RAW_RR_TYPE,
688            c_ares_sys::ares_dns_rr_key_t::ARES_RR_RAW_RR_DATA => DnsRrKey::RAW_RR_DATA,
689        }
690    }
691}
692
693impl fmt::Display for DnsRrKey {
694    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
695        let ptr = unsafe { c_ares_sys::ares_dns_rr_key_tostr((*self).into()) };
696        f.write_str(unsafe { dns_string_as_str(ptr) })
697    }
698}
699
700/// Data types for DNS resource record fields.
701///
702/// Returned by [`DnsRrKey::datatype()`] to indicate which getter/setter is
703/// appropriate for a given key.
704#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
705pub enum DnsDataType {
706    /// IPv4 address (`struct in_addr`).
707    InAddr,
708    /// IPv6 address (`struct ares_in6_addr`).
709    InAddr6,
710    /// 8-bit unsigned integer.
711    U8,
712    /// 16-bit unsigned integer.
713    U16,
714    /// 32-bit unsigned integer.
715    U32,
716    /// Domain name (null-terminated string).
717    Name,
718    /// Null-terminated string.
719    Str,
720    /// Binary data.
721    Bin,
722    /// Binary data, likely printable.
723    BinP,
724    /// Array of options (16-bit key + binary value).
725    Opt,
726    /// Array of binary data, likely printable.
727    ABinP,
728}
729
730impl From<c_ares_sys::ares_dns_datatype_t> for DnsDataType {
731    fn from(val: c_ares_sys::ares_dns_datatype_t) -> Self {
732        match val {
733            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_INADDR => DnsDataType::InAddr,
734            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_INADDR6 => DnsDataType::InAddr6,
735            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_U8 => DnsDataType::U8,
736            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_U16 => DnsDataType::U16,
737            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_U32 => DnsDataType::U32,
738            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_NAME => DnsDataType::Name,
739            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_STR => DnsDataType::Str,
740            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_BIN => DnsDataType::Bin,
741            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_BINP => DnsDataType::BinP,
742            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_OPT => DnsDataType::Opt,
743            c_ares_sys::ares_dns_datatype_t::ARES_DATATYPE_ABINP => DnsDataType::ABinP,
744        }
745    }
746}
747
748/// Data type for option records for keys like `OPT_OPTIONS` and
749/// `HTTPS_PARAMS`.
750///
751/// Returned by [`DnsRr::opt_datatype()`](super::DnsRr::opt_datatype) to indicate the best match for
752/// interpreting an option record value.
753#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
754pub enum DnsOptDataType {
755    /// No value allowed for this option.
756    None,
757    /// List of strings, each prefixed with a single octet representing the length.
758    StrList,
759    /// List of 8-bit integers, concatenated.
760    U8List,
761    /// 16-bit integer in network byte order.
762    U16,
763    /// List of 16-bit integers in network byte order, concatenated.
764    U16List,
765    /// 32-bit integer in network byte order.
766    U32,
767    /// List of 32-bit integers in network byte order, concatenated.
768    U32List,
769    /// List of IPv4 addresses in network byte order, concatenated.
770    InAddr4List,
771    /// List of IPv6 addresses in network byte order, concatenated.
772    InAddr6List,
773    /// Binary data.
774    Bin,
775    /// DNS domain name format.
776    Name,
777}
778
779impl From<c_ares_sys::ares_dns_opt_datatype_t> for DnsOptDataType {
780    fn from(val: c_ares_sys::ares_dns_opt_datatype_t) -> Self {
781        match val {
782            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_NONE => DnsOptDataType::None,
783            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_STR_LIST => {
784                DnsOptDataType::StrList
785            }
786            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_U8_LIST => {
787                DnsOptDataType::U8List
788            }
789            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_U16 => DnsOptDataType::U16,
790            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_U16_LIST => {
791                DnsOptDataType::U16List
792            }
793            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_U32 => DnsOptDataType::U32,
794            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_U32_LIST => {
795                DnsOptDataType::U32List
796            }
797            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_INADDR4_LIST => {
798                DnsOptDataType::InAddr4List
799            }
800            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_INADDR6_LIST => {
801                DnsOptDataType::InAddr6List
802            }
803            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_BIN => DnsOptDataType::Bin,
804            c_ares_sys::ares_dns_opt_datatype_t::ARES_OPT_DATATYPE_NAME => DnsOptDataType::Name,
805        }
806    }
807}
808
809impl DnsRrKey {
810    /// Returns the data type associated with this resource record key.
811    ///
812    /// This tells the caller which getter/setter method to use (e.g.
813    /// `get_addr` for [`DnsDataType::InAddr`], `get_str` for
814    /// [`DnsDataType::Str`] or [`DnsDataType::Name`]).
815    pub fn datatype(self) -> DnsDataType {
816        let raw = unsafe { c_ares_sys::ares_dns_rr_key_datatype(self.into()) };
817        DnsDataType::from(raw)
818    }
819
820    /// Returns the DNS record type that this key belongs to.
821    ///
822    /// For example, `DnsRrKey::A_ADDR` returns `DnsRecordType::A`.
823    pub fn record_type(self) -> DnsRecordType {
824        let raw = unsafe { c_ares_sys::ares_dns_rr_key_to_rec_type(self.into()) };
825        DnsRecordType::from(raw)
826    }
827}
828
829#[cfg(test)]
830mod tests {
831    use super::*;
832
833    #[test]
834    fn enum_round_trip_record_type() {
835        let variants = [
836            DnsRecordType::A,
837            DnsRecordType::NS,
838            DnsRecordType::CNAME,
839            DnsRecordType::SOA,
840            DnsRecordType::PTR,
841            DnsRecordType::HINFO,
842            DnsRecordType::MX,
843            DnsRecordType::TXT,
844            DnsRecordType::SIG,
845            DnsRecordType::AAAA,
846            DnsRecordType::SRV,
847            DnsRecordType::NAPTR,
848            DnsRecordType::OPT,
849            DnsRecordType::TLSA,
850            DnsRecordType::SVCB,
851            DnsRecordType::HTTPS,
852            DnsRecordType::ANY,
853            DnsRecordType::URI,
854            DnsRecordType::CAA,
855            DnsRecordType::RAW_RR,
856        ];
857        for v in variants {
858            let sys: c_ares_sys::ares_dns_rec_type_t = v.into();
859            let back: DnsRecordType = sys.into();
860            assert_eq!(v, back);
861        }
862    }
863
864    #[test]
865    fn enum_round_trip_dns_class() {
866        let variants = [
867            DnsCls::IN,
868            DnsCls::CHAOS,
869            DnsCls::HESIOD,
870            DnsCls::NONE,
871            DnsCls::ANY,
872        ];
873        for v in variants {
874            let sys: c_ares_sys::ares_dns_class_t = v.into();
875            let back: DnsCls = sys.into();
876            assert_eq!(v, back);
877        }
878    }
879
880    #[test]
881    fn enum_round_trip_section() {
882        let variants = [
883            DnsSection::Answer,
884            DnsSection::Authority,
885            DnsSection::Additional,
886        ];
887        for v in variants {
888            let sys: c_ares_sys::ares_dns_section_t = v.into();
889            let back: DnsSection = sys.into();
890            assert_eq!(v, back);
891        }
892    }
893
894    #[test]
895    fn enum_round_trip_opcode() {
896        let variants = [
897            DnsOpcode::Query,
898            DnsOpcode::IQuery,
899            DnsOpcode::Status,
900            DnsOpcode::Notify,
901            DnsOpcode::Update,
902        ];
903        for v in variants {
904            let sys: c_ares_sys::ares_dns_opcode_t = v.into();
905            let back: DnsOpcode = sys.into();
906            assert_eq!(v, back);
907        }
908    }
909
910    #[test]
911    fn enum_round_trip_rcode() {
912        let variants = [
913            DnsRcode::NoError,
914            DnsRcode::FormErr,
915            DnsRcode::ServFail,
916            DnsRcode::NXDomain,
917            DnsRcode::NotImp,
918            DnsRcode::Refused,
919            DnsRcode::YXDomain,
920            DnsRcode::YXRRSet,
921            DnsRcode::NXRRSet,
922            DnsRcode::NotAuth,
923            DnsRcode::NotZone,
924            DnsRcode::DSOTypeI,
925            DnsRcode::BadSig,
926            DnsRcode::BadKey,
927            DnsRcode::BadTime,
928            DnsRcode::BadMode,
929            DnsRcode::BadName,
930            DnsRcode::BadAlg,
931            DnsRcode::BadTrunc,
932            DnsRcode::BadCookie,
933        ];
934        for v in variants {
935            let sys: c_ares_sys::ares_dns_rcode_t = v.into();
936            let back: DnsRcode = sys.into();
937            assert_eq!(v, back);
938        }
939    }
940
941    #[test]
942    fn enum_round_trip_rr_key() {
943        let variants = [
944            DnsRrKey::A_ADDR,
945            DnsRrKey::NS_NSDNAME,
946            DnsRrKey::CNAME_CNAME,
947            DnsRrKey::SOA_MNAME,
948            DnsRrKey::SOA_RNAME,
949            DnsRrKey::SOA_SERIAL,
950            DnsRrKey::SOA_REFRESH,
951            DnsRrKey::SOA_RETRY,
952            DnsRrKey::SOA_EXPIRE,
953            DnsRrKey::SOA_MINIMUM,
954            DnsRrKey::PTR_DNAME,
955            DnsRrKey::HINFO_CPU,
956            DnsRrKey::HINFO_OS,
957            DnsRrKey::MX_PREFERENCE,
958            DnsRrKey::MX_EXCHANGE,
959            DnsRrKey::TXT_DATA,
960            DnsRrKey::SIG_TYPE_COVERED,
961            DnsRrKey::SIG_ALGORITHM,
962            DnsRrKey::SIG_LABELS,
963            DnsRrKey::SIG_ORIGINAL_TTL,
964            DnsRrKey::SIG_EXPIRATION,
965            DnsRrKey::SIG_INCEPTION,
966            DnsRrKey::SIG_KEY_TAG,
967            DnsRrKey::SIG_SIGNERS_NAME,
968            DnsRrKey::SIG_SIGNATURE,
969            DnsRrKey::AAAA_ADDR,
970            DnsRrKey::SRV_PRIORITY,
971            DnsRrKey::SRV_WEIGHT,
972            DnsRrKey::SRV_PORT,
973            DnsRrKey::SRV_TARGET,
974            DnsRrKey::NAPTR_ORDER,
975            DnsRrKey::NAPTR_PREFERENCE,
976            DnsRrKey::NAPTR_FLAGS,
977            DnsRrKey::NAPTR_SERVICES,
978            DnsRrKey::NAPTR_REGEXP,
979            DnsRrKey::NAPTR_REPLACEMENT,
980            DnsRrKey::OPT_UDP_SIZE,
981            DnsRrKey::OPT_VERSION,
982            DnsRrKey::OPT_FLAGS,
983            DnsRrKey::OPT_OPTIONS,
984            DnsRrKey::TLSA_CERT_USAGE,
985            DnsRrKey::TLSA_SELECTOR,
986            DnsRrKey::TLSA_MATCH,
987            DnsRrKey::TLSA_DATA,
988            DnsRrKey::SVCB_PRIORITY,
989            DnsRrKey::SVCB_TARGET,
990            DnsRrKey::SVCB_PARAMS,
991            DnsRrKey::HTTPS_PRIORITY,
992            DnsRrKey::HTTPS_TARGET,
993            DnsRrKey::HTTPS_PARAMS,
994            DnsRrKey::URI_PRIORITY,
995            DnsRrKey::URI_WEIGHT,
996            DnsRrKey::URI_TARGET,
997            DnsRrKey::CAA_CRITICAL,
998            DnsRrKey::CAA_TAG,
999            DnsRrKey::CAA_VALUE,
1000            DnsRrKey::RAW_RR_TYPE,
1001            DnsRrKey::RAW_RR_DATA,
1002        ];
1003        for v in variants {
1004            let sys: c_ares_sys::ares_dns_rr_key_t = v.into();
1005            let back: DnsRrKey = sys.into();
1006            assert_eq!(v, back);
1007        }
1008    }
1009
1010    #[test]
1011    fn dns_flags_bitflags() {
1012        let flags = DnsFlags::QR | DnsFlags::RD;
1013        assert!(flags.contains(DnsFlags::QR));
1014        assert!(flags.contains(DnsFlags::RD));
1015        assert!(!flags.contains(DnsFlags::AA));
1016    }
1017
1018    #[test]
1019    fn dns_flags_all_bits() {
1020        let all = DnsFlags::QR
1021            | DnsFlags::AA
1022            | DnsFlags::TC
1023            | DnsFlags::RD
1024            | DnsFlags::RA
1025            | DnsFlags::AD
1026            | DnsFlags::CD;
1027        assert!(all.contains(DnsFlags::QR));
1028        assert!(all.contains(DnsFlags::AA));
1029        assert!(all.contains(DnsFlags::TC));
1030        assert!(all.contains(DnsFlags::RD));
1031        assert!(all.contains(DnsFlags::RA));
1032        assert!(all.contains(DnsFlags::AD));
1033        assert!(all.contains(DnsFlags::CD));
1034    }
1035
1036    #[test]
1037    fn display_record_type() {
1038        assert_eq!(DnsRecordType::A.to_string(), "A");
1039        assert_eq!(DnsRecordType::AAAA.to_string(), "AAAA");
1040        assert_eq!(DnsRecordType::MX.to_string(), "MX");
1041        assert_eq!(DnsRecordType::CNAME.to_string(), "CNAME");
1042        assert_eq!(DnsRecordType::SRV.to_string(), "SRV");
1043    }
1044
1045    #[test]
1046    fn fromstr_record_type() {
1047        assert_eq!("A".parse::<DnsRecordType>().unwrap(), DnsRecordType::A);
1048        assert_eq!(
1049            "AAAA".parse::<DnsRecordType>().unwrap(),
1050            DnsRecordType::AAAA
1051        );
1052        assert_eq!("MX".parse::<DnsRecordType>().unwrap(), DnsRecordType::MX);
1053        assert!("NOTARECORD".parse::<DnsRecordType>().is_err());
1054    }
1055
1056    #[test]
1057    fn display_dns_class() {
1058        assert_eq!(DnsCls::IN.to_string(), "IN");
1059        assert_eq!(DnsCls::CHAOS.to_string(), "CH");
1060        assert_eq!(DnsCls::ANY.to_string(), "ANY");
1061    }
1062
1063    #[test]
1064    fn fromstr_dns_class() {
1065        assert_eq!("IN".parse::<DnsCls>().unwrap(), DnsCls::IN);
1066        assert_eq!("ANY".parse::<DnsCls>().unwrap(), DnsCls::ANY);
1067        assert!("NOTACLASS".parse::<DnsCls>().is_err());
1068    }
1069
1070    #[test]
1071    fn display_section() {
1072        assert_eq!(DnsSection::Answer.to_string(), "ANSWER");
1073        assert_eq!(DnsSection::Authority.to_string(), "AUTHORITY");
1074        assert_eq!(DnsSection::Additional.to_string(), "ADDITIONAL");
1075    }
1076
1077    #[test]
1078    fn display_opcode() {
1079        assert_eq!(DnsOpcode::Query.to_string(), "QUERY");
1080    }
1081
1082    #[test]
1083    fn display_rcode() {
1084        assert_eq!(DnsRcode::NoError.to_string(), "NOERROR");
1085        assert_eq!(DnsRcode::NXDomain.to_string(), "NXDOMAIN");
1086        assert_eq!(DnsRcode::ServFail.to_string(), "SERVFAIL");
1087    }
1088
1089    #[test]
1090    fn display_rr_key() {
1091        assert_eq!(DnsRrKey::A_ADDR.to_string(), "ADDR");
1092        assert_eq!(DnsRrKey::MX_PREFERENCE.to_string(), "PREFERENCE");
1093    }
1094
1095    #[test]
1096    fn rr_key_datatype() {
1097        assert_eq!(DnsRrKey::A_ADDR.datatype(), DnsDataType::InAddr);
1098        assert_eq!(DnsRrKey::AAAA_ADDR.datatype(), DnsDataType::InAddr6);
1099        assert_eq!(DnsRrKey::MX_PREFERENCE.datatype(), DnsDataType::U16);
1100        assert_eq!(DnsRrKey::MX_EXCHANGE.datatype(), DnsDataType::Name);
1101        assert_eq!(DnsRrKey::SOA_SERIAL.datatype(), DnsDataType::U32);
1102        assert_eq!(DnsRrKey::TXT_DATA.datatype(), DnsDataType::ABinP);
1103        assert_eq!(DnsRrKey::OPT_OPTIONS.datatype(), DnsDataType::Opt);
1104    }
1105
1106    #[test]
1107    fn rr_key_record_type() {
1108        assert_eq!(DnsRrKey::A_ADDR.record_type(), DnsRecordType::A);
1109        assert_eq!(DnsRrKey::AAAA_ADDR.record_type(), DnsRecordType::AAAA);
1110        assert_eq!(DnsRrKey::MX_PREFERENCE.record_type(), DnsRecordType::MX);
1111        assert_eq!(DnsRrKey::MX_EXCHANGE.record_type(), DnsRecordType::MX);
1112        assert_eq!(DnsRrKey::SOA_MNAME.record_type(), DnsRecordType::SOA);
1113        assert_eq!(DnsRrKey::CAA_TAG.record_type(), DnsRecordType::CAA);
1114    }
1115}