Commit 0d9bfa4d18 added code to handle "overrun", but the commit is
very misleading. NLMSG_OVERRUN is in fact not a flag, but a complete
message type, so the (re&netlink.Overrun) masking makes no sense. Even
better, NLMSG_OVERRUN is never actually used by Linux.
The actual bug which the commit was attempting to fix is that Flush was
not receiving replies which the kernel sent for messages with the echo
flag. This change reverts that commit and instead adds code in Flush to
receive the replies.
I updated tests which simulate the kernel to generate replies.
The ID allows referring to a rule before it is committed, as
demonstrated in the newly added test.
I had to update all existing tests which compared generated netlink
messages against a reference, by inserting the newly added ID attribute.
There was an existing mechanism to allocate IDs for sets, but this was
using a global counter without any synchronization to prevent data
races. I replaced this by a new mechanism which uses a connection-scoped
counter, protected by the Conn.mu Mutex. This can then also be used in
other places where IDs need to be allocated.
As an additional safeguard, it will panic instead of allocating the same
ID twice in a transaction. Most likely, your program will run out of
memory before reaching this point.
If the number of elements to be added to or removed from a set is large,
they may not all fit into one message, because the size field of a
netlink attribute is a uint16 and would overflow. To support this case,
the elements need to be split into multiple batches.
This commit adds integration tests to the nftables package to verify
that the Go code correctly programs nftables rules. The tests use
external nftables scripts to define the expected state and compare
it with the state produced by the Go code.
Change-Id: I9c8439ee462b4882b221e6244f53379b822446dc
Signed-off-by: Antonio Ojea <aojea@google.com>
Turns out we cannot make github.com/google/nftables/binaryutil
forward to encoding/binary because it’s not an API-compatible
drop-in replacement: The PutUint* methods allocate in our API,
but do not allocate in encoding/binary.
* fix: resolve deadlock in `Flush` function when handling ENOBUFS error
* Simulate deadlock issue using reduced read/write buffers to verify the fix and ensure no regressions
Note that this will fix support for single expressions on older kernels but multiple expressions on older kernels will remain unsupported as NFT_DYNSET_F_EXPR flag should not be omitted for dynsets with multiple expressions.
* Refactored obj.go to a more generic approach
* Added object support for already implemented expressions
* Added test for limit object
fixes https://github.com/google/nftables/issues/253
`Conn.AddTable` use netlink.Create which will not emit an error
if the table we want to create already existed,
just like the `nft add table ...` command works.
The caller should use netlink.Excl to
get an EEXIST error for that already existed,
So I add another method `Conn.CreateTable`
which works just like `nft create table ...` command.
Related: #245
Signed-off-by: black-desk <me@black-desk.cn>
Related: #242
After 7879d7ecf6, it seems that
any multi-message operation performed without CAP_SYS_ADMIN will
leads to forever block inside nftables.Conn.Flush.
For example:
```go
package main
import "github.com/google/nftables"
func main() {
conn, err := nftables.New()
if err != nil {
panic(err)
}
t := conn.AddTable(&nftables.Table{})
err = conn.AddSet(&nftables.Set{Table: t}, []nftables.SetElement{})
if err != nil {
panic(err)
}
conn.AddSet(&nftables.Set{Table: t}, []nftables.SetElement{})
if err != nil {
panic(err)
}
err = conn.Flush()
if err != nil {
panic(err)
}
return
}
```
That's because that although we send multiple messages on netlink
socket, kernel will only sends one permission error message as reply.
Signed-off-by: black-desk <me@black-desk.cn>