1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
//! [rsdns] is a library implementing a [DNS Stub Resolver][^rfc1034]. //! //! DNS is a large, distributed and hierarchical system comprised of many types of servers. //! The data is held in *Authoritative Servers*, which are responsible for specific domains only. //! The client DNS servers are called *resolvers*. Resolving a DNS query may require a *resolver* //! to communicate with several *authoritative servers*. //! This process is called *recursion* and resolvers implementing it are usually called *recursors*. //! //! *rsdns* implements a *Stub Resolver*, which is the simplest resolver in DNS. //! It delegates queries to another DNS server, usually (but not necessarily) a *recursor*. //! //! *rsnds* provides an API to directly communicate with DNS servers using its own implementation //! of the DNS protocol. It strives to be minimal and fast. //! //! # Notable Features //! //! * Minimal API //! * Three independent asynchronous resolvers for different async runtimes: //! [`tokio`], [`async-std`] and [`smol`] //! * An independent blocking resolver implemented on top of [`std::net`] //! * Zero memory allocations when parsing records with no variable size fields //! (e.g. [`A`], [`AAAA`]) //! * Sockets can be bound to network interfaces by name (requires `SO_BINDTODEVICE` support //! from the underlying OS) //! * Minimal set of dependencies //! //! [^rfc1034]: Initial definition of stub resolvers is in [RFC 1034]. //! //! [rsdns]: crate //! [RFC 1034]: https://www.rfc-editor.org/rfc/rfc1034.html#section-5.3.1 //! [DNS Stub Resolver]: https://en.wikipedia.org/wiki/Domain_Name_System#DNS_resolvers //! [`tokio`]: https://docs.rs/tokio //! [`async-std`]: https://docs.rs/async-std //! [`smol`]: https://docs.rs/smol //! [`std::net`]: https://doc.rust-lang.org/std/net //! [`A`]: crate::records::data::A //! [`AAAA`]: crate::records::data::Aaaa //! # Library Structure //! //! *rsdns* is built from two major parts: *message parsing* and *resolvers*. //! //! The *message parsing* part is the core of *rsdns*. It is generic and is suitable for any type //! of resolver that you may choose. It can be used even without an *rsdns* resolver at all, //! if you have DNS messages obtained by other means. This part is always present and cannot //! be disabled. //! //! The *resolvers* part is comprised of four independent implementations //! of the resolver API. Usually an application will use only one of those. //! See the [`resolvers`] module for more information. //! # Examples //! //! The following function retrieves [`A`] records using *rsdns's* asynchronous [`tokio::Resolver`]. //! To retrieve a different type of record, or use a different asynchronous resolver, use the //! relevant types from [`records::data`] and [`resolvers`] modules respectively. //! //! This is a very simplified example of the available API. In a real application initialization //! of the Resolver object would be done once for many DNS queries. //! Also, please note that a full application requires `tokio` runtime initialization, //! which is out of *rsdns* scope. See the [`tokio`] documentation for details. //! //! [`A`]: crate::records::data::A //! [`tokio::Resolver`]: crate::resolvers::tokio::Resolver //! [`records::data`]: crate::records::data //! [`resolvers`]: crate::resolvers //! //! ```rust //! use rsdns::{constants::RClass, records::data::A}; //! # #[cfg(feature = "net-tokio")] //! use rsdns::resolvers::{tokio::Resolver, ResolverConfig}; //! # use std::{error::Error, net::{Ipv4Addr, SocketAddr}, str::FromStr}; //! //! # #[cfg(feature = "net-tokio")] //! async fn get_a_records(qname: &str) -> Result<Vec<A>, Box<dyn Error>> { //! // use Google's Public DNS recursor as nameserver //! let nameserver = SocketAddr::from_str("8.8.8.8:53")?; //! //! // default resolver configuration; specify nameserver address only //! let config = ResolverConfig::new(nameserver); //! //! // create tokio Resolver //! let mut resolver = Resolver::new(config).await?; //! //! // issue an A query //! let rrset = resolver.query_rrset::<A>(qname, RClass::In).await?; //! //! Ok(rrset.rdata) //! } //! ``` //! //! The same function using *rsdns's* synchronous [`std::Resolver`]. //! //! [`std::Resolver`]: crate::resolvers::std::Resolver //! //! ```rust //! use rsdns::{constants::RClass, records::data::A}; //! # #[cfg(feature = "net-std")] //! use rsdns::resolvers::{std::Resolver, ResolverConfig}; //! # use std::{error::Error, net::{Ipv4Addr, SocketAddr}, str::FromStr}; //! //! # #[cfg(feature = "net-std")] //! fn get_a_records(qname: &str) -> Result<Vec<A>, Box<dyn Error>> { //! let nameserver = SocketAddr::from_str("8.8.8.8:53")?; //! let mut resolver = Resolver::new(ResolverConfig::new(nameserver))?; //! let rrset = resolver.query_rrset::<A>(qname, RClass::In)?; //! Ok(rrset.rdata) //! } //! ``` //! # `std::net::ToSocketAddrs` //! //! [`ToSocketAddrs`] is the Rust standard library interface for obtaining addresses of hostnames. //! This interface hides the low-level details of how addresses //! are obtained (usually it uses pre-configured facilities provided by the underlying operating //! system), and returns an iterator over the resulting set of addresses. //! //! The following is a list of possible limitations that you may experience with this interface: //! //! * it returns IP addresses only (`A` and `AAAA` records in DNS lingo), and doesn't allow //! retrieval of other types of data stored in DNS //! * it doesn't allow you to choose which DNS server to consult //! * it doesn't allow you to control how the communication is performed (network protocol, //! network interface, timeout etc.) //! * it is blocking - harder to use in an asynchronous context //! //! If any of the above is an issue in your application, or if you need to directly communicate with //! a DNS server, you may find *rsdns* useful. //! Otherwise, if all you need is a host address, and a blocking API call is not an issue, //! consider using [`ToSocketAddrs`] instead. It comes built-in with the Rust standard library, //! and is very simple to use. //! //! [`ToSocketAddrs`]: https://doc.rust-lang.org/std/net/trait.ToSocketAddrs.html #![warn(missing_docs)] #![cfg_attr(docsrs, feature(doc_cfg))] #[macro_use] pub(crate) mod macros; pub(crate) mod bytes; pub mod constants; mod domain_name; pub use domain_name::*; mod errors; pub mod message; pub mod records; cfg_any_resolver! { pub mod resolvers; } #[doc(inline)] pub use errors::{Error, Result};