trust_dns_resolver/name_server/
name_server.rs1use std::cmp::Ordering;
9use std::fmt::{self, Debug, Formatter};
10use std::pin::Pin;
11use std::sync::Arc;
12use std::time::Instant;
13
14use futures_util::lock::Mutex;
15use futures_util::stream::{once, Stream};
16
17#[cfg(feature = "mdns")]
18use proto::multicast::MDNS_IPV4;
19use proto::xfer::{DnsHandle, DnsRequest, DnsResponse, FirstAnswer};
20use tracing::debug;
21
22use crate::config::{NameServerConfig, ResolverOpts};
23use crate::error::ResolveError;
24use crate::name_server::connection_provider::{ConnectionProvider, GenericConnector};
25use crate::name_server::{NameServerState, NameServerStats};
26#[cfg(feature = "mdns")]
27use proto::multicast::{MdnsClientConnect, MdnsClientStream, MdnsQueryType};
28
29#[derive(Clone)]
31pub struct NameServer<P: ConnectionProvider> {
32 config: NameServerConfig,
33 options: ResolverOpts,
34 client: Arc<Mutex<Option<P::Conn>>>,
35 state: Arc<NameServerState>,
36 stats: Arc<NameServerStats>,
37 connection_provider: P,
38}
39
40pub type GenericNameServer<R> = NameServer<GenericConnector<R>>;
42
43impl<P> Debug for NameServer<P>
44where
45 P: ConnectionProvider + Send,
46{
47 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
48 write!(f, "config: {:?}, options: {:?}", self.config, self.options)
49 }
50}
51
52impl<P> NameServer<P>
53where
54 P: ConnectionProvider + Send,
55{
56 pub fn new(config: NameServerConfig, options: ResolverOpts, connection_provider: P) -> Self {
58 Self {
59 config,
60 options,
61 client: Arc::new(Mutex::new(None)),
62 state: Arc::new(NameServerState::init(None)),
63 stats: Arc::new(NameServerStats::default()),
64 connection_provider,
65 }
66 }
67
68 #[doc(hidden)]
69 pub fn from_conn(
70 config: NameServerConfig,
71 options: ResolverOpts,
72 client: P::Conn,
73 connection_provider: P,
74 ) -> Self {
75 Self {
76 config,
77 options,
78 client: Arc::new(Mutex::new(Some(client))),
79 state: Arc::new(NameServerState::init(None)),
80 stats: Arc::new(NameServerStats::default()),
81 connection_provider,
82 }
83 }
84
85 #[cfg(test)]
86 #[allow(dead_code)]
87 pub(crate) fn is_connected(&self) -> bool {
88 !self.state.is_failed()
89 && if let Some(client) = self.client.try_lock() {
90 client.is_some()
91 } else {
92 true
94 }
95 }
96
97 async fn connected_mut_client(&mut self) -> Result<P::Conn, ResolveError> {
101 let mut client = self.client.lock().await;
102
103 if self.state.is_failed() || client.is_none() {
105 debug!("reconnecting: {:?}", self.config);
106
107 self.state.reinit(None);
109
110 let new_client = Box::pin(
111 self.connection_provider
112 .new_connection(&self.config, &self.options),
113 )
114 .await?;
115
116 *client = Some(new_client);
118 } else {
119 debug!("existing connection: {:?}", self.config);
120 }
121
122 Ok((*client)
123 .clone()
124 .expect("bad state, client should be connected"))
125 }
126
127 async fn inner_send<R: Into<DnsRequest> + Unpin + Send + 'static>(
128 mut self,
129 request: R,
130 ) -> Result<DnsResponse, ResolveError> {
131 let mut client = self.connected_mut_client().await?;
132 let now = Instant::now();
133 let response = client.send(request).first_answer().await;
134 let rtt = now.elapsed();
135
136 match response {
137 Ok(response) => {
138 self.stats.record_rtt(rtt);
140
141 let response =
143 ResolveError::from_response(response, self.config.trust_negative_responses)?;
144
145 let remote_edns = response.extensions().clone();
147
148 self.state.establish(remote_edns);
150
151 Ok(response)
152 }
153 Err(error) => {
154 debug!("name_server connection failure: {}", error);
155
156 self.state.fail(Instant::now());
158
159 self.stats.record_connection_failure();
161
162 Err(error)
164 }
165 }
166 }
167
168 pub fn trust_nx_responses(&self) -> bool {
170 self.config.trust_negative_responses
171 }
172}
173
174impl<P> DnsHandle for NameServer<P>
175where
176 P: ConnectionProvider + Clone,
177{
178 type Response = Pin<Box<dyn Stream<Item = Result<DnsResponse, ResolveError>> + Send>>;
179 type Error = ResolveError;
180
181 fn is_verifying_dnssec(&self) -> bool {
182 self.options.validate
183 }
184
185 fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
187 let this = self.clone();
188 Box::pin(once(this.inner_send(request)))
190 }
191}
192
193impl<P> Ord for NameServer<P>
194where
195 P: ConnectionProvider + Send,
196{
197 fn cmp(&self, other: &Self) -> Ordering {
199 if self == other {
201 return Ordering::Equal;
202 }
203
204 self.stats.cmp(&other.stats)
205 }
206}
207
208impl<P> PartialOrd for NameServer<P>
209where
210 P: ConnectionProvider + Send,
211{
212 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
213 Some(self.cmp(other))
214 }
215}
216
217impl<P> PartialEq for NameServer<P>
218where
219 P: ConnectionProvider + Send,
220{
221 fn eq(&self, other: &Self) -> bool {
223 self.config == other.config
224 }
225}
226
227impl<P> Eq for NameServer<P> where P: ConnectionProvider + Send {}
228
229#[cfg(feature = "mdns")]
231pub(crate) fn mdns_nameserver<P>(
232 options: ResolverOpts,
233 conn_provider: P,
234 trust_negative_responses: bool,
235) -> GenericNameServer<P>
236where
237 P: ConnectionProvider,
238{
239 let config = NameServerConfig {
240 socket_addr: *MDNS_IPV4,
241 protocol: Protocol::Mdns,
242 tls_dns_name: None,
243 trust_negative_responses,
244 #[cfg(feature = "dns-over-rustls")]
245 tls_config: None,
246 bind_addr: None,
247 };
248 GenericNameServer::new_with_provider(config, options, conn_provider)
249}
250
251#[cfg(test)]
252#[cfg(feature = "tokio-runtime")]
253mod tests {
254 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
255 use std::time::Duration;
256
257 use futures_util::{future, FutureExt};
258 use tokio::runtime::Runtime;
259
260 use proto::op::{Query, ResponseCode};
261 use proto::rr::{Name, RecordType};
262 use proto::xfer::{DnsHandle, DnsRequestOptions, FirstAnswer};
263
264 use super::*;
265 use crate::config::Protocol;
266 use crate::name_server::TokioConnectionProvider;
267
268 #[test]
269 fn test_name_server() {
270 let config = NameServerConfig {
273 socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), 53),
274 protocol: Protocol::Udp,
275 tls_dns_name: None,
276 trust_negative_responses: false,
277 #[cfg(feature = "dns-over-rustls")]
278 tls_config: None,
279 bind_addr: None,
280 };
281 let io_loop = Runtime::new().unwrap();
282 let name_server = future::lazy(|_| {
283 GenericNameServer::new(
284 config,
285 ResolverOpts::default(),
286 TokioConnectionProvider::default(),
287 )
288 });
289
290 let name = Name::parse("www.example.com.", None).unwrap();
291 let response = io_loop
292 .block_on(name_server.then(|mut name_server| {
293 name_server
294 .lookup(
295 Query::query(name.clone(), RecordType::A),
296 DnsRequestOptions::default(),
297 )
298 .first_answer()
299 }))
300 .expect("query failed");
301 assert_eq!(response.response_code(), ResponseCode::NoError);
302 }
303
304 #[test]
305 fn test_failed_name_server() {
306 let options = ResolverOpts {
307 timeout: Duration::from_millis(1), ..ResolverOpts::default()
309 };
310 let config = NameServerConfig {
311 socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 252)), 252),
312 protocol: Protocol::Udp,
313 tls_dns_name: None,
314 trust_negative_responses: false,
315 #[cfg(feature = "dns-over-rustls")]
316 tls_config: None,
317 bind_addr: None,
318 };
319 let io_loop = Runtime::new().unwrap();
320 let name_server = future::lazy(|_| {
321 GenericNameServer::new(config, options, TokioConnectionProvider::default())
322 });
323
324 let name = Name::parse("www.example.com.", None).unwrap();
325 assert!(io_loop
326 .block_on(name_server.then(|mut name_server| {
327 name_server
328 .lookup(
329 Query::query(name.clone(), RecordType::A),
330 DnsRequestOptions::default(),
331 )
332 .first_answer()
333 }))
334 .is_err());
335 }
336}