nrf_modem/dns/
dns_blocking.rs1use crate::{ip::NrfSockAddr, lte_link::LteLink, CancellationToken, Error};
2use arrayvec::ArrayString;
3use core::net::{IpAddr, SocketAddr};
4use core::str::FromStr;
5
6use super::{AddrType, DnsQuery};
7
8pub async fn get_host_by_name(hostname: &str) -> Result<IpAddr, Error> {
17 resolve_dns(DnsQuery::new(hostname)).await
18}
19
20pub async fn get_host_by_name_with_cancellation(
29 hostname: &str,
30 token: &CancellationToken,
31) -> Result<IpAddr, Error> {
32 resolve_dns_with_cancellation(DnsQuery::new(hostname), token).await
33}
34
35pub async fn resolve_dns(query: DnsQuery<'_>) -> Result<IpAddr, Error> {
44 resolve_dns_with_cancellation(query, &Default::default()).await
45}
46
47pub async fn resolve_dns_with_cancellation(
56 query: DnsQuery<'_>,
57 token: &CancellationToken,
58) -> Result<IpAddr, Error> {
59 #[cfg(feature = "defmt")]
60 defmt::debug!("Resolving dns hostname for \"{}\"", query.hostname());
61
62 if let Ok(ip) = query.hostname().parse() {
64 if !query.addr_type().addr_matches(ip) {
66 return Err(Error::AddressNotFound);
67 } else {
68 return Ok(ip);
69 }
70 }
71
72 if !query.hostname().is_ascii() {
74 return Err(Error::HostnameNotAscii);
75 }
76
77 token.bind_to_current_task().await;
78
79 let link = LteLink::new().await?;
81 link.wait_for_link_with_cancellation(token).await?;
82
83 let mut found_ip = None;
84
85 unsafe {
86 let hints = nrfxlib_sys::nrf_addrinfo {
87 ai_family: match query.addr_type() {
88 AddrType::Any => nrfxlib_sys::NRF_AF_UNSPEC as _,
89 AddrType::V4 => nrfxlib_sys::NRF_AF_INET as _,
90 AddrType::V6 => nrfxlib_sys::NRF_AF_INET6 as _,
91 },
92 ai_socktype: nrfxlib_sys::NRF_SOCK_STREAM as _,
93
94 ai_flags: 0,
95 ai_protocol: 0,
96 ai_addrlen: 0,
97 ai_addr: core::ptr::null_mut(),
98 ai_canonname: core::ptr::null_mut(),
99 ai_next: core::ptr::null_mut(),
100 };
101
102 let mut result: *mut nrfxlib_sys::nrf_addrinfo = core::ptr::null_mut();
103
104 let mut hostname =
106 ArrayString::<257>::from_str(query.hostname()).map_err(|_| Error::HostnameTooLong)?;
107 hostname.push('\0');
108
109 let err = nrfxlib_sys::nrf_getaddrinfo(
110 hostname.as_ptr() as *const core::ffi::c_char,
111 core::ptr::null(),
112 &hints as *const _,
113 &mut result as *mut *mut _,
114 ) as isize;
115
116 let deactivation_result = link.deactivate().await;
117
118 if err > 0 {
119 return Err(Error::NrfError(err));
120 } else if err == -1 {
121 return Err(Error::NrfError(crate::ffi::get_last_error()));
122 }
123
124 if result.is_null() {
125 return Err(Error::AddressNotFound);
126 }
127
128 if let Err(deactivation_error) = deactivation_result {
129 nrfxlib_sys::nrf_freeaddrinfo(result);
130 return Err(deactivation_error);
131 }
132
133 let mut result_iter = result;
134
135 while !result_iter.is_null() && found_ip.is_none() {
136 let address = (*result_iter).ai_addr;
137
138 if (*address).sa_family == nrfxlib_sys::NRF_AF_INET as u16 {
139 let dns_addr: &nrfxlib_sys::nrf_sockaddr_in =
140 &*(address as *const nrfxlib_sys::nrf_sockaddr_in);
141
142 let socket_addr: SocketAddr = NrfSockAddr::from(*dns_addr).into();
143 found_ip = Some(socket_addr.ip());
144 } else if (*address).sa_family == nrfxlib_sys::NRF_AF_INET6 as u16 {
145 let dns_addr: &nrfxlib_sys::nrf_sockaddr_in6 =
146 &*(address as *const nrfxlib_sys::nrf_sockaddr_in6);
147
148 let socket_addr: SocketAddr = NrfSockAddr::from(*dns_addr).into();
149 found_ip = Some(socket_addr.ip());
150 }
151
152 result_iter = (*result_iter).ai_next;
153 }
154
155 nrfxlib_sys::nrf_freeaddrinfo(result);
157
158 if let Some(found_ip) = found_ip {
159 Ok(found_ip)
160 } else {
161 Err(Error::AddressNotFound)
162 }
163 }
164}