///|
pub(all) enum Action {
Allow
Deny
} derive(Eq, Debug)
///|
pub(all) enum Protocol {
Tcp
Udp
} derive(Eq, Debug)
///|
pub struct Packet {
source : @cidr.IPv4
destination : @cidr.IPv4
protocol : Protocol
source_port : Int
destination_port : Int
} derive(Eq, Debug)
///|
pub fn Packet::new(
source : String,
destination : String,
protocol : Protocol,
source_port : Int,
destination_port : Int,
) -> Packet raise PolicyError {
if source.length() > 15 || destination.length() > 15 {
raise Invalid("IPv4 text too long")
}
let source = match @cidr.IPv4::parse(source) {
Ok(x) => x
Err(e) => raise Invalid(e)
}
let destination = match @cidr.IPv4::parse(destination) {
Ok(x) => x
Err(e) => raise Invalid(e)
}
ignore(Ports::new(source_port, source_port))
ignore(Ports::new(destination_port, destination_port))
{ source, destination, protocol, source_port, destination_port }
}
///|
pub fn Packet::fields(self : Packet) -> (String, String, Protocol, Int, Int) {
(
self.source.to_dotted(),
self.destination.to_dotted(),
self.protocol,
self.source_port,
self.destination_port,
)
}
///|
pub struct Rule {
id : String
action : Action
protocol : Protocol?
source : @cidr.CidrBlock
destination : @cidr.CidrBlock
source_ports : Ports
destination_ports : Ports
} derive(Eq, Debug)
///|
pub fn Rule::new(
id : String,
action : Action,
protocol : Protocol?,
source : String,
destination : String,
source_ports : Ports,
destination_ports : Ports,
) -> Rule raise PolicyError {
if id.length() == 0 || id.length() > 64 {
raise Invalid("rule id must contain 1..64 characters")
}
for c in id.iter() {
if !((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_' ||
c == '-') {
raise Invalid("rule id must be ASCII alphanumeric, _ or -")
}
}
if source.length() > 18 || destination.length() > 18 {
raise Invalid("CIDR text too long")
}
{
id,
action,
protocol,
source: cidr_value(source),
destination: cidr_value(destination),
source_ports,
destination_ports,
}
}
///|
pub fn Rule::name(self : Rule) -> String {
self.id
}
///|
pub struct Policy {
priv rules : Array[Rule]
default_action : Action
} derive(Eq, Debug)
///|
pub fn Policy::new(
rules : Array[Rule],
default_action : Action,
) -> Policy raise PolicyError {
if rules.length() > 256 {
raise Invalid("at most 256 rules")
}
let seen : Map[String, Bool] = Map([])
for rule in rules {
if seen.contains(rule.id) {
raise Invalid("duplicate rule id: " + rule.id)
}
seen[rule.id] = true
}
{ rules: rules.copy(), default_action }
}
///|
pub fn Policy::rule_count(self : Policy) -> Int {
self.rules.length()
}