///|
pub struct ScopeCount {
scope : Ipv4Scope
count : Int
} derive(Eq, Debug)
///|
pub struct NetworkHit {
network : Ipv4Network
count : Int
} derive(Eq, Debug)
///|
pub struct AddressScanReport {
total : Int
allowed : Int
denied : Int
scope_counts : Array[ScopeCount]
network_hits : Array[NetworkHit]
unmatched : Array[Ipv4Address]
} derive(Debug)
///|
pub fn ScopeCount::scope(self : ScopeCount) -> Ipv4Scope {
self.scope
}
///|
pub fn ScopeCount::count(self : ScopeCount) -> Int {
self.count
}
///|
pub fn ScopeCount::to_string(self : ScopeCount) -> String {
"\{self.scope.to_string()}=\{self.count}"
}
///|
pub fn NetworkHit::network(self : NetworkHit) -> Ipv4Network {
self.network
}
///|
pub fn NetworkHit::count(self : NetworkHit) -> Int {
self.count
}
///|
pub fn NetworkHit::to_string(self : NetworkHit) -> String {
"\{self.network.to_string()}=\{self.count}"
}
///|
pub fn AddressScanReport::total(self : AddressScanReport) -> Int {
self.total
}
///|
pub fn AddressScanReport::allowed(self : AddressScanReport) -> Int {
self.allowed
}
///|
pub fn AddressScanReport::denied(self : AddressScanReport) -> Int {
self.denied
}
///|
pub fn AddressScanReport::scope_counts(
self : AddressScanReport,
) -> Array[ScopeCount] {
self.scope_counts.copy()
}
///|
pub fn AddressScanReport::network_hits(
self : AddressScanReport,
) -> Array[NetworkHit] {
self.network_hits.copy()
}
///|
pub fn AddressScanReport::unmatched(
self : AddressScanReport,
) -> Array[Ipv4Address] {
self.unmatched.copy()
}
///|
pub fn AddressScanReport::to_string(self : AddressScanReport) -> String {
let mut text = "total=\{self.total}, allowed=\{self.allowed}, denied=\{self.denied}"
text = text + "\nscopes: " + join_scope_counts(self.scope_counts)
text = text + "\nnetworks: " + join_network_hits(self.network_hits)
text = text + "\nunmatched: " + join_addresses(self.unmatched)
text
}
///|
pub fn scan_addresses(
addresses : Array[Ipv4Address],
policy : AclPolicy,
networks : Ipv4NetworkSet,
) -> AddressScanReport {
let scope_counts = Array::new()
let network_hits = Array::new()
let unmatched = Array::new()
let mut allowed = 0
let mut denied = 0
for address in addresses {
if policy.allows(address) {
allowed = allowed + 1
} else {
denied = denied + 1
}
add_scope_count(scope_counts, address.scope())
match networks.match_network(address) {
Some(network) => add_network_hit(network_hits, network)
None => unmatched.push(address)
}
}
sort_scope_counts(scope_counts)
sort_network_hits(network_hits)
{
total: addresses.length(),
allowed,
denied,
scope_counts,
network_hits,
unmatched,
}
}
///|
pub fn parse_ipv4_addresses(
items : Array[String],
) -> Result[Array[Ipv4Address], CidrError] {
let addresses = Array::new()
for item in items {
match Ipv4Address::parse(item) {
Err(error) => return Err(error)
Ok(address) => addresses.push(address)
}
}
Ok(addresses)
}
///|
pub fn filter_by_scope(
addresses : Array[Ipv4Address],
scope : Ipv4Scope,
) -> Array[Ipv4Address] {
let result = Array::new()
for address in addresses {
if address.scope() == scope {
result.push(address)
}
}
result
}
///|
pub fn filter_matching_set(
addresses : Array[Ipv4Address],
networks : Ipv4NetworkSet,
) -> Array[Ipv4Address] {
let result = Array::new()
for address in addresses {
if networks.contains(address) {
result.push(address)
}
}
result
}
///|
pub fn filter_not_matching_set(
addresses : Array[Ipv4Address],
networks : Ipv4NetworkSet,
) -> Array[Ipv4Address] {
let result = Array::new()
for address in addresses {
if !networks.contains(address) {
result.push(address)
}
}
result
}
///|
pub fn summarize_addresses(addresses : Array[Ipv4Address]) -> Ipv4Summary {
Ipv4Summary::from_addresses(addresses)
}
///|
fn add_scope_count(counts : Array[ScopeCount], scope : Ipv4Scope) -> Unit {
let mut index = 0
while index < counts.length() {
if counts[index].scope == scope {
counts[index] = { scope, count: counts[index].count + 1 }
return
}
index = index + 1
}
counts.push({ scope, count: 1 })
}
///|
fn add_network_hit(hits : Array[NetworkHit], network : Ipv4Network) -> Unit {
let mut index = 0
while index < hits.length() {
if hits[index].network == network {
hits[index] = { network, count: hits[index].count + 1 }
return
}
index = index + 1
}
hits.push({ network, count: 1 })
}
///|
fn sort_scope_counts(counts : Array[ScopeCount]) -> Unit {
let mut i = 0
while i < counts.length() {
let mut j = i + 1
while j < counts.length() {
if counts[i].scope.to_string() > counts[j].scope.to_string() {
let tmp = counts[i]
counts[i] = counts[j]
counts[j] = tmp
}
j = j + 1
}
i = i + 1
}
}
///|
fn sort_network_hits(hits : Array[NetworkHit]) -> Unit {
let mut i = 0
while i < hits.length() {
let mut j = i + 1
while j < hits.length() {
if hits[i].network.address().to_uint() >
hits[j].network.address().to_uint() {
let tmp = hits[i]
hits[i] = hits[j]
hits[j] = tmp
}
j = j + 1
}
i = i + 1
}
}
///|
fn join_scope_counts(counts : Array[ScopeCount]) -> String {
let mut text = ""
let mut index = 0
for item in counts {
if index > 0 {
text = text + ", "
}
text = text + item.to_string()
index = index + 1
}
text
}
///|
fn join_network_hits(hits : Array[NetworkHit]) -> String {
let mut text = ""
let mut index = 0
for item in hits {
if index > 0 {
text = text + ", "
}
text = text + item.to_string()
index = index + 1
}
text
}
///|
fn join_addresses(addresses : Array[Ipv4Address]) -> String {
let mut text = ""
let mut index = 0
for address in addresses {
if index > 0 {
text = text + ", "
}
text = text + address.to_string()
index = index + 1
}
text
}