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

A GenServer that owns a multicast nfnetlink socket subscribed to
`NFNLGRP_NFTABLES`, decodes each broadcast message into a
`%Linx.Netfilter.Event{}`, and forwards it to the owner pid.

## Lifecycle

    {:ok, monitor} = Linx.Netfilter.subscribe()
    # → caller process receives:
    #   {:linx_netfilter, :event, %Linx.Netfilter.Event{...}}
    #   {:linx_netfilter, :resync_needed}    (on ENOBUFS)
    :ok = Linx.Netfilter.unsubscribe(monitor)

## Event grouping

The kernel broadcasts one `NEW_GEN` message at the start of each
committed transaction, then one event per entity in that commit.
The Monitor tracks the most recent `NEW_GEN` and attaches its
`gen_id` / `proc_pid` / `proc_name` to every subsequent entity
event, so each `%Event{}` carries full provenance.

## ENOBUFS recovery

If the multicast traffic outpaces the consumer, the kernel
drops messages and the next recv returns `:enobufs`. The
Monitor emits `{:linx_netfilter, :resync_needed}` to the owner
and continues reading; the owner is responsible for re-running
`pull/1..2` to re-sync state.

Default `SO_RCVBUF` is bumped to 4 MiB at start to reduce
the likelihood of overflow.

## Snapshot+tail

`subscribe/1` accepts a `:since_gen` option — events with
`gen_id <= since_gen` are silently dropped. The canonical
pattern (no race with the kernel):

    {:ok, m} = Linx.Netfilter.subscribe()
    {:ok, gen} = Linx.Netlink.Nfnl.Codec.get_gen(some_socket)
    Linx.Netfilter.Monitor.set_min_gen(m, gen.id)
    {:ok, snapshot} = Linx.Netfilter.pull(some_socket)
    # → all events with gen_id > gen.id flow to the owner
    #   (events already captured in the snapshot are filtered)

`Linx.Netfilter.pull/1..2` exposes a `:subscribe_first` shortcut
that does this whole dance in one call.

# `opt`

```elixir
@type opt() ::
  {:owner, pid()}
  | {:netns, Linx.Netlink.Socket.netns()}
  | {:since_gen, non_neg_integer()}
  | {:rcvbuf, pos_integer()}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `set_min_gen`

```elixir
@spec set_min_gen(pid(), non_neg_integer()) :: :ok
```

Sets the minimum gen — subsequent events whose `gen_id` is
greater than this value will be delivered; events at or below
are filtered out. Used by `pull(..., subscribe_first: monitor)`
to drop events already captured in the snapshot.

# `start_link`

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

Starts a Monitor linked to the caller, subscribed to
`NFNLGRP_NFTABLES`.

Options:

  * `:owner` (required) — pid that receives `{:linx_netfilter, _}`
    messages.
  * `:netns` — namespace to monitor; defaults to `:host`.
  * `:since_gen` — initial floor; events with `gen_id <=`
    this value are dropped. Defaults to `0` (everything flows).
  * `:rcvbuf` — `SO_RCVBUF` size in bytes; default 4 MiB.

# `stop`

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

Stops the Monitor (closes its socket).

---

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