Skip to content

Commit 1db8dcb

Browse files
committed
Add support for domain name and domain search to generate FQDNs
1 parent b55726c commit 1db8dcb

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

embassy-net/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"]
4848
dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"]
4949
## Enable DHCPv4 support with hostname
5050
dhcpv4-hostname = ["dhcpv4"]
51+
## Enable DHCP option 15 (domain-name) for use in DNS queries
52+
dhcpv4-domainname = ["dhcpv4"]
5153
## Enable IPv4 support
5254
proto-ipv4 = ["smoltcp/proto-ipv4"]
5355
## Enable IPv6 support

embassy-net/src/lib.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use embassy_net_driver::{Driver, LinkState};
3333
use embassy_sync::waitqueue::WakerRegistration;
3434
use embassy_time::{Instant, Timer};
3535
#[allow(unused_imports)]
36-
use heapless::Vec;
36+
use heapless::{String, Vec};
3737
#[cfg(feature = "dns")]
3838
pub use smoltcp::config::DNS_MAX_SERVER_COUNT;
3939
#[cfg(feature = "igmp")]
@@ -66,6 +66,10 @@ const LOCAL_PORT_MAX: u16 = 65535;
6666
const MAX_QUERIES: usize = 4;
6767
#[cfg(feature = "dhcpv4-hostname")]
6868
const MAX_HOSTNAME_LEN: usize = 32;
69+
#[cfg(feature = "dhcpv4-domainname")]
70+
const MAX_DOMAINNAME_LEN: usize = 64;
71+
#[cfg(all(feature = "dhcpv4-domainname", feature = "dns"))]
72+
const MAX_DNS_QUERY_LEN: usize = 128;
6973

7074
/// Memory resources needed for a network stack.
7175
pub struct StackResources<const SOCK: usize> {
@@ -146,7 +150,7 @@ pub struct DhcpConfig {
146150
pub client_port: u16,
147151
/// Our hostname. This will be sent to the DHCP server as Option 12.
148152
#[cfg(feature = "dhcpv4-hostname")]
149-
pub hostname: Option<heapless::String<MAX_HOSTNAME_LEN>>,
153+
pub hostname: Option<String<MAX_HOSTNAME_LEN>>,
150154
}
151155

152156
#[cfg(feature = "dhcpv4")]
@@ -263,6 +267,8 @@ struct Inner<D: Driver> {
263267
dns_waker: WakerRegistration,
264268
#[cfg(feature = "dhcpv4-hostname")]
265269
hostname: &'static mut core::cell::UnsafeCell<HostnameResources>,
270+
#[cfg(feature = "dhcpv4-domainname")]
271+
domainname: String<MAX_DOMAINNAME_LEN>,
266272
}
267273

268274
pub(crate) struct SocketStack {
@@ -345,6 +351,8 @@ impl<D: Driver> Stack<D> {
345351
dns_waker: WakerRegistration::new(),
346352
#[cfg(feature = "dhcpv4-hostname")]
347353
hostname: &mut resources.hostname,
354+
#[cfg(feature = "dhcpv4-domainname")]
355+
domainname: String::new(),
348356
};
349357

350358
#[cfg(feature = "proto-ipv4")]
@@ -527,6 +535,20 @@ impl<D: Driver> Stack<D> {
527535
_ => {}
528536
}
529537

538+
// Form name together with domain name.
539+
#[cfg(feature = "dhcpv4-domainname")]
540+
let name = &{
541+
use core::str::FromStr;
542+
543+
let domainname = &self.inner.borrow().domainname;
544+
let mut name = String::<MAX_DNS_QUERY_LEN>::from_str(name).map_err(|_| dns::Error::NameTooLong)?;
545+
if !domainname.is_empty() {
546+
name.push('.').map_err(|_| dns::Error::NameTooLong)?;
547+
name.push_str(domainname).map_err(|_| dns::Error::NameTooLong)?;
548+
}
549+
name
550+
};
551+
530552
let query = poll_fn(|cx| {
531553
self.with_mut(|s, i| {
532554
let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket);
@@ -746,6 +768,12 @@ impl<D: Driver> Inner<D> {
746768
socket.set_outgoing_options(core::slice::from_ref(&hostname.option));
747769
}
748770

771+
// The domain-search (119) option specifies a list of domains to use when looking up bare
772+
// hostnames, and is specified in resolv.conf with the search keyword. If this option
773+
// isn't provided it defaults to the single domain provided by domain-name (15).
774+
#[cfg(feature = "dhcpv4-domainname")]
775+
socket.set_parameter_request_list(&[1, 3, 6, 15, 119]);
776+
749777
socket.reset();
750778
}
751779
_ => {
@@ -904,6 +932,21 @@ impl<D: Driver> Inner<D> {
904932
dns_servers: config.dns_servers,
905933
});
906934
apply_config = true;
935+
936+
#[cfg(feature = "dhcpv4-domainname")]
937+
if let Some(packet) = config.packet {
938+
if let Some(domainname) = packet.options().find(|o| o.kind == 15) {
939+
self.domainname.clear();
940+
if let Ok(name) = core::str::from_utf8(domainname.data) {
941+
if self.domainname.push_str(name).is_err() {
942+
warn!("Domain name is too long, skipping");
943+
} else {
944+
debug!("DHCP: Got domain name");
945+
debug!(" Domain name: '{}'", self.domainname);
946+
}
947+
}
948+
}
949+
}
907950
}
908951
}
909952
} else if old_link_up {

0 commit comments

Comments
 (0)