aboutsummaryrefslogtreecommitdiff
path: root/embassy-net
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-06 20:47:31 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-07 01:33:21 +0200
commit534eb960e9f7c9bb28cbd6ffe10b6cc43fd55ff7 (patch)
tree16dff322979e05e9da47c95e3131a3ac49e9b1e4 /embassy-net
parentf30fc949ff34683bd9b9330d09583da4a35428ea (diff)
net: add support for dhcp hostname option.
Diffstat (limited to 'embassy-net')
-rw-r--r--embassy-net/Cargo.toml1
-rw-r--r--embassy-net/src/lib.rs44
2 files changed, 45 insertions, 0 deletions
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 89582deee..c2fffba84 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -33,6 +33,7 @@ udp = ["smoltcp/socket-udp"]
33tcp = ["smoltcp/socket-tcp"] 33tcp = ["smoltcp/socket-tcp"]
34dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] 34dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"]
35dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"] 35dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"]
36dhcpv4-hostname = ["dhcpv4"]
36proto-ipv4 = ["smoltcp/proto-ipv4"] 37proto-ipv4 = ["smoltcp/proto-ipv4"]
37proto-ipv6 = ["smoltcp/proto-ipv6"] 38proto-ipv6 = ["smoltcp/proto-ipv6"]
38medium-ethernet = ["smoltcp/medium-ethernet"] 39medium-ethernet = ["smoltcp/medium-ethernet"]
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index 297f04679..ef67935e1 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -56,12 +56,22 @@ const LOCAL_PORT_MIN: u16 = 1025;
56const LOCAL_PORT_MAX: u16 = 65535; 56const LOCAL_PORT_MAX: u16 = 65535;
57#[cfg(feature = "dns")] 57#[cfg(feature = "dns")]
58const MAX_QUERIES: usize = 4; 58const MAX_QUERIES: usize = 4;
59#[cfg(feature = "dhcpv4-hostname")]
60const MAX_HOSTNAME_LEN: usize = 32;
59 61
60/// Memory resources needed for a network stack. 62/// Memory resources needed for a network stack.
61pub struct StackResources<const SOCK: usize> { 63pub struct StackResources<const SOCK: usize> {
62 sockets: [SocketStorage<'static>; SOCK], 64 sockets: [SocketStorage<'static>; SOCK],
63 #[cfg(feature = "dns")] 65 #[cfg(feature = "dns")]
64 queries: [Option<dns::DnsQuery>; MAX_QUERIES], 66 queries: [Option<dns::DnsQuery>; MAX_QUERIES],
67 #[cfg(feature = "dhcpv4-hostname")]
68 hostname: core::cell::UnsafeCell<HostnameResources>,
69}
70
71#[cfg(feature = "dhcpv4-hostname")]
72struct HostnameResources {
73 option: smoltcp::wire::DhcpOption<'static>,
74 data: [u8; MAX_HOSTNAME_LEN],
65} 75}
66 76
67impl<const SOCK: usize> StackResources<SOCK> { 77impl<const SOCK: usize> StackResources<SOCK> {
@@ -73,6 +83,11 @@ impl<const SOCK: usize> StackResources<SOCK> {
73 sockets: [SocketStorage::EMPTY; SOCK], 83 sockets: [SocketStorage::EMPTY; SOCK],
74 #[cfg(feature = "dns")] 84 #[cfg(feature = "dns")]
75 queries: [INIT; MAX_QUERIES], 85 queries: [INIT; MAX_QUERIES],
86 #[cfg(feature = "dhcpv4-hostname")]
87 hostname: core::cell::UnsafeCell::new(HostnameResources {
88 option: smoltcp::wire::DhcpOption { kind: 0, data: &[] },
89 data: [0; MAX_HOSTNAME_LEN],
90 }),
76 } 91 }
77 } 92 }
78} 93}
@@ -104,6 +119,7 @@ pub struct StaticConfigV6 {
104/// DHCP configuration. 119/// DHCP configuration.
105#[cfg(feature = "dhcpv4")] 120#[cfg(feature = "dhcpv4")]
106#[derive(Debug, Clone, PartialEq, Eq)] 121#[derive(Debug, Clone, PartialEq, Eq)]
122#[non_exhaustive]
107pub struct DhcpConfig { 123pub struct DhcpConfig {
108 /// Maximum lease duration. 124 /// Maximum lease duration.
109 /// 125 ///
@@ -120,6 +136,9 @@ pub struct DhcpConfig {
120 pub server_port: u16, 136 pub server_port: u16,
121 /// Client port. This is almost always 68. Do not change unless you know what you're doing. 137 /// Client port. This is almost always 68. Do not change unless you know what you're doing.
122 pub client_port: u16, 138 pub client_port: u16,
139 /// Our hostname. This will be sent to the DHCP server as Option 12.
140 #[cfg(feature = "dhcpv4-hostname")]
141 pub hostname: Option<heapless::String<MAX_HOSTNAME_LEN>>,
123} 142}
124 143
125#[cfg(feature = "dhcpv4")] 144#[cfg(feature = "dhcpv4")]
@@ -131,6 +150,8 @@ impl Default for DhcpConfig {
131 ignore_naks: Default::default(), 150 ignore_naks: Default::default(),
132 server_port: smoltcp::wire::DHCP_SERVER_PORT, 151 server_port: smoltcp::wire::DHCP_SERVER_PORT,
133 client_port: smoltcp::wire::DHCP_CLIENT_PORT, 152 client_port: smoltcp::wire::DHCP_CLIENT_PORT,
153 #[cfg(feature = "dhcpv4-hostname")]
154 hostname: None,
134 } 155 }
135 } 156 }
136} 157}
@@ -232,6 +253,8 @@ struct Inner<D: Driver> {
232 dns_socket: SocketHandle, 253 dns_socket: SocketHandle,
233 #[cfg(feature = "dns")] 254 #[cfg(feature = "dns")]
234 dns_waker: WakerRegistration, 255 dns_waker: WakerRegistration,
256 #[cfg(feature = "dhcpv4-hostname")]
257 hostname: &'static mut core::cell::UnsafeCell<HostnameResources>,
235} 258}
236 259
237pub(crate) struct SocketStack { 260pub(crate) struct SocketStack {
@@ -307,6 +330,8 @@ impl<D: Driver> Stack<D> {
307 )), 330 )),
308 #[cfg(feature = "dns")] 331 #[cfg(feature = "dns")]
309 dns_waker: WakerRegistration::new(), 332 dns_waker: WakerRegistration::new(),
333 #[cfg(feature = "dhcpv4-hostname")]
334 hostname: &mut resources.hostname,
310 }; 335 };
311 336
312 #[cfg(feature = "proto-ipv4")] 337 #[cfg(feature = "proto-ipv4")]
@@ -673,6 +698,25 @@ impl<D: Driver> Inner<D> {
673 socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); 698 socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp));
674 socket.set_ports(c.server_port, c.client_port); 699 socket.set_ports(c.server_port, c.client_port);
675 socket.set_retry_config(c.retry_config); 700 socket.set_retry_config(c.retry_config);
701
702 socket.set_outgoing_options(&[]);
703 #[cfg(feature = "dhcpv4-hostname")]
704 if let Some(h) = c.hostname {
705 // safety: we just did set_outgoing_options([]) so we know the socket is no longer holding a reference.
706 let hostname = unsafe { &mut *self.hostname.get() };
707
708 // create data
709 // safety: we know the buffer lives forever, new borrows the StackResources for 'static.
710 // also we won't modify it until next call to this function.
711 hostname.data[..h.len()].copy_from_slice(h.as_bytes());
712 let data: &[u8] = &hostname.data[..h.len()];
713 let data: &'static [u8] = unsafe { core::mem::transmute(data) };
714
715 // set the option.
716 hostname.option = smoltcp::wire::DhcpOption { data, kind: 12 };
717 socket.set_outgoing_options(core::slice::from_ref(&hostname.option));
718 }
719
676 socket.reset(); 720 socket.reset();
677 } 721 }
678 _ => { 722 _ => {