Skip to main content

nftables/
expr.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::{borrow::Cow, collections::HashSet};
4
5use crate::stmt::{Counter, JumpTarget, Statement};
6use crate::visitor::deserialize_flags;
7use strum_macros::EnumString;
8
9#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
10#[serde(untagged)]
11/// Expressions are the building blocks of (most) [statements](crate::stmt::Statement).
12/// In their most basic form, they are just immediate values represented as a
13/// JSON string, integer or boolean type.
14pub enum Expression<'a> {
15    // immediates
16    /// A string expression (*immediate expression*).
17    /// For string expressions there are two special cases:
18    ///   * `@STRING`: The remaining part is taken as [set](crate::schema::Set)
19    ///     name to create a set reference.
20    ///   * `\*`: Construct a wildcard expression.
21    String(Cow<'a, str>),
22    /// An integer expression (*immediate expression*).
23    Number(u32),
24    /// A boolean expression (*immediate expression*).
25    Boolean(bool),
26    /// List expressions are constructed by plain arrays containing of an arbitrary number of expressions.
27    List(Vec<Expression<'a>>),
28    /// A [binary operation](BinaryOperation) expression.
29    BinaryOperation(Box<BinaryOperation<'a>>),
30    /// Construct a range of values.
31    ///
32    /// The first array item denotes the lower boundary, the second one the upper boundary.
33    Range(Box<Range<'a>>),
34
35    /// Wrapper for non-immediate expressions.
36    Named(NamedExpression<'a>),
37    /// A verdict expression (used in [verdict maps](crate::stmt::VerdictMap)).
38    Verdict(Verdict<'a>),
39}
40
41#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
42#[serde(rename_all = "lowercase")]
43/// Wrapper for non-immediate [Expressions](Expression).
44pub enum NamedExpression<'a> {
45    /// Concatenate several expressions.
46    Concat(Vec<Expression<'a>>),
47    /// This object constructs an anonymous set with [items](SetItem).
48    /// For mappings, an array of arrays with exactly two elements is expected.
49    Set(Vec<SetItem<'a>>),
50    /// Map a key to a value.
51    Map(Box<Map<'a>>),
52    /// Construct an IPv4 or IPv6 [prefix](Prefix) consisting of address part and prefix length.
53    Prefix(Prefix<'a>),
54
55    /// Construct a [payload](Payload) expression, i.e. a reference to a certain part of packet data.
56    Payload(Payload<'a>),
57
58    /// Create a reference to a field in an IPv6 extension header.
59    Exthdr(Exthdr<'a>),
60    #[serde(rename = "tcp option")]
61    /// Create a reference to a field of a TCP option header.
62    TcpOption(TcpOption<'a>),
63    #[serde(rename = "sctp chunk")]
64    /// Create a reference to a field of an SCTP chunk.
65    SctpChunk(SctpChunk<'a>),
66    // TODO: DCCP Option
67    /// Create a reference to packet meta data.
68    Meta(Meta),
69    /// Create a reference to packet routing data.
70    RT(RT),
71    /// Create a reference to packet conntrack data.
72    CT(CT<'a>),
73    /// Create a number generator.
74    Numgen(Numgen),
75    /// Hash packet data (Jenkins Hash).
76    JHash(JHash<'a>),
77    /// Hash packet data (Symmetric Hash).
78    SymHash(SymHash),
79
80    /// Perform kernel Forwarding Information Base lookups.
81    Fib(Fib),
82    /// Explicitly set element object, in case `timeout`, `expires`, or `comment`
83    /// are desired.
84    Elem(Elem<'a>),
85    /// Construct a reference to a packet’s socket.
86    Socket(Socket<'a>),
87    /// Perform OS fingerprinting.
88    ///
89    /// This expression is typically used in the [LHS](crate::stmt::Match::left)
90    /// of a [match](crate::stmt::Match) statement.
91    Osf(Osf<'a>),
92}
93
94#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
95#[serde(rename = "map")]
96/// Map a key to a value.
97pub struct Map<'a> {
98    /// Map key.
99    pub key: Expression<'a>,
100    /// Mapping expression consisting of value/target pairs.
101    pub data: Expression<'a>,
102}
103
104/// Default map expression (`true -> false`).
105impl Default for Map<'_> {
106    fn default() -> Self {
107        Map {
108            key: Expression::Boolean(true),
109            data: Expression::Boolean(false),
110        }
111    }
112}
113
114#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
115#[serde(untagged)]
116/// Item in an anonymous set.
117pub enum SetItem<'a> {
118    /// A set item containing a single expression.
119    Element(Expression<'a>),
120    /// A set item mapping two expressions.
121    Mapping(Expression<'a>, Expression<'a>),
122    /// A set item mapping an expression to a statement.
123    MappingStatement(Expression<'a>, Statement<'a>),
124}
125
126#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
127#[serde(rename = "prefix")]
128/// Construct an IPv4 or IPv6 prefix consisting of address part in
129/// [addr](Prefix::addr) and prefix length in [len](Prefix::len).
130pub struct Prefix<'a> {
131    /// An IPv4 or IPv6 address.
132    pub addr: Box<Expression<'a>>,
133    /// The prefix length.
134    pub len: u32,
135}
136
137#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
138#[serde(rename = "range")]
139/// Construct a range of values.
140/// The first array item denotes the lower boundary, the second one the upper
141/// boundary.
142pub struct Range<'a> {
143    /// The range boundaries.
144    ///
145    /// The first array item denotes the lower boundary, the second one the
146    /// upper boundary.
147    pub range: [Expression<'a>; 2],
148}
149
150#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
151#[serde(untagged)]
152/// Construct a payload expression, i.e. a reference to a certain part of packet
153/// data.
154pub enum Payload<'a> {
155    /// Allows one to reference a field by name in a named packet header.
156    PayloadField(PayloadField<'a>),
157    /// Creates a raw payload expression to point at a random number of bits at
158    /// a certain offset from a given reference point.
159    PayloadRaw(PayloadRaw),
160}
161
162#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
163/// Creates a raw payload expression to point at a random number
164/// ([len](PayloadRaw::len)) of bits at a certain offset
165/// ([offset](PayloadRaw::offset)) from a given reference point
166/// ([base](PayloadRaw::base)).
167pub struct PayloadRaw {
168    /// The (protocol layer) reference point.
169    pub base: PayloadBase,
170    /// Offset from the reference point in bits.
171    pub offset: u32,
172    /// Number of bits.
173    pub len: u32,
174}
175
176/// Default raw payload expression (0-length at link layer).
177impl Default for PayloadRaw {
178    fn default() -> Self {
179        PayloadRaw {
180            base: PayloadBase::LL,
181            offset: 0,
182            len: 0,
183        }
184    }
185}
186
187#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
188/// Construct a payload expression, i.e. a reference to a certain part of packet
189/// data.
190///
191/// Allows to reference a field by name ([field](PayloadField::field)) in a
192/// named packet header ([protocol](PayloadField::protocol)).
193pub struct PayloadField<'a> {
194    /// A named packet header.
195    pub protocol: Cow<'a, str>,
196    /// The field name.
197    pub field: Cow<'a, str>,
198}
199
200/// Default payload field reference (`arp ptype`).
201impl Default for PayloadField<'_> {
202    fn default() -> Self {
203        PayloadField {
204            protocol: "arp".into(),
205            field: "ptype".into(),
206        }
207    }
208}
209
210#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
211#[serde(rename_all = "lowercase")]
212/// Represents a protocol layer for [payload](Payload) references.
213pub enum PayloadBase {
214    /// Link layer, for example the Ethernet header.
215    LL,
216    /// Network header, for example IPv4 or IPv6.
217    NH,
218    /// Transport Header, for example TCP.
219    ///
220    /// *Added in nftables 0.9.2 and Linux kernel 5.3.*
221    TH,
222    /// Inner Header / Payload, i.e. after the L4 transport level header.
223    ///
224    /// *Added in Kernel version 6.2.*
225    IH,
226}
227
228#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
229#[serde(rename = "exthdr")]
230/// Create a reference to a field ([field](Exthdr::field)) in an IPv6 extension
231/// header ([name](Exthdr::name)).
232///
233/// [offset](Exthdr::offset) is used only for `rt0` protocol.
234pub struct Exthdr<'a> {
235    /// The IPv6 extension header name.
236    pub name: Cow<'a, str>,
237    /// The field name.
238    ///
239    /// If the [field][Exthdr::field] property is not given, the expression is
240    /// to be used as a header existence check in a [match](crate::stmt::Match)
241    /// statement with a [boolean](Expression::Boolean) on the
242    /// [right](crate::stmt::Match::right) hand side.
243    pub field: Option<Cow<'a, str>>,
244    /// The offset length. Used only for `rt0` protocol.
245    pub offset: Option<u32>,
246}
247
248/// Default [Exthdr] for `frag` extension header.
249impl Default for Exthdr<'_> {
250    fn default() -> Self {
251        Exthdr {
252            name: "frag".into(),
253            field: None,
254            offset: None,
255        }
256    }
257}
258
259#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
260#[serde(rename = "tcp option")]
261/// Create a reference to a field ([field](TcpOption::field)) of a TCP option
262/// header ([name](TcpOption::field)).
263pub struct TcpOption<'a> {
264    /// The TCP option header name.
265    pub name: Cow<'a, str>,
266    /// The field name.
267    ///
268    /// If the field property is not given, the expression is to be used as a
269    /// TCP option existence check in a [match](crate::stmt::Match)
270    /// statement with a [boolean](Expression::Boolean) on the
271    /// [right](crate::stmt::Match::right) hand side.
272    pub field: Option<Cow<'a, str>>,
273}
274
275/// Default TCP option for `maxseg` option.
276impl Default for TcpOption<'_> {
277    fn default() -> Self {
278        TcpOption {
279            name: "maxseg".into(),
280            field: None,
281        }
282    }
283}
284
285#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
286#[serde(rename = "sctp chunk")]
287/// Create a reference to a field ([field](SctpChunk::field)) of an SCTP chunk
288/// ((name)[SctpChunk::name]).
289pub struct SctpChunk<'a> {
290    /// The SCTP chunk name.
291    pub name: Cow<'a, str>,
292    /// The field name.
293    ///
294    /// If the field property is not given, the expression is to be used as an
295    /// SCTP chunk existence check in a [match](crate::stmt::Match) statement
296    /// with a [boolean](Expression::Boolean) on the
297    /// [right](crate::stmt::Match::right) hand side.
298    pub field: Cow<'a, str>,
299}
300
301#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
302#[serde(rename = "meta")]
303/// Create a reference to packet meta data.
304///
305/// See [this page](https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation)
306/// for more information.
307pub struct Meta {
308    /// The packet [meta data key](MetaKey).
309    pub key: MetaKey,
310}
311
312/// Default impl for meta key `l4proto`.
313impl Default for Meta {
314    fn default() -> Self {
315        Meta {
316            key: MetaKey::L4proto,
317        }
318    }
319}
320
321#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
322#[serde(rename_all = "lowercase")]
323/// Represents a `meta` key for packet meta data.
324///
325/// See [this page](https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation)
326/// for more information.
327pub enum MetaKey {
328    // matching by packet info:
329    /// Packet type (unicast, broadcast, multicast, other).
330    Pkttype,
331    /// Packet length in bytes.
332    Length,
333    /// Packet protocol / EtherType protocol value.
334    Protocol,
335    /// Netfilter packet protocol family.
336    Nfproto,
337    /// Layer 4 protocol.
338    L4proto,
339
340    // matching by interface:
341    /// Input interface index.
342    Iif,
343    /// Input interface name.
344    Iifname,
345    /// Input interface type.
346    Iiftype,
347    /// Input interface kind name.
348    Iifkind,
349    /// Input interface group.
350    Iifgroup,
351    /// Output interface index.
352    Oif,
353    /// Output interface name.
354    Oifname,
355    /// Output interface type.
356    Oiftype,
357    /// Output interface kind name.
358    Oifkind,
359    /// Output interface group.
360    Oifgroup,
361    /// Input bridge interface name.
362    Ibridgename,
363    /// Output bridge interface name.
364    Obridgename,
365    /// Input bridge interface name
366    Ibriport,
367    /// Output bridge interface name
368    Obriport,
369
370    // matching by packet mark, routing class and realm:
371    /// Packet mark.
372    Mark,
373    /// TC packet priority.
374    Priority,
375    /// Routing realm.
376    Rtclassid,
377
378    // matching by socket uid/gid:
379    /// UID associated with originating socket.
380    Skuid,
381    /// GID associated with originating socket.
382    Skgid,
383
384    // matching by security selectors:
385    /// CPU number processing the packet.
386    Cpu,
387    /// Socket control group ID.
388    Cgroup,
389    /// `true` if packet was ipsec encrypted. (*obsolete*)
390    Secpath,
391
392    // matching by miscellaneous selectors:
393    /// Pseudo-random number.
394    Random,
395    /// [nftrace debugging] bit.
396    ///
397    /// [nftract debugging]: <https://wiki.nftables.org/wiki-nftables/index.php/Ruleset_debug/tracing>
398    Nftrace,
399}
400
401#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
402#[serde(rename = "rt")]
403/// Create a reference to packet routing data.
404pub struct RT {
405    /// The routing data key.
406    pub key: RTKey,
407    #[serde(skip_serializing_if = "Option::is_none")]
408    /// The protocol family.
409    ///
410    /// The `family` property is optional and defaults to unspecified.
411    pub family: Option<RTFamily>,
412}
413
414/// Default impl for [RT] with key [nexthop](RTKey::NextHop).
415impl Default for RT {
416    fn default() -> Self {
417        RT {
418            key: RTKey::NextHop,
419            family: None,
420        }
421    }
422}
423
424#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
425#[serde(rename_all = "lowercase")]
426/// Represents a key to reference to packet routing data.
427pub enum RTKey {
428    /// Routing realm.
429    ClassId,
430    /// Routing nexthop.
431    NextHop,
432    /// TCP maximum segment size of route.
433    MTU,
434}
435
436#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
437#[serde(rename_all = "lowercase")]
438/// Represents a protocol family for use by the [rt](RT) expression.
439pub enum RTFamily {
440    /// IPv4 RT protocol family.
441    IP,
442    /// IPv6 RT protocol family.
443    IP6,
444}
445
446#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
447#[serde(rename = "ct")]
448/// Create a reference to packet conntrack data.
449pub struct CT<'a> {
450    /// The conntrack expression.
451    ///
452    /// See also: *CONNTRACK EXPRESSIONS* in *ntf(8)*.
453    pub key: Cow<'a, str>,
454    #[serde(skip_serializing_if = "Option::is_none")]
455    /// The [conntrack protocol family](CTFamily).
456    pub family: Option<CTFamily>,
457    #[serde(skip_serializing_if = "Option::is_none")]
458    /// Conntrack flow [direction](CTDir).
459    ///
460    /// Some CT keys do not support a direction.
461    /// In this case, `dir` must not be given.
462    pub dir: Option<CTDir>,
463}
464
465/// Default impl for conntrack with `l3proto` conntrack key.
466impl Default for CT<'_> {
467    fn default() -> Self {
468        CT {
469            key: "l3proto".into(),
470            family: None,
471            dir: None,
472        }
473    }
474}
475
476#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
477#[serde(rename_all = "lowercase")]
478/// Represents a protocol family for use by the [ct](CT) expression.
479pub enum CTFamily {
480    /// IPv4 conntrack protocol family.
481    IP,
482    /// IPv6 conntrack protocol family.
483    IP6,
484}
485
486#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
487#[serde(rename_all = "lowercase")]
488/// Represents a direction for use by the [ct](CT) expression.
489pub enum CTDir {
490    /// Original direction.
491    Original,
492    /// Reply direction.
493    Reply,
494}
495
496#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
497#[serde(rename = "numgen")]
498/// Create a number generator.
499pub struct Numgen {
500    /// The [number generator mode](NgMode).
501    pub mode: NgMode,
502    #[serde(rename = "mod")]
503    /// Specifies an upper boundary ("modulus") which is not reached by returned
504    /// numbers.
505    pub ng_mod: u32,
506    #[serde(skip_serializing_if = "Option::is_none")]
507    /// Allows one to increment the returned value by a fixed offset.
508    pub offset: Option<u32>,
509}
510
511/// Default impl for [numgen](Numgen) with mode [inc](NgMode::Inc) and mod `7`.
512impl Default for Numgen {
513    fn default() -> Self {
514        Numgen {
515            mode: NgMode::Inc,
516            ng_mod: 7,
517            offset: None,
518        }
519    }
520}
521
522#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
523#[serde(rename_all = "lowercase")]
524/// Represents a number generator mode.
525pub enum NgMode {
526    /// The last returned value is simply incremented.
527    Inc,
528    /// A new random number is returned.
529    Random,
530}
531
532#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
533#[serde(rename = "jhash")]
534/// Hash packet data (Jenkins Hash).
535pub struct JHash<'a> {
536    #[serde(rename = "mod")]
537    /// Specifies an upper boundary ("modulus") which is not reached by returned numbers.
538    pub hash_mod: u32,
539    #[serde(skip_serializing_if = "Option::is_none")]
540    /// Increment the returned value by a fixed offset.
541    pub offset: Option<u32>,
542    /// Determines the parameters of the packet header to apply the hashing,
543    /// concatenations are possible as well.
544    pub expr: Box<Expression<'a>>,
545    #[serde(skip_serializing_if = "Option::is_none")]
546    /// Specify an init value used as seed in the hashing function
547    pub seed: Option<u32>,
548}
549
550/// Default impl for [jhash](JHash).
551impl Default for JHash<'_> {
552    fn default() -> Self {
553        JHash {
554            hash_mod: 7,
555            offset: None,
556            expr: Box::new(Expression::Named(NamedExpression::Payload(
557                Payload::PayloadField(PayloadField {
558                    protocol: "ip".into(),
559                    field: "saddr".into(),
560                }),
561            ))),
562            seed: None,
563        }
564    }
565}
566
567#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
568#[serde(rename = "symhash")]
569/// Hash packet data (Symmetric Hash).
570pub struct SymHash {
571    #[serde(rename = "mod")]
572    /// Specifies an upper boundary ("modulus") which is not reached by returned numbers.
573    pub hash_mod: u32,
574    /// Increment the returned value by a fixed offset.
575    pub offset: Option<u32>,
576}
577
578/// Default impl for [symhash](SymHash).
579impl Default for SymHash {
580    fn default() -> Self {
581        SymHash {
582            hash_mod: 2,
583            offset: None,
584        }
585    }
586}
587
588#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
589#[serde(rename = "fib")]
590/// Perform kernel Forwarding Information Base lookups.
591pub struct Fib {
592    /// The data to be queried by fib lookup.
593    pub result: FibResult,
594    #[serde(deserialize_with = "deserialize_flags")]
595    /// The tuple of elements ([FibFlags](FibFlag)) that is used as input to the
596    /// fib lookup functions.
597    pub flags: HashSet<FibFlag>,
598}
599
600/// Default impl for [fib](Fib).
601impl Default for Fib {
602    fn default() -> Self {
603        let mut flags = HashSet::with_capacity(1);
604        flags.insert(FibFlag::Iif);
605        Fib {
606            result: FibResult::Oif,
607            flags,
608        }
609    }
610}
611
612#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
613#[serde(rename_all = "lowercase")]
614/// Represents which data is queried by [fib](Fib) lookup.
615pub enum FibResult {
616    /// Output interface index.
617    Oif,
618    /// Output interface name.
619    Oifname,
620    /// Address type.
621    Type,
622}
623
624#[derive(
625    Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, EnumString, Hash, JsonSchema,
626)]
627#[serde(rename_all = "lowercase")]
628#[strum(serialize_all = "lowercase")]
629/// Represents flags for `fib` lookup.
630pub enum FibFlag {
631    /// Consider the source address of a packet.
632    Saddr,
633    /// Consider the destination address of a packet.
634    Daddr,
635    /// Consider the packet mark.
636    Mark,
637    /// Consider the packet's input interface.
638    Iif,
639    /// Consider the packet's output interface.
640    Oif,
641}
642
643#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
644/// Represents a binary operation to be used in an `Expression`.
645pub enum BinaryOperation<'a> {
646    #[serde(rename = "&")]
647    /// Binary AND (`&`)
648    AND(Expression<'a>, Expression<'a>),
649
650    #[serde(rename = "|")]
651    /// Binary OR (`|`)
652    OR(Vec<Expression<'a>>),
653
654    #[serde(rename = "^")]
655    /// Binary XOR (`^`)
656    XOR(Expression<'a>, Expression<'a>),
657
658    #[serde(rename = "<<")]
659    /// Left shift (`<<`)
660    LSHIFT(Expression<'a>, Expression<'a>),
661
662    #[serde(rename = ">>")]
663    /// Right shift (`>>`)
664    RSHIFT(Expression<'a>, Expression<'a>),
665}
666
667#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
668#[serde(rename_all = "lowercase")]
669/// A verdict expression (used in [verdict maps](crate::stmt::VerdictMap)).
670///
671/// There are also verdict [statements](crate::stmt::Statement), such as
672/// [accept](crate::stmt::Statement::Accept).
673pub enum Verdict<'a> {
674    /// Terminate ruleset evaluation and accept the packet.
675    ///
676    /// The packet can still be dropped later by another hook, for instance
677    /// accept in the forward hook still allows one to drop the packet later in
678    /// the postrouting hook, or another forward base chain that has a higher
679    /// priority number and is evaluated afterwards in the processing pipeline.
680    Accept,
681    /// Terminate ruleset evaluation and drop the packet.
682    ///
683    /// The drop occurs instantly, no further chains or hooks are evaluated.
684    /// It is not possible to accept the packet in a later chain again, as those
685    /// are not evaluated anymore for the packet.
686    Drop,
687    /// Continue ruleset evaluation with the next rule.
688    ///
689    /// This is the default behaviour in case a rule issues no verdict.
690    Continue,
691    /// Return from the current chain and continue evaluation at the next rule
692    /// in the last chain.
693    ///
694    /// If issued in a base chain, it is equivalent to the base chain policy.
695    Return,
696    /// Continue evaluation at the first rule in chain.
697    ///
698    /// The current position in the ruleset is pushed to a call stack and
699    /// evaluation will continue there when the new chain is entirely evaluated
700    /// or a [return](Verdict::Return) verdict is issued. In case an absolute
701    /// verdict is issued by a rule in the chain, ruleset evaluation terminates
702    /// immediately and the specific action is taken.
703    Jump(JumpTarget<'a>),
704    /// Similar to jump, but the current position is not pushed to the call
705    /// stack.
706    ///
707    /// That means that after the new chain evaluation will continue at the
708    /// last chain instead of the one containing the goto statement.
709    Goto(JumpTarget<'a>),
710}
711
712#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
713#[serde(rename = "elem")]
714/// Explicitly set element object.
715///
716/// Element-related commands allow one to change contents of named
717/// [sets](crate::schema::Set) and [maps](crate::schema::Map).
718pub struct Elem<'a> {
719    /// The element value.
720    pub val: Box<Expression<'a>>,
721    /// Timeout value for [sets](crate::schema::Set)/[maps](crate::schema::Map).
722    /// with flag [timeout](crate::schema::SetFlag::Timeout)
723    pub timeout: Option<u32>,
724    /// The time until given element expires, useful for ruleset replication only.
725    pub expires: Option<u32>,
726    /// Per element comment field.
727    pub comment: Option<Cow<'a, str>>,
728    /// Enable a [counter][crate::stmt::Counter] per element.
729    ///
730    /// Added in nftables version *0.9.5*.
731    pub counter: Option<Counter<'a>>,
732}
733
734/// Default impl for [Elem].
735impl Default for Elem<'_> {
736    fn default() -> Self {
737        Elem {
738            val: Box::new(Expression::String("10.2.3.4".into())),
739            timeout: None,
740            expires: None,
741            comment: None,
742            counter: None,
743        }
744    }
745}
746
747#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
748#[serde(rename = "socket")]
749/// Construct a reference to packet’s socket.
750pub struct Socket<'a> {
751    /// The socket attribute to match on.
752    pub key: Cow<'a, SocketAttr>,
753}
754
755/// Default impl for [Socket] with [wildcard](SocketAttr::Wildcard) key.
756impl Default for Socket<'_> {
757    fn default() -> Self {
758        Socket {
759            key: Cow::Borrowed(&SocketAttr::Wildcard),
760        }
761    }
762}
763
764#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
765#[serde(rename_all = "lowercase")]
766/// A [socket][Socket] attribute to match on.
767pub enum SocketAttr {
768    /// Match on the `IP_TRANSPARENT` socket option in the found socket.
769    Transparent,
770    /// Match on the socket mark (`SOL_SOCKET`, `SO_MARK`).
771    Mark,
772    /// Indicates whether the socket is wildcard-bound (e.g. 0.0.0.0 or ::0).
773    Wildcard,
774    /// The cgroup version 2 for this socket (path from `/sys/fs/cgroup`).
775    Cgroupv2,
776}
777
778#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
779#[serde(rename = "osf")]
780/// Perform OS fingerprinting.
781///
782/// This expression is typically used in the [LHS](crate::stmt::Match::left) of
783/// a [match](crate::stmt::Match) statement.
784pub struct Osf<'a> {
785    /// Name of the OS signature to match.
786    ///
787    /// All signatures can be found at `pf.os` file.
788    /// Use "unknown" for OS signatures that the expression could not detect.
789    pub key: Cow<'a, str>,
790    /// Do TTL checks on the packet to determine the operating system.
791    pub ttl: OsfTtl,
792}
793
794#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, JsonSchema)]
795#[serde(rename_all = "lowercase")]
796/// TTL check mode for [osf](Osf).
797pub enum OsfTtl {
798    /// Check if the IP header's TTL is less than the fingerprint one.
799    ///
800    /// Works for globally-routable addresses.
801    Loose,
802    /// Do not compare the TTL at all.
803    Skip,
804}