Skip to content

Commit

Permalink
fix DHCPv4 panic when T1 < T2 < lease duration is not respected
Browse files Browse the repository at this point in the history
When receiving T1 and T2 values from the DHCP server, they must be in
the order T1 < T2 < lease duration. If this order is not respected, the
defaults should be used. This patch adds a check to ensure that the
order is respected and uses the defaults otherwise.

Signed-off-by: Thibaut Vandervelden <thvdveld@vub.be>
  • Loading branch information
thvdveld committed Jan 3, 2025
1 parent 3a30d0c commit e77d02b
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/socket/dhcpv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ impl<'a> Socket<'a> {
// Times T1 and T2 are configurable by the server through
// options. T1 defaults to (0.5 * duration_of_lease). T2
// defaults to (0.875 * duration_of_lease).
// When receiving T1 and T2, they must be in the order:
// T1 < T2 < lease_duration
let (renew_duration, rebind_duration) = match (
dhcp_repr
.renew_duration
Expand All @@ -510,26 +512,36 @@ impl<'a> Socket<'a> {
.rebind_duration
.map(|d| Duration::from_secs(d as u64)),
) {
(Some(renew_duration), Some(rebind_duration)) => (renew_duration, rebind_duration),
(None, None) => (lease_duration / 2, lease_duration * 7 / 8),
(Some(renew_duration), Some(rebind_duration))
if renew_duration < rebind_duration && rebind_duration < lease_duration =>
{
(renew_duration, rebind_duration)
}
// RFC 2131 does not say what to do if only one value is
// provided, so:

// If only T1 is provided, set T2 to be 0.75 through the gap
// between T1 and the duration of the lease. If T1 is set to
// the default (0.5 * duration_of_lease), then T2 will also
// be set to the default (0.875 * duration_of_lease).
(Some(renew_duration), None) => (
(Some(renew_duration), None) if renew_duration < lease_duration => (
renew_duration,
renew_duration + (lease_duration - renew_duration) * 3 / 4,
),

// If only T2 is provided, then T1 will be set to be
// whichever is smaller of the default (0.5 *
// duration_of_lease) or T2.
(None, Some(rebind_duration)) => {
(None, Some(rebind_duration)) if rebind_duration < lease_duration => {
((lease_duration / 2).min(rebind_duration), rebind_duration)
}

// Use the defaults if the following order is not met:
// T1 < T2 < lease_duration
(_, _) => {
net_debug!("using default T1 and T2 values since the provided values are invalid");
(lease_duration / 2, lease_duration * 7 / 8)
}
};
let renew_at = now + renew_duration;
let rebind_at = now + rebind_duration;
Expand Down

0 comments on commit e77d02b

Please sign in to comment.