nftables_json/
expression.rs

1// Copyright (c) nftables-json Developers
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Provides types related to specifying a rule's match criteria
5
6#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
7#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
8#[serde(deny_unknown_fields, rename_all = "kebab-case")]
9pub enum Binary {
10    #[serde(rename = "|")]
11    Or((Box<Expression>, Box<Expression>)),
12    #[serde(rename = "^")]
13    Not((Box<Expression>, Box<Expression>)),
14    #[serde(rename = "&")]
15    And((Box<Expression>, Box<Expression>)),
16    #[serde(rename = "<<")]
17    LShift((Box<Expression>, Box<Expression>)),
18    #[serde(rename = ">>")]
19    RShift((Box<Expression>, Box<Expression>)),
20}
21
22#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
23#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
24#[serde(deny_unknown_fields)]
25pub struct Ct {
26    pub key: String,
27    pub dir: Option<String>,
28}
29
30#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
31#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
32#[serde(deny_unknown_fields)]
33pub struct Elem {
34    pub val: Box<Expression>,
35    pub timeout: Option<isize>,
36    pub expires: Option<isize>,
37    pub comment: Option<String>,
38}
39
40#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
41#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
42#[serde(deny_unknown_fields)]
43pub struct Exthdr {
44    pub name: String,
45    pub field: Option<String>,
46    pub offset: Option<isize>,
47}
48
49#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
50#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
51#[serde(deny_unknown_fields)]
52pub struct Fib {
53    pub result: String,
54    #[serde(with = "serde_with::As::<Option<serde_with::OneOrMany<serde_with::Same>>>")]
55    pub flags: Option<Vec<String>>,
56}
57
58#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
59#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
60#[serde(deny_unknown_fields, rename_all = "kebab-case")]
61#[non_exhaustive]
62pub enum Hash {
63    Jhash {
64        #[serde(rename = "mod")]
65        r#mod: isize,
66        offset: Option<isize>,
67        expr: Box<Expression>,
68        seed: Option<isize>,
69    },
70    Symhash {
71        #[serde(rename = "mod")]
72        r#mod: isize,
73        offset: Option<isize>,
74    },
75}
76
77#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
78#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
79#[serde(deny_unknown_fields, untagged)]
80pub enum Immediate {
81    String(String),
82    Number(isize),
83    Boolean(bool),
84}
85
86#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
87#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
88#[serde(deny_unknown_fields)]
89pub struct IpOption {
90    pub name: String,
91    pub field: Option<String>,
92}
93
94#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
95#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
96#[serde(deny_unknown_fields)]
97pub struct Xfrm {
98    pub key: String,
99    pub family: Option<String>,
100    pub dir: Option<String>,
101    pub spnum: Option<isize>,
102}
103
104#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
105#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
106#[serde(deny_unknown_fields)]
107pub struct Map {
108    pub key: Box<Expression>,
109    pub data: Box<Expression>,
110}
111
112#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
113#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
114#[serde(deny_unknown_fields)]
115pub struct Meta {
116    pub key: String,
117}
118
119#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
120#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
121#[serde(deny_unknown_fields)]
122pub struct Numgen {
123    pub mode: String,
124    #[serde(rename = "mod")]
125    pub r#mod: isize,
126    pub offset: Option<isize>,
127}
128
129#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
130#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
131#[serde(deny_unknown_fields)]
132pub struct Osf {
133    pub key: String,
134    pub ttl: Option<String>,
135}
136
137#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
138#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
139#[serde(deny_unknown_fields, untagged)]
140pub enum Payload {
141    Raw { base: String, offset: isize, len: isize },
142    Named { protocol: String, field: String },
143}
144
145#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
146#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
147#[serde(deny_unknown_fields)]
148pub struct Prefix {
149    pub addr: Box<Expression>,
150    pub len: isize,
151}
152
153#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
154#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
155#[serde(deny_unknown_fields)]
156pub struct Rt {
157    pub key: String,
158    pub family: Option<String>,
159}
160
161#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
162#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
163#[serde(deny_unknown_fields)]
164pub struct SctpChunk {
165    pub name: String,
166    pub field: Option<String>,
167}
168
169#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
170#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
171#[serde(deny_unknown_fields)]
172pub struct Socket {
173    pub key: Option<String>,
174}
175
176#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
177#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
178#[serde(deny_unknown_fields)]
179pub struct Synproxy {
180    pub mss: Option<isize>,
181    pub wscale: Option<isize>,
182    #[serde(with = "serde_with::As::<Option<serde_with::OneOrMany<serde_with::Same>>>")]
183    pub flags: Option<Vec<String>>,
184}
185
186#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
187#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
188#[serde(deny_unknown_fields, untagged)]
189pub enum TcpOption {
190    Raw { base: isize, offset: isize, len: isize },
191    Named { name: String, field: Option<String> },
192}
193
194#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
195#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
196#[serde(deny_unknown_fields)]
197pub struct Tproxy {
198    pub addr: Option<String>,
199    pub family: Option<String>,
200    pub port: Option<isize>,
201}
202
203#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
204#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
205#[serde(deny_unknown_fields, rename_all = "kebab-case")]
206#[non_exhaustive]
207pub enum Verdict {
208    Accept(()),
209    Drop(()),
210    Continue(()),
211    Return(()),
212    Jump { target: String },
213    Goto { target: String },
214}
215
216/// Represents a rule's match criteria
217#[serde_with::apply(Option => #[serde(default, skip_serializing_if = "Option::is_none")])]
218#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
219#[serde(deny_unknown_fields, untagged)]
220#[non_exhaustive]
221pub enum Expression {
222    Immediate(Immediate),
223    List(Vec<Self>),
224    Concat {
225        concat: Vec<Self>,
226    },
227    Set {
228        set: Vec<Self>,
229    },
230    Map {
231        map: Map,
232    },
233    Prefix {
234        prefix: Prefix,
235    },
236    Range {
237        range: (Immediate, Immediate),
238    },
239    Payload {
240        payload: Payload,
241    },
242    Exthdr {
243        exthdr: Exthdr,
244    },
245    IpOption {
246        #[serde(rename = "ip option")]
247        ip_option: IpOption,
248    },
249    TcpOption {
250        #[serde(rename = "tcp option")]
251        tcp_option: TcpOption,
252    },
253    SctpChunk {
254        #[serde(rename = "sctp chunk")]
255        sctp_chunk: SctpChunk,
256    },
257    Meta {
258        meta: Meta,
259    },
260    Rt {
261        rt: Rt,
262    },
263    Ct {
264        ct: Ct,
265    },
266    Numgen {
267        numgen: Numgen,
268    },
269    Hash(Hash),
270    Fib {
271        fib: Fib,
272    },
273    Xfrm {
274        ipsec: Xfrm,
275    },
276    Binary(Binary),
277    Verdict(Verdict),
278    Elem {
279        elem: Elem,
280    },
281    Socket {
282        socket: Socket,
283    },
284    Osf {
285        osf: Osf,
286    },
287    Synproxy {
288        synproxy: Option<Synproxy>,
289    },
290    Tproxy {
291        tproxy: Tproxy,
292    },
293}