parent
75f24cfe6c
commit
ad4bf96587
@ -0,0 +1,95 @@ |
|||||||
|
use std::net::{Ipv4Addr, Ipv6Addr}; |
||||||
|
|
||||||
|
#[derive(Clone, Debug)] |
||||||
|
pub struct Ipv4Net { |
||||||
|
pub addr: Ipv4Addr, |
||||||
|
pub prefix_len: u8, |
||||||
|
pub netmask: Ipv4Addr, |
||||||
|
} |
||||||
|
|
||||||
|
impl Ipv4Net { |
||||||
|
pub fn new(ipv4_addr: Ipv4Addr, prefix_len: u8) -> Ipv4Net { |
||||||
|
Ipv4Net { |
||||||
|
addr: ipv4_addr, |
||||||
|
prefix_len: prefix_len, |
||||||
|
netmask: prefix_to_ipv4_netmask(prefix_len), |
||||||
|
} |
||||||
|
} |
||||||
|
pub fn new_with_netmask(ipv4_addr: Ipv4Addr, netmask: Ipv4Addr) -> Ipv4Net { |
||||||
|
Ipv4Net { |
||||||
|
addr: ipv4_addr, |
||||||
|
prefix_len: ipv4_netmask_to_prefix(netmask), |
||||||
|
netmask: netmask, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Clone, Debug)] |
||||||
|
pub struct Ipv6Net { |
||||||
|
pub addr: Ipv6Addr, |
||||||
|
pub prefix_len: u8, |
||||||
|
pub netmask: Ipv6Addr, |
||||||
|
} |
||||||
|
|
||||||
|
impl Ipv6Net { |
||||||
|
pub fn new(ipv6_addr: Ipv6Addr, prefix_len: u8) -> Ipv6Net { |
||||||
|
Ipv6Net { |
||||||
|
addr: ipv6_addr, |
||||||
|
prefix_len: prefix_len, |
||||||
|
netmask: prefix_to_ipv6_netmask(prefix_len), |
||||||
|
} |
||||||
|
} |
||||||
|
pub fn new_with_netmask(ipv6_addr: Ipv6Addr, netmask: Ipv6Addr) -> Ipv6Net { |
||||||
|
Ipv6Net { |
||||||
|
addr: ipv6_addr, |
||||||
|
prefix_len: ipv6_netmask_to_prefix(netmask), |
||||||
|
netmask: netmask, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn ipv4_netmask_to_prefix(netmask: Ipv4Addr) -> u8 { |
||||||
|
let netmask = u32::from(netmask); |
||||||
|
let prefix = (!netmask).leading_zeros() as u8; |
||||||
|
if (u64::from(netmask) << prefix) & 0xffff_ffff != 0 { |
||||||
|
0 |
||||||
|
} else { |
||||||
|
prefix |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 { |
||||||
|
let netmask = netmask.segments(); |
||||||
|
let mut mask_iter = netmask.iter(); |
||||||
|
let mut prefix = 0; |
||||||
|
for &segment in &mut mask_iter { |
||||||
|
if segment == 0xffff { |
||||||
|
prefix += 16; |
||||||
|
} else if segment == 0 { |
||||||
|
break; |
||||||
|
} else { |
||||||
|
let prefix_bits = (!segment).leading_zeros() as u8; |
||||||
|
if segment << prefix_bits != 0 { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
prefix += prefix_bits; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
for &segment in mask_iter { |
||||||
|
if segment != 0 { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
prefix |
||||||
|
} |
||||||
|
|
||||||
|
fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr { |
||||||
|
let netmask_u32: u32 = u32::max_value().checked_shl(32 - prefix_len as u32).unwrap_or(0); |
||||||
|
Ipv4Addr::from(netmask_u32) |
||||||
|
} |
||||||
|
|
||||||
|
fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr { |
||||||
|
let netmask_u128: u128 = u128::max_value().checked_shl((128 - prefix_len) as u32).unwrap_or(u128::min_value()); |
||||||
|
Ipv6Addr::from(netmask_u128) |
||||||
|
} |
Loading…
Reference in new issue