From ae882f37d6b9e6454e19d19e7a8051ce3c3b06bf Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Fri, 9 Aug 2024 16:24:11 +0200 Subject: [PATCH] Add support for domain name to generate FQDNs --- embassy-net/Cargo.toml | 5 ++++- embassy-net/src/device.rs | 2 +- embassy-net/src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index d86a30755e..89c04ea2ae 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -48,6 +48,8 @@ dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"] ## Enable DHCPv4 support with hostname dhcpv4-hostname = ["dhcpv4"] +## Enable DHCP option 15 (domain-name) for use in DNS queries +dhcpv4-domainname = ["dhcpv4"] ## Enable IPv4 support proto-ipv4 = ["smoltcp/proto-ipv4"] ## Enable IPv6 support @@ -66,7 +68,7 @@ igmp = ["smoltcp/proto-igmp"] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } -smoltcp = { version = "0.11.0", default-features = false, features = [ +smoltcp = { git = "https://github.com/korken89/smoltcp.git", branch = "dhcp-option-15", default-features = false, features = [ "socket", "async", ] } @@ -80,3 +82,4 @@ managed = { version = "0.8.0", default-features = false, features = [ "map" ] } heapless = { version = "0.8", default-features = false } embedded-nal-async = { version = "0.7.1" } document-features = "0.2.7" + diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 3b1d3c47cb..b2af1d4993 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs @@ -74,7 +74,7 @@ where { fn consume(self, f: F) -> R where - F: FnOnce(&mut [u8]) -> R, + F: FnOnce(&[u8]) -> R, { self.0.consume(|buf| { #[cfg(feature = "packet-trace")] diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 56321cec99..6699a95503 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -33,7 +33,7 @@ use embassy_net_driver::{Driver, LinkState}; use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Instant, Timer}; #[allow(unused_imports)] -use heapless::Vec; +use heapless::{String, Vec}; #[cfg(feature = "dns")] pub use smoltcp::config::DNS_MAX_SERVER_COUNT; #[cfg(feature = "igmp")] @@ -66,6 +66,8 @@ const LOCAL_PORT_MAX: u16 = 65535; const MAX_QUERIES: usize = 4; #[cfg(feature = "dhcpv4-hostname")] const MAX_HOSTNAME_LEN: usize = 32; +#[cfg(all(feature = "dhcpv4-domainname", feature = "dns"))] +const MAX_DNS_QUERY_LEN: usize = 128; /// Memory resources needed for a network stack. pub struct StackResources { @@ -110,6 +112,9 @@ pub struct StaticConfigV4 { pub gateway: Option, /// DNS servers. pub dns_servers: Vec, + /// Domain name. + #[cfg(feature = "dhcpv4-domainname")] + pub domain_name: Option>, } /// Static IPv6 address configuration @@ -146,7 +151,7 @@ pub struct DhcpConfig { pub client_port: u16, /// Our hostname. This will be sent to the DHCP server as Option 12. #[cfg(feature = "dhcpv4-hostname")] - pub hostname: Option>, + pub hostname: Option>, } #[cfg(feature = "dhcpv4")] @@ -527,6 +532,15 @@ impl Stack { _ => {} } + #[cfg(feature = "dhcpv4-domainname")] + let name = if name.contains(".") { + // Already a FQDN. + name + } else { + &self.create_fqdn(name)? + }; + debug!("Performing DNS lookup of: {}", name); + let query = poll_fn(|cx| { self.with_mut(|s, i| { let socket = s.sockets.get_mut::(i.dns_socket); @@ -602,6 +616,23 @@ impl Stack { res } + + #[cfg(feature = "dhcpv4-domainname")] + fn create_fqdn(&self, name: &str) -> Result, dns::Error> { + use core::str::FromStr; + + // Form name together with domain name. + let mut name = String::::from_str(name).map_err(|_| dns::Error::NameTooLong)?; + + if let Some(Some(domain_name)) = &self.inner.borrow().static_v4.as_ref().map(|c| &c.domain_name) { + if !domain_name.is_empty() { + name.push('.').map_err(|_| dns::Error::NameTooLong)?; + name.push_str(&domain_name).map_err(|_| dns::Error::NameTooLong)?; + } + } + + Ok(name) + } } #[cfg(feature = "igmp")] @@ -788,6 +819,8 @@ impl Inner { debug!(" DNS server: {:?}", s); unwrap!(dns_servers.push(s.clone().into()).ok()); } + #[cfg(feature = "dhcpv4-domainname")] + debug!(" Domain name: {:?}", config.domain_name); } else { info!("IPv4: DOWN"); } @@ -902,6 +935,8 @@ impl Inner { address: config.address, gateway: config.router, dns_servers: config.dns_servers, + #[cfg(feature = "dhcpv4-domainname")] + domain_name: config.domain_name, }); apply_config = true; }