Linx.Netfilter.Verdict (Linx v0.1.0)

Copy Markdown View Source

A netfilter verdict — the terminal result of a rule's evaluation.

Verdicts are the kernel's per-packet decisions. The simple verdicts (:accept, :drop, :continue, :return) take no target; :jump and :goto target another chain by name; :queue targets a userspace queue number.

Verdict kinds

  • :accept — let the packet through; further chains may still see it.
  • :drop — silently drop the packet.
  • :continue — fall through to the next rule (the implicit default when no rule matches).
  • :return — return from the current chain (only meaningful inside a chain reached via :jump).
  • :jump — call into another chain; control returns when that chain :returns or runs out of rules.
  • :goto — tail-call another chain; control does not return.
  • :queue — hand the packet to a userspace queue (NFQUEUE consumer — Linx.Netfilter.Queue is deferred post-v1).

:reject is not a verdict — it's a statement that constructs an ICMP/TCP-RST/ICMPX response then drops. Construct it via Linx.Netfilter.Expr.reject.

Construction

iex> Verdict.accept()
#Linx.Netfilter.Verdict<accept>

iex> Verdict.jump("input_extras")
#Linx.Netfilter.Verdict<jump "input_extras">

iex> Verdict.new(:drop)
#Linx.Netfilter.Verdict<drop>

iex> Verdict.new({:goto, "drop_quietly"})
#Linx.Netfilter.Verdict<goto "drop_quietly">

Validation

new/1 returns {:error, {:bad_verdict, reason}} for unknown kinds, missing chain targets on :jump/:goto, or non-integer queue numbers. The bang variant raises ArgumentError.

Wire encoding (the integer codes the kernel expects in NFT_DATA_VERDICT) is handled elsewhere — this struct is pure data.

References

Summary

Types

The user-facing input forms new/1 accepts.

t()

Functions

Verdict: let the packet through.

Verdict: fall through to the next rule.

Verdict: silently drop the packet.

Verdict: tail-call chain_name. Control does not return.

Verdict: call into chain_name. Control returns when that chain :returns or runs out of rules.

Constructs a verdict from a user-friendly input form.

Bang variant of new/1 — returns the verdict or raises ArgumentError describing the failure.

Verdict: hand the packet to userspace queue num.

Verdict: return from the current chain.

Returns true if v is a well-formed verdict.

Types

input()

@type input() ::
  :accept
  | :drop
  | :continue
  | :return
  | {:jump, String.t()}
  | {:goto, String.t()}
  | {:queue, non_neg_integer()}
  | t()

The user-facing input forms new/1 accepts.

kind()

@type kind() :: :accept | :drop | :continue | :return | :jump | :goto | :queue

t()

@type t() :: %Linx.Netfilter.Verdict{kind: kind(), target: target()}

target()

@type target() :: nil | String.t() | non_neg_integer()

Functions

accept()

@spec accept() :: t()

Verdict: let the packet through.

continue()

@spec continue() :: t()

Verdict: fall through to the next rule.

drop()

@spec drop() :: t()

Verdict: silently drop the packet.

goto(chain_name)

@spec goto(String.t()) :: t()

Verdict: tail-call chain_name. Control does not return.

jump(chain_name)

@spec jump(String.t()) :: t()

Verdict: call into chain_name. Control returns when that chain :returns or runs out of rules.

new(v)

@spec new(input()) :: {:ok, t()} | {:error, {:bad_verdict, term()}}

Constructs a verdict from a user-friendly input form.

Accepts an atom for simple verdicts, a {kind, target} tuple for parameterised verdicts, or an existing %Verdict{} (returned as-is — convenient for pipeline code that doesn't know which form it was handed).

new!(input)

@spec new!(input()) :: t()

Bang variant of new/1 — returns the verdict or raises ArgumentError describing the failure.

queue(num)

@spec queue(non_neg_integer()) :: t()

Verdict: hand the packet to userspace queue num.

return()

@spec return() :: t()

Verdict: return from the current chain.

valid?(arg1)

@spec valid?(t()) :: boolean()

Returns true if v is a well-formed verdict.