Skip to main content

edge_nal/stack/
dns.rs

1//! A trait for performing DNS lookups on embedded devices
2
3use core::net::IpAddr;
4
5/// This is the host address type to be returned by `gethostbyname`.
6///
7/// An IPv4 address type always looks for `A` records, while IPv6 address type
8/// will look for `AAAA` records
9#[derive(Clone, Debug, PartialEq)]
10pub enum AddrType {
11    /// Result is `A` record
12    IPv4,
13    /// Result is `AAAA` record
14    IPv6,
15    /// Result is either a `A` record, or a `AAAA` record
16    Either,
17}
18
19/// This trait provides DNS resolution facility for embedded applications.
20///
21/// It does not handle every DNS record type, but is meant as an
22/// embedded alternative to [`ToSocketAddrs`], and is as such meant to resolve
23/// an ip address from a hostname, or a hostname from an ip address. This means
24/// that it only deals in host address records `A` (IPv4) and `AAAA` (IPv6).
25///
26/// [`ToSocketAddrs`]:
27/// https://doc.rust-lang.org/std/net/trait.ToSocketAddrs.html
28pub trait Dns {
29    /// The type returned when we have an error
30    type Error: embedded_io_async::Error;
31
32    /// Resolve the first ip address of a host, given its hostname and a desired
33    /// address record type to look for
34    async fn get_host_by_name(
35        &self,
36        host: &str,
37        addr_type: AddrType,
38    ) -> Result<IpAddr, Self::Error>;
39
40    /// Resolve the hostname of a host, given its ip address.
41    ///
42    /// The hostname is stored at the beginning of `result`, the length is returned.
43    ///
44    /// If the buffer is too small to hold the domain name, an error should be returned.
45    ///
46    /// **Note**: A fully qualified domain name (FQDN), has a maximum length of
47    /// 255 bytes according to [`rfc1035`]. Therefore, you can pass a 255-byte long
48    /// buffer to guarantee it'll always be large enough.
49    ///
50    /// [`rfc1035`]: https://tools.ietf.org/html/rfc1035
51    async fn get_host_by_address(
52        &self,
53        addr: IpAddr,
54        result: &mut [u8],
55    ) -> Result<usize, Self::Error>;
56}
57
58impl<T> Dns for &T
59where
60    T: Dns,
61{
62    type Error = T::Error;
63
64    async fn get_host_by_name(
65        &self,
66        host: &str,
67        addr_type: AddrType,
68    ) -> Result<IpAddr, Self::Error> {
69        T::get_host_by_name(self, host, addr_type).await
70    }
71
72    async fn get_host_by_address(
73        &self,
74        addr: IpAddr,
75        result: &mut [u8],
76    ) -> Result<usize, Self::Error> {
77        T::get_host_by_address(self, addr, result).await
78    }
79}
80
81impl<T> Dns for &mut T
82where
83    T: Dns,
84{
85    type Error = T::Error;
86
87    async fn get_host_by_name(
88        &self,
89        host: &str,
90        addr_type: AddrType,
91    ) -> Result<IpAddr, Self::Error> {
92        T::get_host_by_name(self, host, addr_type).await
93    }
94
95    async fn get_host_by_address(
96        &self,
97        addr: IpAddr,
98        result: &mut [u8],
99    ) -> Result<usize, Self::Error> {
100        T::get_host_by_address(self, addr, result).await
101    }
102}