An nftables chain — a named container of rules within a table.
Chains come in two flavours:
Base chains carry a
:type+:hook+:priorityand (optionally) a:policy. The kernel attaches them to the hook point so packets actually flow through them.Regular chains have none of those — they are jump/goto targets reachable from base chains via verdicts. Pure organisational tools.
Fields
:name— chain name (unique within the table).:table— name of the owning table;nilfor free-standing chains, populated when added to a table.:type—:filter|:nat|:routefor base chains,nilfor regular chains.:hook—:prerouting|:input|:forward|:output|:postrouting|:ingress|:egressfor base chains,nilfor regular chains.:priority— integer | atom (named priority) |{atom, integer}(named-with-offset, e.g.{:filter, -10}). Required for base chains;nilfor regular chains.:policy—:accept|:drop; default verdict when no rule matches. Only meaningful on base chains.nilmeans "no explicit policy" (kernel defaults to:accept).:device— interface name (string). Required for:ingressand:egresshooks; nil otherwise.:flags— list (advanced)::hw_offloadenables hardware offload (kernel + driver permitting); other flags reserved for future use.:handle— kernel-assigned handle;niluntil pushed.:rules— ordered list of%Linx.Netfilter.Rule{}.
Validation
new/2 validates the chain's intrinsic shape (base-vs-regular
consistency, required fields). Family-specific validation (e.g.
:nat type only valid in ip/ip6/inet families, :ingress
hook only valid in certain families) lives in validate_for_family/2
and runs when the chain is added to a table (Linx.Netfilter.Ruleset.add_chain/4).
Construction
iex> Chain.new("input", type: :filter, hook: :input, priority: 0, policy: :accept)
{:ok, %Linx.Netfilter.Chain{name: "input", type: :filter, hook: :input, ...}}
iex> Chain.new("ingress_drop", type: :filter, hook: :ingress, priority: -500, device: "eth0")
{:ok, %Linx.Netfilter.Chain{hook: :ingress, device: "eth0", ...}}
iex> Chain.new("input_extras")
{:ok, %Linx.Netfilter.Chain{type: nil, hook: nil, ...}} # regular chainErrors come back as {:error, {:bad_chain, reason}}.
References
Summary
Functions
Returns a new chain with rule appended to its rules list.
Returns true iff chain is a base chain (has :type, :hook,
and :priority set).
Builds a chain. Validates intrinsic shape; family-specific
validation happens at validate_for_family/2.
Bang variant of new/2 — returns the chain or raises
ArgumentError.
Validates the chain against the given family — checks family-specific
rules that new/2 can't (since it doesn't know the family).
Types
@type chain_type() :: :filter | :nat | :route
@type hook() ::
:prerouting | :input | :forward | :output | :postrouting | :ingress | :egress
@type policy() :: :accept | :drop
@type t() :: %Linx.Netfilter.Chain{ device: String.t() | nil, flags: [atom()], handle: pos_integer() | nil, hook: hook() | nil, name: String.t(), policy: policy() | nil, priority: priority() | nil, rules: [Linx.Netfilter.Rule.t()], table: String.t() | nil, type: chain_type() | nil }
Functions
@spec add_rule(t(), Linx.Netfilter.Rule.t()) :: {:ok, t()} | {:error, {:bad_chain, term()}}
Returns a new chain with rule appended to its rules list.
This is a pure data operation — no validation beyond ensuring
rule is a %Rule{}. Higher-level validation (tag uniqueness
within chain) lives in Linx.Netfilter.Ruleset.add_rule/4.
The added rule's :chain field is set to the chain's name (so
free-standing rules pick up their context when inserted).
Returns true iff chain is a base chain (has :type, :hook,
and :priority set).
Builds a chain. Validates intrinsic shape; family-specific
validation happens at validate_for_family/2.
Bang variant of new/2 — returns the chain or raises
ArgumentError.
Validates the chain against the given family — checks family-specific
rules that new/2 can't (since it doesn't know the family).
Rules enforced:
- Family-allowed chain types (e.g.
:natinvalid inarp,bridge,netdev;:routeonly inip/ip6). - Family-allowed hooks (e.g.
arponly has:input/:output;netdevonly has:ingress/:egress). :natchains restricted to NAT-applicable hooks.:routechains restricted to:outputhook.