# `Linx.Netlink.Socket.Native`
[🔗](https://github.com/oshlabs/linx/blob/v0.2.0/lib/linx/netlink/socket/native.ex#L1)

The native half of `Linx.Netlink.Socket`: opens an `AF_NETLINK` socket
*inside* a given network namespace.

This is a NIF (`c_src/netlink_socket.c`), loaded into the BEAM. It exists
because `Linx.Netlink` is otherwise pure Elixir: the BEAM can open and drive
a netlink socket itself, but only in *its own* network namespace. Reaching
another netns needs `setns(2)`, which acts per-thread — unsafe to run on a
BEAM scheduler, where it would strand unrelated work in the wrong namespace.

`open_in_netns/2` does the `setns` on a private, throwaway thread that opens
the socket and then exits. A socket is permanently bound to the netns that
was current when it was created, so the fd outlives the thread and is usable
from any BEAM thread afterward.

The result is a raw integer fd. The caller adopts it — typically with
`:socket.open/1` — and is then responsible for closing it.

# `bind_netlink`

```elixir
@spec bind_netlink(non_neg_integer(), non_neg_integer()) :: :ok | {:error, integer()}
```

Binds a netlink socket fd to `nl_pid = 0` (kernel-auto-assigned)
with the given group-membership bitmask.

Erlang's `:socket.bind/2` does not accept netlink `sockaddr_nl`,
so the bind goes through this NIF. Use `groups = 0` for a plain
bind (e.g. to enable multicast reception via
`NETLINK_ADD_MEMBERSHIP` setsockopt later — the socket must be
bound to receive multicast events at all).

# `close_fd`

```elixir
@spec close_fd(non_neg_integer()) :: :ok
```

Closes a descriptor returned by `open_in_netns/2`.

Needed only on the error path where `:socket.open/1` declines to adopt the
fd, leaving it owned by Elixir rather than by a socket object. On the normal
path the adopting socket owns the fd and closes it. Always returns `:ok`.

# `open_in_netns`

```elixir
@spec open_in_netns(binary(), non_neg_integer()) ::
  {:ok, non_neg_integer()} | {:error, {atom(), integer()}}
```

Opens a netlink socket of `protocol` inside the network namespace named by
`netns_path` and returns `{:ok, fd}` — a raw, netns-pinned file descriptor.

`netns_path` names a network-namespace file: typically `/proc/<pid>/ns/net`,
or `/proc/self/ns/net` for the BEAM's own (host) network namespace.
`protocol` is the netlink protocol number passed to `socket(2)` — e.g.
`NETLINK_ROUTE` (0) or `NETLINK_GENERIC` (16).

On failure returns `{:error, {stage, errno}}`, where `stage` is `:open`,
`:setns`, `:socket` or `:thread` and `errno` is the integer error number of
the failing step.

The returned fd belongs to the caller and is not closed by this module.

---

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