use std::collections::HashSet;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use strum_macros::EnumString;
use crate::types::{RejectCode, SynProxyFlag};
use crate::visitor::deserialize_optional_flags;
use crate::expr::Expression;
use std::borrow::Cow;
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum Statement<'a> {
Accept(Option<Accept>),
Drop(Option<Drop>),
Continue(Option<Continue>),
Return(Option<Return>),
Jump(JumpTarget<'a>),
Goto(JumpTarget<'a>),
Match(Match<'a>),
Counter(Counter<'a>),
Mangle(Mangle<'a>),
Quota(QuotaOrQuotaRef<'a>),
Limit(Limit<'a>),
Flow(Flow<'a>),
FWD(Option<FWD<'a>>),
Notrack,
Dup(Dup<'a>),
SNAT(Option<NAT<'a>>),
DNAT(Option<NAT<'a>>),
Masquerade(Option<NAT<'a>>), Redirect(Option<NAT<'a>>), Reject(Option<Reject>),
Set(Set<'a>),
Log(Option<Log<'a>>),
#[serde(rename = "ct helper")]
CTHelper(Cow<'a, str>),
Meter(Meter<'a>),
Queue(Queue<'a>),
#[serde(rename = "vmap")]
VerdictMap(VerdictMap<'a>),
#[serde(rename = "ct count")]
CTCount(CTCount<'a>),
#[serde(rename = "ct timeout")]
CTTimeout(Expression<'a>),
#[serde(rename = "ct expectation")]
CTExpectation(Expression<'a>),
XT(Option<serde_json::Value>),
SynProxy(SynProxy),
TProxy(TProxy<'a>),
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Accept {}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Drop {}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Continue {}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Return {}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct JumpTarget<'a> {
pub target: Cow<'a, str>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Match<'a> {
pub left: Expression<'a>,
pub right: Expression<'a>,
pub op: Operator,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(untagged)]
pub enum Counter<'a> {
Named(Cow<'a, str>),
Anonymous(Option<AnonymousCounter>),
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AnonymousCounter {
#[serde(serialize_with = "crate::visitor::serialize_none_to_zero")]
pub packets: Option<usize>,
#[serde(serialize_with = "crate::visitor::serialize_none_to_zero")]
pub bytes: Option<usize>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Mangle<'a> {
pub key: Expression<'a>,
pub value: Expression<'a>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(untagged)]
pub enum QuotaOrQuotaRef<'a> {
Quota(Quota<'a>),
QuotaRef(Cow<'a, str>),
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Quota<'a> {
pub val: u32,
pub val_unit: Cow<'a, str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub used: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub used_unit: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub inv: Option<bool>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Limit<'a> {
pub rate: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub rate_unit: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub per: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub burst: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub burst_unit: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub inv: Option<bool>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Flow<'a> {
pub op: SetOp,
pub flowtable: Cow<'a, str>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct FWD<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub dev: Option<Expression<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub family: Option<FWDFamily>,
#[serde(skip_serializing_if = "Option::is_none")]
pub addr: Option<Expression<'a>>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum FWDFamily {
IP,
IP6,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Dup<'a> {
pub addr: Expression<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dev: Option<Expression<'a>>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NAT<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub addr: Option<Expression<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub family: Option<NATFamily>,
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<Expression<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<HashSet<NATFlag>>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum NATFamily {
IP,
IP6,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum NATFlag {
Random,
#[serde(rename = "fully-random")]
FullyRandom,
Persistent,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Reject {
#[serde(skip_serializing_if = "Option::is_none", rename = "type")]
pub _type: Option<RejectType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expr: Option<RejectCode>,
}
impl Reject {
pub fn new(_type: Option<RejectType>, code: Option<RejectCode>) -> Reject {
Reject { _type, expr: code }
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum RejectType {
#[serde(rename = "tcp reset")]
TCPReset,
ICMPX,
ICMP,
ICMPv6,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Set<'a> {
pub op: SetOp,
pub elem: Expression<'a>,
pub set: Cow<'a, str>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum SetOp {
Add,
Update,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Log<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub prefix: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub group: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub snaplen: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", rename = "queue-threshold")]
pub queue_threshold: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub level: Option<LogLevel>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_optional_flags"
)]
pub flags: Option<HashSet<LogFlag>>,
}
impl Log<'_> {
pub fn new(group: Option<u32>) -> Self {
Log {
prefix: None,
group,
snaplen: None,
queue_threshold: None,
level: None,
flags: None,
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Emerg,
Alert,
Crit,
Err,
Warn,
Notice,
Info,
Debug,
Audit,
}
#[derive(
Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, EnumString, JsonSchema,
)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum LogFlag {
#[serde(rename = "tcp sequence")]
TCPSequence,
#[serde(rename = "tcp options")]
TCPOptions,
#[serde(rename = "ip options")]
IPOptions,
Skuid,
Ether,
All,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Meter<'a> {
pub name: Cow<'a, str>,
pub key: Expression<'a>,
pub stmt: Box<Statement<'a>>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Queue<'a> {
pub num: Expression<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<HashSet<QueueFlag>>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum QueueFlag {
Bypass,
Fanout,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename = "vmap")]
pub struct VerdictMap<'a> {
pub key: Expression<'a>,
pub data: Expression<'a>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename = "ct count")]
pub struct CTCount<'a> {
pub val: Expression<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub inv: Option<bool>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct SynProxy {
#[serde(skip_serializing_if = "Option::is_none")]
pub mss: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wscale: Option<u32>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_optional_flags",
default
)]
pub flags: Option<HashSet<SynProxyFlag>>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub struct TProxy<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub family: Option<Cow<'a, str>>,
pub port: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub addr: Option<Cow<'a, str>>,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
pub enum Operator {
#[serde(rename = "&")]
AND,
#[serde(rename = "|")]
OR,
#[serde(rename = "^")]
XOR,
#[serde(rename = "<<")]
LSHIFT,
#[serde(rename = ">>")]
RSHIFT,
#[serde(rename = "==")]
EQ,
#[serde(rename = "!=")]
NEQ,
#[serde(rename = ">")]
LT,
#[serde(rename = "<")]
GT,
#[serde(rename = "<=")]
LEQ,
#[serde(rename = ">=")]
GEQ,
#[serde(rename = "in")]
IN,
}