///|
pub enum AclDecision {
Allow
Deny
} derive(Eq, Debug)
///|
pub enum AclTarget {
Network(Ipv4Network)
Range(Ipv4Range)
Address(Ipv4Address)
} derive(Eq, Debug)
///|
pub struct AclRule {
name : String
decision : AclDecision
target : AclTarget
} derive(Eq, Debug)
///|
pub struct AclPolicy {
rules : Array[AclRule]
default_decision : AclDecision
} derive(Debug)
///|
pub struct AclEvaluation {
address : Ipv4Address
decision : AclDecision
matched_rule : String?
} derive(Eq, Debug)
///|
pub fn AclDecision::to_string(self : AclDecision) -> String {
match self {
Allow => "allow"
Deny => "deny"
}
}
///|
pub fn AclDecision::allow() -> AclDecision {
Allow
}
///|
pub fn AclDecision::deny() -> AclDecision {
Deny
}
///|
pub fn AclTarget::matches(self : AclTarget, address : Ipv4Address) -> Bool {
match self {
Network(network) => network.contains(address)
Range(range) => range.contains(address)
Address(exact) => exact == address
}
}
///|
pub fn AclTarget::to_string(self : AclTarget) -> String {
match self {
Network(network) => network.to_string()
Range(range) => range.to_string()
Address(address) => address.to_string()
}
}
///|
pub fn AclRule::network(
name : String,
decision : AclDecision,
network : Ipv4Network,
) -> AclRule {
{ name, decision, target: Network(network) }
}
///|
pub fn AclRule::range(
name : String,
decision : AclDecision,
range : Ipv4Range,
) -> AclRule {
{ name, decision, target: Range(range) }
}
///|
pub fn AclRule::address(
name : String,
decision : AclDecision,
address : Ipv4Address,
) -> AclRule {
{ name, decision, target: Address(address) }
}
///|
pub fn AclRule::name(self : AclRule) -> String {
self.name
}
///|
pub fn AclRule::decision(self : AclRule) -> AclDecision {
self.decision
}
///|
pub fn AclRule::target(self : AclRule) -> AclTarget {
self.target
}
///|
pub fn AclRule::matches(self : AclRule, address : Ipv4Address) -> Bool {
self.target.matches(address)
}
///|
pub fn AclRule::explain(self : AclRule) -> String {
"\{self.decision.to_string()} \{self.target.to_string()} by \{self.name}"
}
///|
pub fn AclPolicy::new(default_decision : AclDecision) -> AclPolicy {
{ rules: Array::new(), default_decision }
}
///|
pub fn AclPolicy::allow_by_default() -> AclPolicy {
AclPolicy::new(Allow)
}
///|
pub fn AclPolicy::deny_by_default() -> AclPolicy {
AclPolicy::new(Deny)
}
///|
pub fn AclPolicy::push(self : AclPolicy, rule : AclRule) -> AclPolicy {
let rules = self.rules.copy()
rules.push(rule)
{ rules, default_decision: self.default_decision }
}
///|
pub fn AclPolicy::allow_network(
self : AclPolicy,
name : String,
network : Ipv4Network,
) -> AclPolicy {
self.push(AclRule::network(name, Allow, network))
}
///|
pub fn AclPolicy::deny_network(
self : AclPolicy,
name : String,
network : Ipv4Network,
) -> AclPolicy {
self.push(AclRule::network(name, Deny, network))
}
///|
pub fn AclPolicy::allow_range(
self : AclPolicy,
name : String,
range : Ipv4Range,
) -> AclPolicy {
self.push(AclRule::range(name, Allow, range))
}
///|
pub fn AclPolicy::deny_range(
self : AclPolicy,
name : String,
range : Ipv4Range,
) -> AclPolicy {
self.push(AclRule::range(name, Deny, range))
}
///|
pub fn AclPolicy::allow_address(
self : AclPolicy,
name : String,
address : Ipv4Address,
) -> AclPolicy {
self.push(AclRule::address(name, Allow, address))
}
///|
pub fn AclPolicy::deny_address(
self : AclPolicy,
name : String,
address : Ipv4Address,
) -> AclPolicy {
self.push(AclRule::address(name, Deny, address))
}
///|
pub fn AclPolicy::len(self : AclPolicy) -> Int {
self.rules.length()
}
///|
pub fn AclPolicy::evaluate(
self : AclPolicy,
address : Ipv4Address,
) -> AclEvaluation {
let mut index = 0
while index < self.rules.length() {
let rule = self.rules[index]
if rule.matches(address) {
return { address, decision: rule.decision, matched_rule: Some(rule.name) }
}
index = index + 1
}
{ address, decision: self.default_decision, matched_rule: None }
}
///|
pub fn AclPolicy::allows(self : AclPolicy, address : Ipv4Address) -> Bool {
self.evaluate(address).decision == Allow
}
///|
pub fn AclEvaluation::to_string(self : AclEvaluation) -> String {
match self.matched_rule {
Some(name) =>
"\{self.address.to_string()} => \{self.decision.to_string()} by \{name}"
None =>
"\{self.address.to_string()} => \{self.decision.to_string()} by default"
}
}