dhcp: add "ignore NAKs" option.
This workarounds a known broken Vodafone Fiber router which replies with both NAK and ACK: ![screenshot-2021-10-19_01-18-41](https://user-images.githubusercontent.com/1247578/137819133-a8f9ab28-8bc5-4cca-9c91-2eac15d88070.png)
This commit is contained in:
parent
bcf6211fbe
commit
48debf7db8
|
@ -122,6 +122,9 @@ pub struct Dhcpv4Socket {
|
||||||
/// Max lease duration. If set, it sets a maximum cap to the server-provided lease duration.
|
/// Max lease duration. If set, it sets a maximum cap to the server-provided lease duration.
|
||||||
/// Useful to react faster to IP configuration changes and to test whether renews work correctly.
|
/// Useful to react faster to IP configuration changes and to test whether renews work correctly.
|
||||||
max_lease_duration: Option<Duration>,
|
max_lease_duration: Option<Duration>,
|
||||||
|
|
||||||
|
/// Ignore NAKs.
|
||||||
|
ignore_naks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DHCP client socket.
|
/// DHCP client socket.
|
||||||
|
@ -141,17 +144,45 @@ impl Dhcpv4Socket {
|
||||||
config_changed: true,
|
config_changed: true,
|
||||||
transaction_id: 1,
|
transaction_id: 1,
|
||||||
max_lease_duration: None,
|
max_lease_duration: None,
|
||||||
|
ignore_naks: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the configured max lease duration.
|
||||||
|
///
|
||||||
|
/// See also [`Self::set_max_lease_duration()`]
|
||||||
pub fn max_lease_duration(&self) -> Option<Duration> {
|
pub fn max_lease_duration(&self) -> Option<Duration> {
|
||||||
self.max_lease_duration
|
self.max_lease_duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the max lease duration.
|
||||||
|
///
|
||||||
|
/// When set, the lease duration will be capped at the configured duration if the
|
||||||
|
/// DHCP server gives us a longer lease. This is generally not recommended, but
|
||||||
|
/// can be useful for debugging or reacting faster to network configuration changes.
|
||||||
|
///
|
||||||
|
/// If None, no max is applied (the lease duration from the DHCP server is used.)
|
||||||
pub fn set_max_lease_duration(&mut self, max_lease_duration: Option<Duration>) {
|
pub fn set_max_lease_duration(&mut self, max_lease_duration: Option<Duration>) {
|
||||||
self.max_lease_duration = max_lease_duration;
|
self.max_lease_duration = max_lease_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get whether to ignore NAKs.
|
||||||
|
///
|
||||||
|
/// See also [`Self::set_ignore_naks()`]
|
||||||
|
pub fn ignore_naks(&self) -> bool {
|
||||||
|
self.ignore_naks
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set whether to ignore NAKs.
|
||||||
|
///
|
||||||
|
/// This is not compliant with the DHCP RFCs, since theoretically
|
||||||
|
/// we must stop using the assigned IP when receiving a NAK. This
|
||||||
|
/// can increase reliability on broken networks with buggy routers
|
||||||
|
/// or rogue DHCP servers, however.
|
||||||
|
pub fn set_ignore_naks(&mut self, ignore_naks: bool) {
|
||||||
|
self.ignore_naks = ignore_naks;
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn poll_at(&self, _cx: &Context) -> PollAt {
|
pub(crate) fn poll_at(&self, _cx: &Context) -> PollAt {
|
||||||
let t = match &self.state {
|
let t = match &self.state {
|
||||||
ClientState::Discovering(state) => state.retry_at,
|
ClientState::Discovering(state) => state.retry_at,
|
||||||
|
@ -242,7 +273,9 @@ impl Dhcpv4Socket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ClientState::Requesting(_), DhcpMessageType::Nak) => {
|
(ClientState::Requesting(_), DhcpMessageType::Nak) => {
|
||||||
self.reset();
|
if !self.ignore_naks {
|
||||||
|
self.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(ClientState::Renewing(state), DhcpMessageType::Ack) => {
|
(ClientState::Renewing(state), DhcpMessageType::Ack) => {
|
||||||
if let Some((config, renew_at, expires_at)) =
|
if let Some((config, renew_at, expires_at)) =
|
||||||
|
@ -257,7 +290,9 @@ impl Dhcpv4Socket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ClientState::Renewing(_), DhcpMessageType::Nak) => {
|
(ClientState::Renewing(_), DhcpMessageType::Nak) => {
|
||||||
self.reset();
|
if !self.ignore_naks {
|
||||||
|
self.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
net_debug!(
|
net_debug!(
|
||||||
|
|
Loading…
Reference in New Issue