hickory_resolver/lib.rs
1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! The Resolver is responsible for performing recursive queries to lookup domain names.
9//!
10//! This is a 100% in process DNS resolver. It *does not* use the Host OS' resolver. If what is
11//! desired is to use the Host OS' resolver, generally in the system's libc, then the
12//! `std::net::ToSocketAddrs` variant over `&str` should be used.
13//!
14//! Unlike the `hickory-client`, this tries to provide a simpler interface to perform DNS
15//! queries. For update options, i.e. Dynamic DNS, the `hickory-client` crate must be used
16//! instead. The Resolver library is capable of searching multiple domains (this can be disabled by
17//! using an FQDN during lookup), dual-stack IPv4/IPv6 lookups, performing chained CNAME lookups,
18//! and features connection metric tracking for attempting to pick the best upstream DNS resolver.
19//!
20//! This as best as possible attempts to abide by the DNS RFCs, please file issues at
21//! <https://github.com/hickory-dns/hickory-dns>.
22//!
23//! # Usage
24//!
25//! ## Declare dependency
26//!
27//! ```toml
28//! [dependency]
29//! hickory-resolver = "*"
30//! ```
31//!
32//! ## Using the host system config
33//!
34//! On Unix systems, the `/etc/resolv.conf` can be used for configuration. Not all options
35//! specified in the host systems `resolv.conf` are applicable or compatible with this software. In
36//! addition there may be additional options supported which the host system does not. Example:
37//!
38//! ```rust,no_run
39//! # #[tokio::main]
40//! # async fn main() {
41//! # #[cfg(feature = "tokio")]
42//! # {
43//! # use std::net::*;
44//! # use hickory_resolver::Resolver;
45//! // Use the host OS'es `/etc/resolv.conf`
46//! # #[cfg(unix)]
47//! let resolver = Resolver::builder_tokio().unwrap().build();
48//! # #[cfg(unix)]
49//! let response = resolver.lookup_ip("www.example.com.").await.unwrap();
50//! # }
51//! # }
52//! ```
53//!
54//! ## Using the Tokio/Async Resolver
55//!
56//! ```rust
57//! # fn main() {
58//! # #[cfg(feature = "tokio")]
59//! # {
60//! use std::net::*;
61//! use tokio::runtime::Runtime;
62//! use hickory_resolver::Resolver;
63//! use hickory_resolver::name_server::TokioConnectionProvider;
64//! use hickory_resolver::config::*;
65//!
66//! // We need a Tokio Runtime to run the resolver
67//! // this is responsible for running all Future tasks and registering interest in IO channels
68//! let mut io_loop = Runtime::new().unwrap();
69//!
70//! // Construct a new Resolver with default configuration options
71//! let resolver = Resolver::builder_with_config(
72//! ResolverConfig::default(),
73//! TokioConnectionProvider::default()
74//! ).build();
75//!
76//! // Lookup the IP addresses associated with a name.
77//! // This returns a future that will lookup the IP addresses, it must be run in the Core to
78//! // to get the actual result.
79//! let lookup_future = resolver.lookup_ip("www.example.com.");
80//!
81//! // Run the lookup until it resolves or errors
82//! let mut response = io_loop.block_on(lookup_future).unwrap();
83//!
84//! // There can be many addresses associated with the name,
85//! // this can return IPv4 and/or IPv6 addresses
86//! let _address = response.iter().next().expect("no addresses returned!");
87//! # }
88//! # }
89//! ```
90//!
91//! Generally after a lookup in an asynchronous context, there would probably be a connection made
92//! to a server, for example:
93//!
94//! ```rust,no_run
95//! # fn main() {
96//! # #[cfg(feature = "tokio")]
97//! # {
98//! # use std::net::*;
99//! # use tokio::runtime::Runtime;
100//! # use hickory_resolver::Resolver;
101//! # use hickory_resolver::name_server::TokioConnectionProvider;
102//! # use hickory_resolver::config::*;
103//! # use futures_util::TryFutureExt;
104//! #
105//! # let mut io_loop = Runtime::new().unwrap();
106//! #
107//! # let resolver = Resolver::builder_with_config(
108//! # ResolverConfig::default(),
109//! # TokioConnectionProvider::default()
110//! # ).build();
111//! #
112//! let ips = io_loop.block_on(resolver.lookup_ip("www.example.com.")).unwrap();
113//!
114//! let result = io_loop.block_on(async {
115//! let ip = ips.iter().next().unwrap();
116//! TcpStream::connect((ip, 443))
117//! })
118//! .and_then(|conn| Ok(conn) /* do something with the connection... */)
119//! .unwrap();
120//! # }
121//! # }
122//! ```
123//!
124//! It's beyond the scope of these examples to show how to deal with connection failures and
125//! looping etc. But if you wanted to say try a different address from the result set after a
126//! connection failure, it will be necessary to create a type that implements the `Future` trait.
127//! Inside the `Future::poll` method would be the place to implement a loop over the different IP
128//! addresses.
129//!
130//! ## Optional protocol support
131//!
132//! The following DNS protocols are optionally supported:
133//!
134//! - Enable `tls` for DNS over TLS (DoT)
135//! - Enable `https-rustls` for DNS over HTTP/2 (DoH)
136//! - Enable `quic` for DNS over QUIC (DoQ)
137//! - Enable `h3` for DNS over HTTP/3 (DoH3)
138//!
139//! ### Example
140//!
141//! Enable the TLS library through the dependency on `hickory-resolver`:
142//!
143//! ```toml
144//! hickory-resolver = { version = "*", features = ["tls"] }
145//! ```
146//!
147//! A default TLS configuration is available for Cloudflare's `1.1.1.1` DNS service (Quad9 as
148//! well):
149//!
150//! ```rust,no_run
151//! # fn main() {
152//! # #[cfg(feature = "tokio")]
153//! # {
154//! use hickory_resolver::Resolver;
155//! use hickory_resolver::name_server::TokioConnectionProvider;
156//! use hickory_resolver::config::*;
157//!
158//! // Construct a new Resolver with default configuration options
159//! # #[cfg(feature = "__tls")]
160//! let mut resolver = Resolver::builder_with_config(
161//! ResolverConfig::cloudflare_tls(),
162//! TokioConnectionProvider::default(),
163//! ).build();
164//!
165//! // see example above...
166//! # }
167//! # }
168//! ```
169//!
170//! ## mDNS (multicast DNS)
171//!
172//! Multicast DNS is an experimental feature in Hickory DNS at the moment. Its support on different
173//! platforms is not yet ideal. Initial support is only for IPv4 mDNS, as there are some
174//! complexities to figure out with IPv6. Once enabled, an mDNS `NameServer` will automatically be
175//! added to the `Resolver` and used for any lookups performed in the `.local.` zone.
176
177// LIBRARY WARNINGS
178#![warn(
179 clippy::default_trait_access,
180 clippy::dbg_macro,
181 clippy::print_stdout,
182 clippy::unimplemented,
183 clippy::use_self,
184 missing_copy_implementations,
185 missing_docs,
186 non_snake_case,
187 non_upper_case_globals,
188 rust_2018_idioms,
189 unreachable_pub
190)]
191#![recursion_limit = "128"]
192#![allow(clippy::needless_doctest_main, clippy::single_component_path_imports)]
193#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
194
195pub use hickory_proto as proto;
196// reexports from proto
197pub use proto::rr::{IntoName, Name};
198
199pub mod caching_client;
200pub mod config;
201pub mod dns_lru;
202mod error;
203pub use error::{ResolveError, ResolveErrorKind};
204#[cfg(feature = "__https")]
205mod h2;
206#[cfg(feature = "__h3")]
207mod h3;
208mod hosts;
209pub use hosts::Hosts;
210pub mod lookup;
211pub mod lookup_ip;
212// TODO: consider #[doc(hidden)]
213pub mod name_server;
214#[cfg(feature = "tokio")]
215use name_server::TokioConnectionProvider;
216#[cfg(feature = "__quic")]
217mod quic;
218mod resolver;
219pub use resolver::LookupFuture;
220#[cfg(feature = "tokio")]
221pub use resolver::TokioResolver;
222pub use resolver::{Resolver, ResolverBuilder};
223pub mod system_conf;
224#[cfg(test)]
225mod tests;
226#[cfg(feature = "__tls")]
227mod tls;
228
229#[doc(hidden)]
230#[deprecated(since = "0.25.0", note = "use `Resolver` instead")]
231pub type AsyncResolver<P> = Resolver<P>;
232
233#[doc(hidden)]
234#[deprecated(since = "0.25.0", note = "use `TokioResolver` instead")]
235#[cfg(feature = "tokio")]
236pub type TokioAsyncResolver = Resolver<TokioConnectionProvider>;
237
238/// returns a version as specified in Cargo.toml
239pub fn version() -> &'static str {
240 env!("CARGO_PKG_VERSION")
241}