nfnetlink (NETLINK_NETFILTER) — the kernel's netfilter-control
interface: nf_tables (the modern firewall), conntrack, NFLOG, NFQUEUE.
This is the second Linx.Netlink protocol family (after
Linx.Netlink.Rtnl). nfnetlink multiplexes several sub-subsystems
inside one netlink family — identified by the high byte of
nlmsghdr.type (subsys_id). The map (include/uapi/linux/netfilter/nfnetlink.h):
| subsys_id | Name | Linx module |
|---|---|---|
| 1 | CTNETLINK | Linx.Netfilter.Conntrack (future) |
| 3 | QUEUE | Linx.Netfilter.Queue (future) |
| 4 | ULOG | Linx.Netfilter.Log (NFLOG) |
| 10 | NFTABLES | Linx.Netfilter core |
| 12 | HOOK | (deferred) |
Open a socket with open/1 and pass it to the appropriate higher-level
module (Linx.Netfilter, eventually Linx.Netfilter.{Conntrack,Log,Queue}).
Codec helpers — nfgenmsg header encoding, subsys-id multiplexing on
nlmsghdr.type, batched-transaction envelope (NFNL_MSG_BATCH_BEGIN /
NFNL_MSG_BATCH_END), and the NFT_MSG_GETGEN / NEWGEN codec — live
in Linx.Netlink.Nfnl.Codec. The batch/2 request engine below
drives nf_tables mutating transactions on top of those primitives.
The NFTABLES sub-subsystem (id 10) is driven by Linx.Netfilter;
CTNETLINK / QUEUE / HOOK are future families.
Summary
Functions
Sends a batched nf_tables transaction.
Opens an nfnetlink socket in network namespace netns.
Functions
@spec batch( Linx.Netlink.Socket.t(), [Linx.Netlink.Message.t()], atom() | 0..255, keyword() ) :: :ok | {:error, {non_neg_integer(), Linx.Netlink.Error.t()} | term()}
Sends a batched nf_tables transaction.
Wraps inner_messages between a NFNL_MSG_BATCH_BEGIN envelope
targeting subsys (default :nftables) and a NFNL_MSG_BATCH_END,
assigns sequence numbers, ORs NLM_F_REQUEST | NLM_F_ACK onto every
inner message, sends the whole batch in one sendmsg(2), and
collects per-message ACK / error responses until every inner
message has been accounted for.
Returns :ok if every inner message was accepted, or
{:error, {batch_seq, %Linx.Netlink.Error{}}} for the first
inner message the kernel rejected. batch_seq is the
1-indexed position of the offending message within
inner_messages (the BATCH_BEGIN envelope is position 0; not
returned).
The envelope messages do not themselves get ACKs from the kernel — BATCH_BEGIN merely opens the transaction, BATCH_END commits it. Per-inner-message validation errors are returned during the prep phase; commit-time failures (e.g. BATCH_GENID mismatch) surface here too, attributed to the inner message that triggered them.
Each call allocates fresh sequence numbers from the socket's counter, so concurrent users of the same socket cannot collide.
@spec open(Linx.Netlink.Socket.netns()) :: {:ok, Linx.Netlink.Socket.t()} | {:error, term()}
Opens an nfnetlink socket in network namespace netns.
See Linx.Netlink.Socket.open/2 for the netns forms (:host,
{:pid, n}, {:path, p}). Close the socket with
Linx.Netlink.Socket.close/1.