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
103
src/lib.rs
103
src/lib.rs
@ -26,7 +26,13 @@ pub struct Network {
|
||||
network_address: IpAddr,
|
||||
broadcast_addr: IpAddr,
|
||||
num_hosts: u32,
|
||||
subnet_mask: Option<IpAddr>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
pub struct Subnet {
|
||||
pub networks: Vec<Network>,
|
||||
pub subnet_mask: IpAddr,
|
||||
}
|
||||
|
||||
impl Network {
|
||||
@ -38,12 +44,11 @@ impl Network {
|
||||
/// //Awaiting implementation before creating doctest
|
||||
/// //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_address: given_address.clone(),
|
||||
broadcast_addr: given_address.clone(),
|
||||
num_hosts: 0,
|
||||
subnet_mask: Some(subnet_mask.clone())
|
||||
broadcast_addr: broadcast_address.clone(),
|
||||
num_hosts,
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,11 +58,11 @@ impl Network {
|
||||
/// use subnet_calculator::ip::IpAddr;
|
||||
/// 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.
|
||||
let network_class = Network::get_network_class(network_address)?;
|
||||
let network_address = network_address.to_arr()?;
|
||||
@ -65,9 +70,7 @@ impl Network {
|
||||
// If the CIDR < class network enum associated value, then there is an invalid subnet.
|
||||
if cidr < network_class as u8 {
|
||||
return Err(NetworkingErr::InvalidCIDRErr)
|
||||
}
|
||||
|
||||
let num_borrowed_bits = cidr - network_class as u8;
|
||||
}
|
||||
|
||||
// Determine the starting network
|
||||
let mut base_network = network_address.clone();
|
||||
@ -75,35 +78,49 @@ impl Network {
|
||||
NetworkClass::A => 1,
|
||||
NetworkClass::B => 2,
|
||||
NetworkClass::C => 3
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
for i in most_sig_octet..4 {
|
||||
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
|
||||
// We know that this value is >0 at this point
|
||||
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
|
||||
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
|
||||
//If there is only 1 network, returning the base network will be sufficient
|
||||
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 {
|
||||
//Increment address and append to list
|
||||
base_address += addr_increment;
|
||||
networks.push(IpAddr::from(base_address));
|
||||
base_addr += addr_increment;
|
||||
// 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.
|
||||
@ -206,6 +223,19 @@ pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip:
|
||||
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 {
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
@ -253,26 +283,33 @@ mod tests {
|
||||
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();
|
||||
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.last().unwrap(), &IpAddr::V4(192, 168, 200, 254));
|
||||
|
||||
let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 8).unwrap();
|
||||
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().networks;
|
||||
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.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.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.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