feat(opnsense-config): ip_in_range function works
This commit is contained in:
parent
0700265622
commit
85786cf648
@ -1,3 +1,7 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use super::opnsense::{OPNsense, StaticMap};
|
use super::opnsense::{OPNsense, StaticMap};
|
||||||
use crate::infra::maybe_string::MaybeString;
|
use crate::infra::maybe_string::MaybeString;
|
||||||
use crate::modules::opnsense::NumberOption;
|
use crate::modules::opnsense::NumberOption;
|
||||||
@ -13,7 +17,7 @@ pub enum DhcpError {
|
|||||||
InvalidMacAddress(String),
|
InvalidMacAddress(String),
|
||||||
InvalidIpAddress(String),
|
InvalidIpAddress(String),
|
||||||
IpAddressAlreadyMapped(String),
|
IpAddressAlreadyMapped(String),
|
||||||
MacAddressAlreadyMapped(String),
|
MacAddressAlreadyMapped(String),
|
||||||
IpAddressOutOfRange(String),
|
IpAddressOutOfRange(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,9 +26,15 @@ impl std::fmt::Display for DhcpError {
|
|||||||
match self {
|
match self {
|
||||||
DhcpError::InvalidMacAddress(mac) => write!(f, "Invalid MAC address format: {}", mac),
|
DhcpError::InvalidMacAddress(mac) => write!(f, "Invalid MAC address format: {}", mac),
|
||||||
DhcpError::InvalidIpAddress(ip) => write!(f, "Invalid IP address format: {}", ip),
|
DhcpError::InvalidIpAddress(ip) => write!(f, "Invalid IP address format: {}", ip),
|
||||||
DhcpError::IpAddressAlreadyMapped(ip) => write!(f, "IP address {} is already mapped", ip),
|
DhcpError::IpAddressAlreadyMapped(ip) => {
|
||||||
DhcpError::MacAddressAlreadyMapped(mac) => write!(f, "MAC address {} is already mapped", mac),
|
write!(f, "IP address {} is already mapped", ip)
|
||||||
DhcpError::IpAddressOutOfRange(ip) => write!(f, "IP address {} is out of interface range", ip),
|
}
|
||||||
|
DhcpError::MacAddressAlreadyMapped(mac) => {
|
||||||
|
write!(f, "MAC address {} is already mapped", mac)
|
||||||
|
}
|
||||||
|
DhcpError::IpAddressOutOfRange(ip) => {
|
||||||
|
write!(f, "IP address {} is out of interface range", ip)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,42 +49,40 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
pub fn add_static_mapping(
|
pub fn add_static_mapping(
|
||||||
&mut self,
|
&mut self,
|
||||||
mac: String,
|
mac: String,
|
||||||
ipaddr: String,
|
ipaddr: Ipv4Addr,
|
||||||
hostname: String,
|
hostname: String,
|
||||||
) -> Result<(), DhcpError> {
|
) -> Result<(), DhcpError> {
|
||||||
|
let range: Range = todo!();
|
||||||
if !Self::is_valid_mac(&mac) {
|
if !Self::is_valid_mac(&mac) {
|
||||||
return Err(DhcpError::InvalidMacAddress(mac));
|
return Err(DhcpError::InvalidMacAddress(mac));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Self::is_valid_ip(&ipaddr) {
|
// if !Self::is_ip_in_range(&ipaddr, range) {
|
||||||
return Err(DhcpError::InvalidIpAddress(ipaddr));
|
// return Err(DhcpError::IpAddressOutOfRange(ipaddr));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !Self::is_ip_in_range(&ipaddr) {
|
|
||||||
return Err(DhcpError::IpAddressOutOfRange(ipaddr));
|
|
||||||
}
|
|
||||||
|
|
||||||
let existing_mappings = &self.opnsense.dhcpd.lan.staticmaps;
|
let existing_mappings = &self.opnsense.dhcpd.lan.staticmaps;
|
||||||
|
|
||||||
if existing_mappings.iter().any(|m| m.ipaddr == ipaddr) {
|
|
||||||
return Err(DhcpError::IpAddressAlreadyMapped(ipaddr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if existing_mappings.iter().any(|m| m.mac == mac) {
|
|
||||||
return Err(DhcpError::MacAddressAlreadyMapped(mac));
|
|
||||||
}
|
|
||||||
|
|
||||||
let static_map = StaticMap {
|
// TODO
|
||||||
mac,
|
// if existing_mappings.iter().any(|m| m.ipaddr == ipaddr) {
|
||||||
ipaddr,
|
// return Err(DhcpError::IpAddressAlreadyMapped(ipaddr));
|
||||||
hostname,
|
// }
|
||||||
descr: Default::default(),
|
|
||||||
winsserver: Default::default(),
|
|
||||||
dnsserver: Default::default(),
|
|
||||||
ntpserver: Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
// if existing_mappings.iter().any(|m| m.mac == mac) {
|
||||||
|
// return Err(DhcpError::MacAddressAlreadyMapped(mac));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let static_map = StaticMap {
|
||||||
|
// mac,
|
||||||
|
// ipaddr,
|
||||||
|
// hostname,
|
||||||
|
// descr: Default::default(),
|
||||||
|
// winsserver: Default::default(),
|
||||||
|
// dnsserver: Default::default(),
|
||||||
|
// ntpserver: Default::default(),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,51 +96,28 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.iter().all(|part| {
|
parts
|
||||||
part.len() == 2 && part.chars().all(|c| c.is_ascii_hexdigit())
|
.iter()
|
||||||
})
|
.all(|part| part.len() == 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_ip(ip: &str) -> bool {
|
fn is_ip_in_range(ip: &Ipv4Addr, range: Range) -> bool {
|
||||||
ip.parse::<IpAddr>().is_ok()
|
let range_start = range
|
||||||
}
|
.from
|
||||||
|
.parse::<Ipv4Addr>()
|
||||||
|
.expect("Invalid DHCP range start");
|
||||||
|
let range_end = range.to.parse::<Ipv4Addr>().expect("Invalid DHCP range to");
|
||||||
|
|
||||||
fn is_ip_in_range(ip: &str) -> bool {
|
let start_compare = range_start.cmp(ip);
|
||||||
if let Ok(addr) = ip.parse::<IpAddr>() {
|
let end_compare = range_end.cmp(ip);
|
||||||
if let IpAddr::V4(ipv4) = addr {
|
|
||||||
let octets = ipv4.octets();
|
if (Ordering::Less == start_compare || Ordering::Equal == start_compare)
|
||||||
return octets[0] == 192 && octets[1] == 168 && octets[2] == 1;
|
&& (Ordering::Greater == end_compare || Ordering::Equal == end_compare)
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DhcpConfig<'a> {
|
|
||||||
opnsense: &'a mut OPNsense,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl<'a> DhcpConfig<'a> {
|
|
||||||
pub fn new(opnsense: &'a mut OPNsense) -> Self {
|
|
||||||
Self { opnsense }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_static_mapping(&mut self, mac: String, ipaddr: String, hostname: String) {
|
|
||||||
let static_map = StaticMap {
|
|
||||||
mac,
|
|
||||||
ipaddr,
|
|
||||||
hostname,
|
|
||||||
descr: Default::default(),
|
|
||||||
winsserver: Default::default(),
|
|
||||||
dnsserver: Default::default(),
|
|
||||||
ntpserver: Default::default(),
|
|
||||||
};
|
|
||||||
self.opnsense.dhcpd.lan.staticmaps.push(static_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_static_mappings(&self) -> &[StaticMap] {
|
|
||||||
&self.opnsense.dhcpd.lan.staticmaps
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,6 +157,7 @@ pub struct DhcpRange {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
use crate::infra::yaserde::to_xml_str;
|
use crate::infra::yaserde::to_xml_str;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -183,8 +169,7 @@ mod test {
|
|||||||
yaserde::de::from_str(SERIALIZED_DHCPD).expect("Deserialize Dhcpd failed");
|
yaserde::de::from_str(SERIALIZED_DHCPD).expect("Deserialize Dhcpd failed");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_xml_str(&dhcpd)
|
to_xml_str(&dhcpd).expect("Serialize Dhcpd failed"),
|
||||||
.expect("Serialize Dhcpd failed"),
|
|
||||||
SERIALIZED_DHCPD
|
SERIALIZED_DHCPD
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -244,4 +229,32 @@ mod test {
|
|||||||
<pool/>
|
<pool/>
|
||||||
</lan>
|
</lan>
|
||||||
</dhcpd>\n";
|
</dhcpd>\n";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ip_in_range() {
|
||||||
|
let range = Range {
|
||||||
|
from: "192.168.1.100".to_string(),
|
||||||
|
to: "192.168.1.200".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test IP within range
|
||||||
|
let ip = "192.168.1.150".parse::<Ipv4Addr>().unwrap();
|
||||||
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
||||||
|
|
||||||
|
// Test IP at start of range
|
||||||
|
let ip = "192.168.1.100".parse::<Ipv4Addr>().unwrap();
|
||||||
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
||||||
|
|
||||||
|
// Test IP at end of range
|
||||||
|
let ip = "192.168.1.200".parse::<Ipv4Addr>().unwrap();
|
||||||
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), true);
|
||||||
|
|
||||||
|
// Test IP before range
|
||||||
|
let ip = "192.168.1.99".parse::<Ipv4Addr>().unwrap();
|
||||||
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), false);
|
||||||
|
|
||||||
|
// Test IP after range
|
||||||
|
let ip = "192.168.1.201".parse::<Ipv4Addr>().unwrap();
|
||||||
|
assert_eq!(DhcpConfig::is_ip_in_range(&ip, range.clone()), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -320,11 +320,9 @@ pub struct NumberOption {
|
|||||||
item: MaybeString,
|
item: MaybeString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, Clone, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Range {
|
pub struct Range {
|
||||||
#[yaserde(rename = "from")]
|
|
||||||
pub from: String,
|
pub from: String,
|
||||||
#[yaserde(rename = "to")]
|
|
||||||
pub to: String,
|
pub to: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user