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}