# `Linx.Netfilter.Log`
[🔗](https://github.com/oshlabs/linx/blob/v0.2.0/lib/linx/netfilter/log.ex#L1)

NFLOG listener — receives per-packet events from the kernel's
`NFNL_SUBSYS_ULOG` (sub-subsystem 4) for rules that include
`Linx.Netfilter.Expr.log/1`.

## Lifecycle

    {:ok, listener} = Linx.Netfilter.log_listen(self(),
      group: 5000,
      copy_mode: {:packet, 256},
      flags: [:seq])

    receive do
      {:linx_netfilter, :log, %Linx.Netfilter.Log.Event{} = ev} ->
        IO.inspect(ev.prefix, label: "log")
    end

    :ok = Linx.Netfilter.unlog_listen(listener)

## Group binding

Each NFLOG group is independent. On start, the listener sends:

  * `NFULNL_CFG_CMD_BIND` for the chosen group.
  * `NFULNL_CFG_CMD_PF_BIND` for each address family in
    `:families` (default `[:ipv4, :ipv6]`). Required so the
    kernel actually invokes the NFLOG hook for matching
    packets.
  * `NFULA_CFG_MODE` for the copy mode.
  * `NFULA_CFG_FLAGS` for the flag bitmask.
  * Optional `NFULA_CFG_TIMEOUT` and `NFULA_CFG_QTHRESH` for
    batching.

## Linx convention: group 5000

Group ids 1..65535 are caller-supplied. Linx reserves **group
5000** as the recommended default for "I don't care which group
as long as it's mine" — documented as convention, not a
hard-coded default for the API.

## ENOBUFS recovery

Same shape as `Linx.Netfilter.Monitor`: a `:resync_needed`
message tells the owner that messages were dropped at the
kernel-socket boundary. The owner can choose to ignore (the
next event will still arrive) or re-bind for a clean slate.

# `opt`

```elixir
@type opt() ::
  {:owner, pid()}
  | {:group, 1..65535}
  | {:netns, Linx.Netlink.Socket.netns()}
  | {:copy_mode, :none | :meta | :packet | {:packet, non_neg_integer()}}
  | {:qthresh, 1..1024}
  | {:timeout_ms, non_neg_integer()}
  | {:flags, [:seq | :seq_global | :conntrack]}
  | {:families, [:ipv4 | :ipv6 | :bridge | :arp]}
  | {:rcvbuf, pos_integer()}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `start_link`

```elixir
@spec start_link([opt()]) :: GenServer.on_start()
```

Starts a Log listener linked to the caller.

Required:
  * `:owner` — pid that receives `{:linx_netfilter, :log, %Event{}}`
  * `:group` — NFLOG group (1..65535)

Optional:
  * `:netns` — namespace; default `:host`
  * `:copy_mode` — `:none` | `:meta` | `:packet` (full packet, up
    to default snaplen) | `{:packet, snaplen_bytes}`. Default `:meta`.
  * `:qthresh` — kernel-side queue threshold (1..1024). Default
    `1` (forward each packet immediately).
  * `:timeout_ms` — kernel-side batching timeout in ms; 0 means
    no time-based batching. Default `0`.
  * `:flags` — `:seq` / `:seq_global` / `:conntrack`.
  * `:families` — protocol families to bind via PF_BIND; default
    `[:ipv4, :ipv6]`.
  * `:rcvbuf` — SO_RCVBUF size in bytes; default 4 MiB.

# `stop`

```elixir
@spec stop(pid()) :: :ok
```

Stops the listener (also sends NFULNL_CFG_CMD_UNBIND).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
