hickory_server/authority/
mod.rs1use std::{io, sync::Arc};
11
12use enum_as_inner::EnumAsInner;
13use thiserror::Error;
14
15use crate::proto::op::ResponseCode;
16use crate::proto::rr::{Record, rdata::SOA};
17use crate::proto::{ProtoError, ProtoErrorKind};
18#[cfg(feature = "recursor")]
19use crate::recursor::ErrorKind;
20#[cfg(feature = "resolver")]
21use crate::resolver::ResolveError;
22
23mod auth_lookup;
24#[allow(clippy::module_inception)]
25mod authority;
26pub(crate) mod authority_object;
27mod catalog;
28pub(crate) mod message_request;
29mod message_response;
30
31pub use self::auth_lookup::{
32 AnyRecords, AuthLookup, AuthLookupIter, LookupRecords, LookupRecordsIter,
33};
34pub use self::authority::{Authority, LookupControlFlow, LookupOptions};
35#[cfg(feature = "__dnssec")]
36pub use self::authority::{DnssecAuthority, Nsec3QueryInfo};
37pub use self::authority_object::{AuthorityObject, DnssecSummary, EmptyLookup, LookupObject};
38pub use self::catalog::Catalog;
39pub use self::message_request::{MessageRequest, Queries, UpdateRequest};
40pub use self::message_response::{MessageResponse, MessageResponseBuilder};
41
42pub type UpdateResult<T> = Result<T, ResponseCode>;
44
45#[allow(clippy::large_enum_variant)]
47#[derive(Debug, EnumAsInner, Error)]
49#[non_exhaustive]
50pub enum LookupError {
51 #[error("The name exists, but not for the record requested")]
53 NameExists,
54 #[error("Error performing lookup: {0}")]
56 ResponseCode(ResponseCode),
57 #[error("Proto error: {0}")]
59 ProtoError(#[from] ProtoError),
60 #[cfg(feature = "resolver")]
62 #[error("Forward resolution error: {0}")]
63 ResolveError(#[from] ResolveError),
64 #[cfg(feature = "recursor")]
66 #[error("Recursive resolution error: {0}")]
67 RecursiveError(#[from] hickory_recursor::Error),
68 #[error("io error: {0}")]
70 Io(io::Error),
71}
72
73impl LookupError {
74 pub fn for_name_exists() -> Self {
76 Self::NameExists
77 }
78
79 pub fn is_nx_domain(&self) -> bool {
81 match self {
82 Self::ResponseCode(ResponseCode::NXDomain) => true,
83 #[cfg(feature = "resolver")]
84 Self::ResolveError(e) if e.is_nx_domain() => true,
85 #[cfg(feature = "recursor")]
86 Self::RecursiveError(e) if e.is_nx_domain() => true,
87 _ => false,
88 }
89 }
90
91 pub fn is_no_records_found(&self) -> bool {
93 match self {
94 #[cfg(feature = "resolver")]
95 Self::ResolveError(e) if e.is_no_records_found() => true,
96 #[cfg(feature = "recursor")]
97 Self::RecursiveError(e) if e.is_no_records_found() => true,
98 _ => false,
99 }
100 }
101
102 pub fn into_soa(self) -> Option<Box<Record<SOA>>> {
104 match self {
105 #[cfg(feature = "resolver")]
106 Self::ResolveError(e) => e.into_soa(),
107 #[cfg(feature = "recursor")]
108 Self::RecursiveError(e) => e.into_soa(),
109 _ => None,
110 }
111 }
112
113 pub fn authorities(&self) -> Option<Arc<[Record]>> {
115 match self {
116 Self::ProtoError(e) => match e.kind() {
117 ProtoErrorKind::NoRecordsFound { authorities, .. } => authorities.clone(),
118 _ => None,
119 },
120 #[cfg(feature = "recursor")]
121 Self::RecursiveError(e) => match e.kind() {
122 ErrorKind::Forward(fwd) => fwd.authorities.clone(),
123 ErrorKind::Proto(proto) => match proto.kind() {
124 ProtoErrorKind::NoRecordsFound { authorities, .. } => authorities.clone(),
125 _ => None,
126 },
127 _ => None,
128 },
129 _ => None,
130 }
131 }
132
133 pub fn is_refused(&self) -> bool {
135 matches!(*self, Self::ResponseCode(ResponseCode::Refused))
136 }
137}
138
139impl From<ResponseCode> for LookupError {
140 fn from(code: ResponseCode) -> Self {
141 debug_assert!(code != ResponseCode::NoError);
143 Self::ResponseCode(code)
144 }
145}
146
147impl From<io::Error> for LookupError {
148 fn from(e: io::Error) -> Self {
149 Self::Io(e)
150 }
151}
152
153impl From<LookupError> for io::Error {
154 fn from(e: LookupError) -> Self {
155 Self::new(io::ErrorKind::Other, Box::new(e))
156 }
157}
158
159#[allow(deprecated)]
160mod zone_type {
161 use serde::{Deserialize, Serialize};
162
163 #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
165 pub enum ZoneType {
166 Primary,
168 #[deprecated = "please read about Juneteenth"]
170 Master,
171 Secondary,
173 #[deprecated = "please read about Juneteenth"]
175 Slave,
176 External,
178 }
179
180 impl ZoneType {
181 #[allow(deprecated)]
183 pub fn is_authoritative(self) -> bool {
184 matches!(
185 self,
186 Self::Primary | Self::Secondary | Self::Master | Self::Slave
187 )
188 }
189 }
190}
191
192pub use zone_type::ZoneType;