///|
pub enum DiagnosticSeverity {
Info
Warning
Error
} derive(Eq, Debug)
///|
pub enum DiagnosticKind {
DuplicateNetwork
CoveredNetwork
OverlappingNetwork
SpecialPurposeAddress
EmptyPolicy
} derive(Eq, Debug)
///|
pub struct CidrDiagnostic {
severity : DiagnosticSeverity
kind : DiagnosticKind
message : String
} derive(Eq, Debug)
///|
pub struct DiagnosticReport {
diagnostics : Array[CidrDiagnostic]
} derive(Debug)
///|
pub fn DiagnosticSeverity::to_string(self : DiagnosticSeverity) -> String {
match self {
Info => "info"
Warning => "warning"
Error => "error"
}
}
///|
pub fn DiagnosticKind::to_string(self : DiagnosticKind) -> String {
match self {
DuplicateNetwork => "duplicate-network"
CoveredNetwork => "covered-network"
OverlappingNetwork => "overlapping-network"
SpecialPurposeAddress => "special-purpose-address"
EmptyPolicy => "empty-policy"
}
}
///|
pub fn CidrDiagnostic::new(
severity : DiagnosticSeverity,
kind : DiagnosticKind,
message : String,
) -> CidrDiagnostic {
{ severity, kind, message }
}
///|
pub fn CidrDiagnostic::to_string(self : CidrDiagnostic) -> String {
"[\{self.severity.to_string()}] \{self.kind.to_string()}: \{self.message}"
}
///|
pub fn DiagnosticReport::new() -> DiagnosticReport {
{ diagnostics: Array::new() }
}
///|
pub fn DiagnosticReport::push(
self : DiagnosticReport,
diagnostic : CidrDiagnostic,
) -> DiagnosticReport {
let diagnostics = self.diagnostics.copy()
diagnostics.push(diagnostic)
{ diagnostics, }
}
///|
pub fn DiagnosticReport::len(self : DiagnosticReport) -> Int {
self.diagnostics.length()
}
///|
pub fn DiagnosticReport::is_empty(self : DiagnosticReport) -> Bool {
self.len() == 0
}
///|
pub fn DiagnosticReport::diagnostics(
self : DiagnosticReport,
) -> Array[CidrDiagnostic] {
self.diagnostics.copy()
}
///|
pub fn DiagnosticReport::error_count(self : DiagnosticReport) -> Int {
count_severity(self.diagnostics, Error)
}
///|
pub fn DiagnosticReport::warning_count(self : DiagnosticReport) -> Int {
count_severity(self.diagnostics, Warning)
}
///|
pub fn DiagnosticReport::info_count(self : DiagnosticReport) -> Int {
count_severity(self.diagnostics, Info)
}
///|
pub fn DiagnosticReport::to_string(self : DiagnosticReport) -> String {
if self.diagnostics.length() == 0 {
"no diagnostics"
} else {
let mut text = ""
let mut index = 0
for diagnostic in self.diagnostics {
if index > 0 {
text = text + "\n"
}
text = text + diagnostic.to_string()
index = index + 1
}
text
}
}
///|
pub fn diagnose_networks(networks : Array[Ipv4Network]) -> DiagnosticReport {
let mut report = DiagnosticReport::new()
let mut i = 0
while i < networks.length() {
let mut j = i + 1
while j < networks.length() {
if networks[i] == networks[j] {
report = report.push(
CidrDiagnostic::new(
Warning,
DuplicateNetwork,
"duplicate \{networks[i].to_string()}",
),
)
} else if networks[i].contains_network(networks[j]) {
report = report.push(
CidrDiagnostic::new(
Info,
CoveredNetwork,
"\{networks[j].to_string()} is covered by \{networks[i].to_string()}",
),
)
} else if networks[j].contains_network(networks[i]) {
report = report.push(
CidrDiagnostic::new(
Info,
CoveredNetwork,
"\{networks[i].to_string()} is covered by \{networks[j].to_string()}",
),
)
} else if networks[i].overlaps(networks[j]) {
report = report.push(
CidrDiagnostic::new(
Warning,
OverlappingNetwork,
"\{networks[i].to_string()} overlaps \{networks[j].to_string()}",
),
)
}
j = j + 1
}
i = i + 1
}
report
}
///|
pub fn diagnose_addresses(addresses : Array[Ipv4Address]) -> DiagnosticReport {
let mut report = DiagnosticReport::new()
for address in addresses {
if address.is_special_purpose() {
report = report.push(
CidrDiagnostic::new(
Info,
SpecialPurposeAddress,
"\{address.to_string()} is \{address.scope().to_string()}",
),
)
}
}
report
}
///|
pub fn diagnose_acl(policy : AclPolicy) -> DiagnosticReport {
let mut report = DiagnosticReport::new()
if policy.len() == 0 {
report = report.push(
CidrDiagnostic::new(Warning, EmptyPolicy, "policy has no explicit rules"),
)
}
report
}
///|
fn count_severity(
items : Array[CidrDiagnostic],
severity : DiagnosticSeverity,
) -> Int {
let mut count = 0
for item in items {
if item.severity == severity {
count = count + 1
}
}
count
}