Compare commits

..

2 Commits

Author SHA1 Message Date
Michael Stapelberg 3ad45c080c use “test” as set name in tests 2022-10-29 08:34:19 +02:00
Joe Williams 0929dfc8bf
Support set element counters (#199) 2022-10-29 08:33:22 +02:00
2 changed files with 67 additions and 11 deletions

View File

@ -2552,7 +2552,7 @@ func TestCreateUseNamedSet(t *testing.T) {
portSet := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(portSet, nil); err != nil {
@ -2584,8 +2584,8 @@ func TestCreateUseNamedSet(t *testing.T) {
if len(sets) != 2 {
t.Fatalf("len(sets) = %d, want 2", len(sets))
}
if sets[0].Name != "kek" {
t.Errorf("set[0].Name = %q, want kek", sets[0].Name)
if sets[0].Name != "test" {
t.Errorf("set[0].Name = %q, want test", sets[0].Name)
}
if sets[1].Name != "IPs_4_dayz" {
t.Errorf("set[1].Name = %q, want IPs_4_dayz", sets[1].Name)
@ -2642,6 +2642,49 @@ func TestIP6SetAddElements(t *testing.T) {
}
}
func TestCreateUseCounterSet(t *testing.T) {
// Create a new network namespace to test these operations,
// and tear down the namespace at test completion.
c, newNS := openSystemNFTConn(t)
defer cleanupSystemNFTConn(t, newNS)
// Clear all rules at the beginning + end of the test.
c.FlushRuleset()
defer c.FlushRuleset()
filter := c.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "filter",
})
portSet := &nftables.Set{
Table: filter,
Name: "test",
KeyType: nftables.TypeInetService,
Counter: true,
}
if err := c.AddSet(portSet, nil); err != nil {
t.Errorf("c.AddSet(portSet) failed: %v", err)
}
if err := c.SetAddElements(portSet, []nftables.SetElement{{Key: binaryutil.BigEndian.PutUint16(22)}}); err != nil {
t.Errorf("c.SetVal(portSet) failed: %v", err)
}
if err := c.Flush(); err != nil {
t.Errorf("c.Flush() failed: %v", err)
}
sets, err := c.GetSets(filter)
if err != nil {
t.Errorf("c.GetSets() failed: %v", err)
}
if len(sets) != 1 {
t.Fatalf("len(sets) = %d, want 1", len(sets))
}
if sets[0].Name != "test" {
t.Errorf("set[0].Name = %q, want test", sets[0].Name)
}
}
func TestCreateDeleteNamedSet(t *testing.T) {
// Create a new network namespace to test these operations,
// and tear down the namespace at test completion.
@ -2658,7 +2701,7 @@ func TestCreateDeleteNamedSet(t *testing.T) {
portSet := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(portSet, nil); err != nil {
@ -2699,7 +2742,7 @@ func TestDeleteElementNamedSet(t *testing.T) {
portSet := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(portSet, []nftables.SetElement{{Key: []byte{0, 22}}, {Key: []byte{0, 23}}}); err != nil {
@ -2746,7 +2789,7 @@ func TestFlushNamedSet(t *testing.T) {
portSet := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(portSet, []nftables.SetElement{{Key: []byte{0, 22}}, {Key: []byte{0, 23}}}); err != nil {
@ -3202,7 +3245,7 @@ func TestGetLookupExprDestSet(t *testing.T) {
set := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
IsMap: true,
KeyType: nftables.TypeInetService,
DataType: nftables.TypeVerdict,
@ -3301,7 +3344,7 @@ func TestGetRuleLookupVerdictImmediate(t *testing.T) {
set := &nftables.Set{
Table: filter,
Name: "kek",
Name: "test",
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(set, nil); err != nil {
@ -3340,10 +3383,10 @@ func TestGetRuleLookupVerdictImmediate(t *testing.T) {
&expr.Verdict{
Kind: expr.VerdictAccept,
},
// [ immediate reg 2 kek ]
// [ immediate reg 2 test ]
&expr.Immediate{
Register: 2,
Data: []byte("kek"),
Data: []byte("test"),
},
},
})
@ -3399,7 +3442,7 @@ func TestGetRuleLookupVerdictImmediate(t *testing.T) {
}
if want := (&expr.Immediate{
Register: 2,
Data: []byte("kek"),
Data: []byte("test"),
}); !reflect.DeepEqual(imm, want) {
t.Errorf("verdict expr = %+v, wanted %+v", imm, want)
}

13
set.go
View File

@ -40,6 +40,8 @@ const (
NFTA_SET_DESC_CONCAT = 2
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n428
NFTA_SET_ELEM_KEY_END = 10
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n429
NFTA_SET_ELEM_EXPRESSIONS = 0x11
)
var allocSetID uint32
@ -235,6 +237,7 @@ type Set struct {
Interval bool
IsMap bool
HasTimeout bool
Counter bool
// Can be updated per evaluation path, per `nft list ruleset`
// indicates that set contains "flags dynamic"
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n298
@ -548,6 +551,16 @@ func (cc *Conn) AddSet(s *Set, vals []SetElement) error {
tableInfo = append(tableInfo,
netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x01\x00\x00\x00")})
}
if s.Counter {
data, err := netlink.MarshalAttributes([]netlink.Attribute{
{Type: unix.NFTA_LIST_ELEM, Data: []byte("counter\x00")},
{Type: unix.NFTA_SET_ELEM_PAD | unix.NFTA_SET_ELEM_DATA, Data: []byte{}},
})
if err != nil {
return err
}
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | NFTA_SET_ELEM_EXPRESSIONS, Data: data})
}
cc.messages = append(cc.messages, netlink.Message{
Header: netlink.Header{