trust_dns_server/store/recursor/
authority.rs1use std::{io, path::Path, time::Instant};
9
10use tracing::{debug, info};
11
12use crate::{
13 authority::{
14 Authority, LookupError, LookupObject, LookupOptions, MessageRequest, UpdateResult, ZoneType,
15 },
16 proto::{
17 op::{Query, ResponseCode},
18 rr::{LowerName, Name, Record, RecordType},
19 },
20 recursor::Recursor,
21 resolver::{
22 config::{NameServerConfig, NameServerConfigGroup, Protocol},
23 lookup::Lookup,
24 },
25 server::RequestInfo,
26 store::recursor::RecursiveConfig,
27};
28
29pub struct RecursiveAuthority {
33 origin: LowerName,
34 recursor: Recursor,
35}
36
37impl RecursiveAuthority {
38 pub async fn try_from_config(
40 origin: Name,
41 _zone_type: ZoneType,
42 config: &RecursiveConfig,
43 root_dir: Option<&Path>,
44 ) -> Result<Self, String> {
45 info!("loading recursor config: {}", origin);
46
47 let root_addrs = config
49 .read_roots(root_dir)
50 .map_err(|e| format!("failed to read roots {}: {}", config.roots.display(), e))?;
51
52 let mut roots = NameServerConfigGroup::new();
54 for socket_addr in root_addrs {
55 roots.push(NameServerConfig {
56 socket_addr,
57 protocol: Protocol::Tcp,
58 tls_dns_name: None,
59 trust_negative_responses: false,
60 #[cfg(feature = "dns-over-rustls")]
61 tls_config: None,
62 bind_addr: None, });
64
65 roots.push(NameServerConfig {
66 socket_addr,
67 protocol: Protocol::Udp,
68 tls_dns_name: None,
69 trust_negative_responses: false,
70 #[cfg(feature = "dns-over-rustls")]
71 tls_config: None,
72 bind_addr: None,
73 });
74 }
75
76 let recursor =
77 Recursor::new(roots).map_err(|e| format!("failed to initialize recursor: {e}"))?;
78
79 Ok(Self {
80 origin: origin.into(),
81 recursor,
82 })
83 }
84}
85
86#[async_trait::async_trait]
87impl Authority for RecursiveAuthority {
88 type Lookup = RecursiveLookup;
89
90 fn zone_type(&self) -> ZoneType {
92 ZoneType::Hint
93 }
94
95 fn is_axfr_allowed(&self) -> bool {
97 false
98 }
99
100 async fn update(&self, _update: &MessageRequest) -> UpdateResult<bool> {
101 Err(ResponseCode::NotImp)
102 }
103
104 fn origin(&self) -> &LowerName {
110 &self.origin
111 }
112
113 async fn lookup(
115 &self,
116 name: &LowerName,
117 rtype: RecordType,
118 _lookup_options: LookupOptions,
119 ) -> Result<Self::Lookup, LookupError> {
120 debug!("recursive lookup: {} {}", name, rtype);
121
122 let query = Query::query(name.into(), rtype);
123 let now = Instant::now();
124
125 self.recursor
126 .resolve(query, now)
127 .await
128 .map(RecursiveLookup)
129 .map_err(Into::into)
130 }
131
132 async fn search(
133 &self,
134 request_info: RequestInfo<'_>,
135 lookup_options: LookupOptions,
136 ) -> Result<Self::Lookup, LookupError> {
137 self.lookup(
138 request_info.query.name(),
139 request_info.query.query_type(),
140 lookup_options,
141 )
142 .await
143 }
144
145 async fn get_nsec_records(
146 &self,
147 _name: &LowerName,
148 _lookup_options: LookupOptions,
149 ) -> Result<Self::Lookup, LookupError> {
150 Err(LookupError::from(io::Error::new(
151 io::ErrorKind::Other,
152 "Getting NSEC records is unimplemented for the recursor",
153 )))
154 }
155}
156
157pub struct RecursiveLookup(Lookup);
158
159impl LookupObject for RecursiveLookup {
160 fn is_empty(&self) -> bool {
161 self.0.is_empty()
162 }
163
164 fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
165 Box::new(self.0.record_iter())
166 }
167
168 fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
169 None
170 }
171}