Linx.Netlink.Rtnl.Rule (Linx v0.1.0)

Copy Markdown View Source

rtnetlink policy-routing rules — the FIB rules that decide which routing table to consult for a given packet, based on source address, destination, firewall mark and so on.

list/1 reads rules; add/2 and delete/2 install and remove them. Rules are specified as a keyword list of selectors plus the target table:

Rtnl.Rule.add(socket, from: "10.0.0.0/24", table: 100)
Rtnl.Rule.add(socket, fwmark: 0x1,         table: 100, priority: 200)

:table is required; the family is inferred from the address selectors (:from / :to) — or defaults to IPv4 when only non-address selectors (:fwmark) are used.

Address-typed fields (:src, :dst) on a decoded %Rule{} are Linx.IP structs.

The two table representations

fib_rule_hdr.table is a u8, so tables above 255 are conveyed via the separate FRA_TABLE attribute (mapped to :table_ext); the kernel sets the header byte to RT_TABLE_UNSPEC in that case. target_table/1 returns the effective table — taking :table_ext when present, falling back to :table.

Example

{:ok, sock} = Rtnl.open()

:ok = Rule.add(sock, from: "10.0.0.0/24", table: 100)
:ok = Rule.add(sock, fwmark: 0x1, table: 100, priority: 200)

{:ok, rules} = Rule.list(sock)
# => [..., #Linx.Netlink.Rtnl.Rule<priority=200 fwmark=0x1 table=100>,
#     #Linx.Netlink.Rtnl.Rule<from=10.0.0.0/24 table=100>]

:ok = Rule.delete(sock, from: "10.0.0.0/24", table: 100)

The wire format — struct fib_rule_hdr and the FRA_* attributes (include/uapi/linux/fib_rules.h) — is declared with the Linx.Netlink.Codec DSL.

Summary

Functions

Adds a policy-routing rule.

Decodes a netlink message body into a t/0.

Deletes the policy-routing rule matching opts (same shape as add/2).

Encodes a t/0 into its netlink message body.

Lists every policy-routing rule in the socket's network namespace.

Returns the routing-table number this rule points to.

Types

t()

@type t() :: %Linx.Netlink.Rtnl.Rule{
  action: term(),
  dst: term(),
  dst_len: term(),
  family: term(),
  flags: term(),
  fwmark: term(),
  priority: term(),
  res1: term(),
  res2: term(),
  src: term(),
  src_len: term(),
  table: term(),
  table_ext: term(),
  tos: term()
}

Functions

add(socket, opts)

@spec add(
  Linx.Netlink.Socket.t(),
  keyword()
) :: :ok | {:error, term()}

Adds a policy-routing rule.

Selectors (all optional unless noted):

  • :from — match source "ip/prefix" (CIDR string).
  • :to — match destination "ip/prefix" (CIDR string).
  • :fwmark — match firewall mark (integer).
  • :table — routing table to consult (1..2^32-1). Required.
  • :priority — rule priority (smaller wins; integer).

decode(body)

@spec decode(binary()) :: t()

Decodes a netlink message body into a t/0.

delete(socket, opts)

@spec delete(
  Linx.Netlink.Socket.t(),
  keyword()
) :: :ok | {:error, term()}

Deletes the policy-routing rule matching opts (same shape as add/2).

encode(message)

@spec encode(t()) :: binary()

Encodes a t/0 into its netlink message body.

list(socket)

@spec list(Linx.Netlink.Socket.t()) :: {:ok, [t()]} | {:error, term()}

Lists every policy-routing rule in the socket's network namespace.

target_table(rule)

@spec target_table(t()) :: non_neg_integer()

Returns the routing-table number this rule points to.

Handles both the in-header byte form and the FRA_TABLE extension used for tables above 255.