fork of https://github.com/shellrow/default-net/tree/v0.16.2
fixes an unsafe bug in sockaddr_to_network_addr
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.0 KiB
111 lines
3.0 KiB
use std::net::{Ipv4Addr, Ipv6Addr};
|
|
|
|
/// Structure of IPv4 Network
|
|
#[derive(Clone, Debug)]
|
|
pub struct Ipv4Net {
|
|
/// IPv4 Address
|
|
pub addr: Ipv4Addr,
|
|
/// Prefix Length
|
|
pub prefix_len: u8,
|
|
/// Network Mask
|
|
pub netmask: Ipv4Addr,
|
|
}
|
|
|
|
impl Ipv4Net {
|
|
/// Construct a new Ipv4Net instance from IPv4 Address and Prefix Length
|
|
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),
|
|
}
|
|
}
|
|
/// Construct a new Ipv4Net instance from IPv4 Address and Network Mask
|
|
pub fn new_with_netmask(ipv4_addr: Ipv4Addr, netmask: Ipv4Addr) -> Ipv4Net {
|
|
Ipv4Net {
|
|
addr: ipv4_addr,
|
|
prefix_len: ipv4_netmask_to_prefix(netmask),
|
|
netmask: netmask,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Structure of IPv6 Network
|
|
#[derive(Clone, Debug)]
|
|
pub struct Ipv6Net {
|
|
/// IPv6 Address
|
|
pub addr: Ipv6Addr,
|
|
/// Prefix Length
|
|
pub prefix_len: u8,
|
|
/// Network Mask
|
|
pub netmask: Ipv6Addr,
|
|
}
|
|
|
|
impl Ipv6Net {
|
|
/// Construct a new Ipv6Net instance from IPv6 Address and Prefix Length
|
|
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),
|
|
}
|
|
}
|
|
/// Construct a new Ipv6Net instance from IPv6 Address and Network Mask
|
|
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)
|
|
}
|
|
|