Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions src/network/create_config/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ pub fn validate_subnets(

/// Get the first IP address in a subnet (network address + 1).
fn first_ip_in_subnet(network: &IpNet) -> NetavarkResult<IpAddr> {
match network {
let first_ip = match network {
IpNet::V4(net_v4) => {
let network_addr: u32 = net_v4.network().into();
let first_ip = network_addr
.checked_add(1)
.ok_or_else(|| NetavarkError::msg("Subnet address overflow"))?;
Ok(IpAddr::V4(first_ip.into()))
IpAddr::V4(first_ip.into())
}
IpNet::V6(net_v6) => {
use std::net::Ipv6Addr;
Expand All @@ -154,9 +154,18 @@ fn first_ip_in_subnet(network: &IpNet) -> NetavarkResult<IpAddr> {
let first_ip_u128 = addr_u128
.checked_add(1)
.ok_or_else(|| NetavarkError::msg("Subnet address overflow"))?;
Ok(IpAddr::V6(Ipv6Addr::from(first_ip_u128.to_be_bytes())))
IpAddr::V6(Ipv6Addr::from(first_ip_u128.to_be_bytes()))
}
};

if !network.contains(&first_ip) {
return Err(NetavarkError::msg(format!(
"could not create gateway for subnet {}",
network
)));
}
Comment on lines +161 to 166

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of adding another check here could you not just swap the order in validate_subnet() which already checks that as well.

Then again if we do not work with /32 or /128 then we might as well produce an actual error saying that explicitly at least.


Ok(first_ip)
}

/// Validate lease range IP addresses against a subnet.
Expand Down Expand Up @@ -219,6 +228,56 @@ fn validate_lease_range(
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn validate_subnet_adds_first_ip_as_gateway() {
let mut subnet = Subnet {
subnet: "10.100.0.0/24".parse().unwrap(),
gateway: None,
lease_range: None,
};

validate_subnet(&mut subnet, true, false, &[]).unwrap();

assert_eq!(subnet.gateway, Some("10.100.0.1".parse().unwrap()));
}

#[test]
fn validate_subnet_rejects_ipv4_subnet_without_gateway_address() {
let mut subnet = Subnet {
subnet: "10.100.0.1/32".parse().unwrap(),
gateway: None,
lease_range: None,
};

let err = validate_subnet(&mut subnet, true, false, &[]).unwrap_err();

assert_eq!(
err.to_string(),
"could not create gateway for subnet 10.100.0.1/32"
);
}

#[test]
fn validate_subnet_rejects_ipv6_subnet_without_gateway_address() {
let mut subnet = Subnet {
subnet: "fd00::1/128".parse().unwrap(),
gateway: None,
lease_range: None,
};

let err = validate_subnet(&mut subnet, true, false, &[]).unwrap_err();

assert_eq!(
err.to_string(),
"could not create gateway for subnet fd00::1/128"
);
}
}

/// Validate a single subnet.
/// This function validates the subnet, checks for conflicts with used networks,
/// validates/creates the gateway, and validates the lease range.
Expand Down