Added ability to create full networks, including the number of hosts on each as well as the broadcast address for each given network
This commit is contained in:
parent
108f8f2ab4
commit
f224cf4c29
95
src/lib.rs
95
src/lib.rs
@ -26,7 +26,13 @@ pub struct Network {
|
|||||||
network_address: IpAddr,
|
network_address: IpAddr,
|
||||||
broadcast_addr: IpAddr,
|
broadcast_addr: IpAddr,
|
||||||
num_hosts: u32,
|
num_hosts: u32,
|
||||||
subnet_mask: Option<IpAddr>
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(unused)]
|
||||||
|
pub struct Subnet {
|
||||||
|
pub networks: Vec<Network>,
|
||||||
|
pub subnet_mask: IpAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
@ -38,12 +44,11 @@ impl Network {
|
|||||||
/// //Awaiting implementation before creating doctest
|
/// //Awaiting implementation before creating doctest
|
||||||
/// //let network = Network::new(&IpAddr::V4(127, 0, 0, 1), 32);
|
/// //let network = Network::new(&IpAddr::V4(127, 0, 0, 1), 32);
|
||||||
/// ```
|
/// ```
|
||||||
fn new(given_address: &IpAddr, subnet_mask: &IpAddr) -> Network {
|
fn new(given_address: &IpAddr, broadcast_address: &IpAddr, num_hosts: u32) -> Network {
|
||||||
Network {
|
Network {
|
||||||
network_address: given_address.clone(),
|
network_address: given_address.clone(),
|
||||||
broadcast_addr: given_address.clone(),
|
broadcast_addr: broadcast_address.clone(),
|
||||||
num_hosts: 0,
|
num_hosts,
|
||||||
subnet_mask: Some(subnet_mask.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,11 +58,11 @@ impl Network {
|
|||||||
/// use subnet_calculator::ip::IpAddr;
|
/// use subnet_calculator::ip::IpAddr;
|
||||||
/// use subnet_calculator::Network;
|
/// use subnet_calculator::Network;
|
||||||
///
|
///
|
||||||
/// let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 16).unwrap();
|
/// let subnets = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 16).unwrap();
|
||||||
///
|
///
|
||||||
/// assert_eq!(networks.len(), 256);
|
/// assert_eq!(subnets.networks.len(), 256);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn create_subnet(network_address: &IpAddr, cidr: u8) -> Result<Vec<IpAddr>, NetworkingErr> {
|
pub fn create_subnet(network_address: &IpAddr, cidr: u8) -> Result<Subnet, NetworkingErr> {
|
||||||
//Get number of host and network bits.
|
//Get number of host and network bits.
|
||||||
let network_class = Network::get_network_class(network_address)?;
|
let network_class = Network::get_network_class(network_address)?;
|
||||||
let network_address = network_address.to_arr()?;
|
let network_address = network_address.to_arr()?;
|
||||||
@ -67,8 +72,6 @@ impl Network {
|
|||||||
return Err(NetworkingErr::InvalidCIDRErr)
|
return Err(NetworkingErr::InvalidCIDRErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_borrowed_bits = cidr - network_class as u8;
|
|
||||||
|
|
||||||
// Determine the starting network
|
// Determine the starting network
|
||||||
let mut base_network = network_address.clone();
|
let mut base_network = network_address.clone();
|
||||||
let most_sig_octet: u8 = match network_class {
|
let most_sig_octet: u8 = match network_class {
|
||||||
@ -81,29 +84,43 @@ impl Network {
|
|||||||
base_network[i as usize] = 0;
|
base_network[i as usize] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove trailing values from the base network
|
||||||
|
let num_borrowed_bits = cidr - network_class as u8;
|
||||||
|
|
||||||
|
// Get the base network and next added address as u32's
|
||||||
|
let mut base_addr = u32::from(IpAddr::from_arr(&base_network)?);
|
||||||
|
let subnet_mask = u32::from(Network::gen_subnet_mask(cidr)?);
|
||||||
|
let addr_increment = u32::pow(2, subnet_mask.trailing_zeros());
|
||||||
|
|
||||||
|
// The number of hosts per network can be determined using the number of remaining
|
||||||
|
// bits raised to the second power.
|
||||||
|
let num_hosts = u32::pow(2, (32 - network_class as u8 - num_borrowed_bits) as u32);
|
||||||
|
|
||||||
// Determine how many networks are available
|
// Determine how many networks are available
|
||||||
// We know that this value is >0 at this point
|
// We know that this value is >0 at this point
|
||||||
let num_networks = u32::pow(2, num_borrowed_bits as u32);
|
let num_networks = u32::pow(2, num_borrowed_bits as u32);
|
||||||
|
|
||||||
|
// The broadcast address will always be 1 less than the next subnet network address
|
||||||
|
let mut broadcast_addr = (base_addr + addr_increment) - 1;
|
||||||
|
|
||||||
//Create the subnets
|
//Create the subnets
|
||||||
let mut networks = vec![IpAddr::from_arr(&base_network)?];
|
let mut subnet = Subnet::new(&IpAddr::from(base_addr), &IpAddr::from(broadcast_addr), num_hosts, cidr)?;
|
||||||
|
|
||||||
// Determine the networking gaps
|
// Determine the networking gaps
|
||||||
//If there is only 1 network, returning the base network will be sufficient
|
//If there is only 1 network, returning the base network will be sufficient
|
||||||
if num_networks > 1 {
|
if num_networks > 1 {
|
||||||
//Get the base network and next added address as u32's
|
|
||||||
let mut base_address = u32::from(IpAddr::from_arr(&base_network)?);
|
|
||||||
let subnet_mask = u32::from(Network::gen_subnet_mask(cidr)?);
|
|
||||||
let addr_increment = u32::pow(2, subnet_mask.trailing_zeros());
|
|
||||||
|
|
||||||
for _ in 0..num_networks-1 {
|
for _ in 0..num_networks-1 {
|
||||||
//Increment address and append to list
|
//Increment address and append to list
|
||||||
base_address += addr_increment;
|
base_addr += addr_increment;
|
||||||
networks.push(IpAddr::from(base_address));
|
// We can start adding the full subnet range now instead of 1 less
|
||||||
|
broadcast_addr += addr_increment;
|
||||||
|
|
||||||
|
subnet.networks.push(Network::new(&IpAddr::from(base_addr), &IpAddr::from(broadcast_addr), num_hosts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(networks)
|
Ok(subnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function that is used to determine the class of network that an IP is in.
|
/// Function that is used to determine the class of network that an IP is in.
|
||||||
@ -206,6 +223,19 @@ pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip:
|
|||||||
return Ok((ip_address, cidr))
|
return Ok((ip_address, cidr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Subnet {
|
||||||
|
/// Function to return a new subbet struct
|
||||||
|
///
|
||||||
|
fn new(base_address: &IpAddr, broadcast_addr: &IpAddr, num_hosts: u32, cidr: u8) -> Result<Subnet, NetworkingErr> {
|
||||||
|
Ok(
|
||||||
|
Subnet {
|
||||||
|
networks: vec![Network::new(base_address, broadcast_addr, num_hosts)],
|
||||||
|
subnet_mask: Network::gen_subnet_mask(cidr)?,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
@ -253,26 +283,33 @@ mod tests {
|
|||||||
assert_eq!(Network::create_subnet(&IpAddr::V4(192, 168, 0, 1), 23).unwrap_err(), NetworkingErr::InvalidCIDRErr);
|
assert_eq!(Network::create_subnet(&IpAddr::V4(192, 168, 0, 1), 23).unwrap_err(), NetworkingErr::InvalidCIDRErr);
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 10).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 10).unwrap();
|
||||||
assert_eq!(networks.len(), 4);
|
assert_eq!(networks.networks.len(), 4);
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(192, 168, 200, 1), 31).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(192, 168, 200, 1), 31).unwrap().networks;
|
||||||
assert_eq!(networks.len(), 128);
|
assert_eq!(networks.len(), 128);
|
||||||
assert_eq!(networks.last().unwrap(), &IpAddr::V4(192, 168, 200, 254));
|
assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(192, 168, 200, 254));
|
||||||
|
assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(192, 168, 200, 255));
|
||||||
|
assert_eq!(networks.last().unwrap().num_hosts, 2);
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 8).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 8).unwrap().networks;
|
||||||
assert_eq!(networks.len(), 1);
|
assert_eq!(networks.len(), 1);
|
||||||
assert_eq!(networks.last().unwrap(), &IpAddr::V4(127, 0, 0, 0));
|
assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(127, 0, 0, 0));
|
||||||
|
assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(127, 255, 255, 255));
|
||||||
|
assert_eq!(networks.last().unwrap().num_hosts, 16_777_216);
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 9).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 9).unwrap().networks;
|
||||||
assert_eq!(networks.len(), 2);
|
assert_eq!(networks.len(), 2);
|
||||||
assert_eq!(networks.first().unwrap(), &IpAddr::V4(127, 0, 0, 0));
|
assert_eq!(networks.first().unwrap().network_address, IpAddr::V4(127, 0, 0, 0));
|
||||||
|
assert_eq!(networks.first().unwrap().broadcast_addr, IpAddr::V4(127, 127, 255, 255));
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(168, 20, 0, 0), 17).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(168, 20, 0, 0), 17).unwrap().networks;
|
||||||
assert_eq!(networks.len(), 2);
|
assert_eq!(networks.len(), 2);
|
||||||
assert_eq!(networks.last().unwrap(), &IpAddr::V4(168, 20, 128, 0));
|
assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(168, 20, 128, 0));
|
||||||
|
assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(168, 20, 255, 255));
|
||||||
|
assert_eq!(networks.last().unwrap().num_hosts, 32_768);
|
||||||
|
|
||||||
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 17).unwrap();
|
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 17).unwrap().networks;
|
||||||
assert_eq!(networks.len(), 512);
|
assert_eq!(networks.len(), 512);
|
||||||
assert_eq!(networks.last().unwrap(), &IpAddr::V4(127, 255, 128, 0));
|
assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(127, 255, 128, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user