Compare commits

..

1 Commits

Author SHA1 Message Date
turekt ac32e1ceb5 Add ct expect support 2024-09-01 23:42:12 +02:00
4 changed files with 12 additions and 108 deletions

View File

@ -226,20 +226,16 @@ func (c *CtExpect) marshal(fam byte) ([]byte, error) {
} }
func (c *CtExpect) marshalData(fam byte) ([]byte, error) { func (c *CtExpect) marshalData(fam byte) ([]byte, error) {
// all elements except l3proto must be defined // all elements must be defined
// per https://git.netfilter.org/nftables/tree/doc/stateful-objects.txt?id=db70959a5ccf2952b218f51c3d529e186a5a43bb#n119 // per https://git.netfilter.org/nftables/tree/doc/stateful-objects.txt?id=db70959a5ccf2952b218f51c3d529e186a5a43bb#n119
// from man page: l3proto is derived from the table family by default
exprData := []netlink.Attribute{ exprData := []netlink.Attribute{
{Type: NFTA_CT_EXPECT_L3PROTO, Data: binaryutil.BigEndian.PutUint16(c.L3Proto)},
{Type: NFTA_CT_EXPECT_L4PROTO, Data: []byte{c.L4Proto}}, {Type: NFTA_CT_EXPECT_L4PROTO, Data: []byte{c.L4Proto}},
{Type: NFTA_CT_EXPECT_DPORT, Data: binaryutil.BigEndian.PutUint16(c.DPort)}, {Type: NFTA_CT_EXPECT_DPORT, Data: binaryutil.BigEndian.PutUint16(c.DPort)},
{Type: NFTA_CT_EXPECT_TIMEOUT, Data: binaryutil.BigEndian.PutUint32(c.Timeout)}, {Type: NFTA_CT_EXPECT_TIMEOUT, Data: binaryutil.BigEndian.PutUint32(c.Timeout)},
{Type: NFTA_CT_EXPECT_SIZE, Data: []byte{c.Size}}, {Type: NFTA_CT_EXPECT_SIZE, Data: []byte{c.Size}},
} }
if c.L3Proto != 0 {
attr := netlink.Attribute{Type: NFTA_CT_EXPECT_L3PROTO, Data: binaryutil.BigEndian.PutUint16(c.L3Proto)}
exprData = append(exprData, attr)
}
return netlink.MarshalAttributes(exprData) return netlink.MarshalAttributes(exprData)
} }

View File

@ -1486,7 +1486,7 @@ func TestCtExpect(t *testing.T) {
defer conn.FlushRuleset() defer conn.FlushRuleset()
table := conn.AddTable(&nftables.Table{ table := conn.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4, Family: nftables.TableFamilyINet,
Name: "filter", Name: "filter",
}) })
@ -1498,8 +1498,8 @@ func TestCtExpect(t *testing.T) {
L3Proto: unix.NFPROTO_IPV4, L3Proto: unix.NFPROTO_IPV4,
L4Proto: unix.IPPROTO_TCP, L4Proto: unix.IPPROTO_TCP,
DPort: 53, DPort: 53,
Timeout: 20, Timeout: 2000,
Size: 100, Size: 1,
}, },
} }
@ -3564,66 +3564,6 @@ func TestCreateUseNamedSet(t *testing.T) {
} }
} }
func TestCreateAutoMergeSet(t *testing.T) {
// Create a new network namespace to test these operations,
// and tear down the namespace at test completion.
c, newNS := nftest.OpenSystemConn(t, *enableSysTests)
defer nftest.CleanupSystemConn(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,
Interval: true,
AutoMerge: 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)
}
ipSet := &nftables.Set{
Table: filter,
Name: "IPs_4_dayz",
KeyType: nftables.TypeIPAddr,
Interval: true,
AutoMerge: true,
}
if err := c.AddSet(ipSet, []nftables.SetElement{{Key: []byte(net.ParseIP("192.168.1.64").To4())}}); err != nil {
t.Errorf("c.AddSet(ipSet) failed: %v", err)
}
if err := c.SetAddElements(ipSet, []nftables.SetElement{{Key: []byte(net.ParseIP("192.168.1.42").To4())}}); err != nil {
t.Errorf("c.SetVal(ipSet) 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) != 2 {
t.Fatalf("len(sets) = %d, want 2", len(sets))
}
if !sets[0].AutoMerge {
t.Errorf("set[0].AutoMerge = %v, want true", sets[0].AutoMerge)
}
if !sets[1].AutoMerge {
t.Errorf("set[1].AutoMerge = %v, want true", sets[1].AutoMerge)
}
}
func TestIP6SetAddElements(t *testing.T) { func TestIP6SetAddElements(t *testing.T) {
// Create a new network namespace to test these operations, // Create a new network namespace to test these operations,
// and tear down the namespace at test completion. // and tear down the namespace at test completion.

29
set.go
View File

@ -21,10 +21,10 @@ import (
"strings" "strings"
"time" "time"
"github.com/google/nftables/binaryutil"
"github.com/google/nftables/expr" "github.com/google/nftables/expr"
"github.com/google/nftables/internal/parseexprfunc" "github.com/google/nftables/internal/parseexprfunc"
"github.com/google/nftables/userdata"
"github.com/google/nftables/binaryutil"
"github.com/mdlayher/netlink" "github.com/mdlayher/netlink"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -249,7 +249,6 @@ type Set struct {
Anonymous bool Anonymous bool
Constant bool Constant bool
Interval bool Interval bool
AutoMerge bool
IsMap bool IsMap bool
HasTimeout bool HasTimeout bool
Counter bool Counter bool
@ -581,27 +580,15 @@ func (cc *Conn) AddSet(s *Set, vals []SetElement) error {
// Marshal concat size description as set description // Marshal concat size description as set description
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: concatBytes}) tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: concatBytes})
} }
// https://git.netfilter.org/libnftnl/tree/include/udata.h#n17
var userData []byte
if s.Anonymous || s.Constant || s.Interval || s.KeyByteOrder == binaryutil.BigEndian { if s.Anonymous || s.Constant || s.Interval || s.KeyByteOrder == binaryutil.BigEndian {
tableInfo = append(tableInfo,
// Semantically useless - kept for binary compatability with nft // Semantically useless - kept for binary compatability with nft
userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_KEYBYTEORDER, 2) netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x02\x00\x00\x00")})
} else if s.KeyByteOrder == binaryutil.NativeEndian { } else if s.KeyByteOrder == binaryutil.NativeEndian {
// Per https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1165 // Per https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1165
userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_KEYBYTEORDER, 1) tableInfo = append(tableInfo,
netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x01\x00\x00\x00")})
} }
if s.Interval && s.AutoMerge {
// https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1174
userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_MERGE_ELEMENTS, 1)
}
if len(userData) > 0 {
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: userData})
}
if s.Counter { if s.Counter {
data, err := netlink.MarshalAttributes([]netlink.Attribute{ data, err := netlink.MarshalAttributes([]netlink.Attribute{
{Type: unix.NFTA_LIST_ELEM, Data: []byte("counter\x00")}, {Type: unix.NFTA_LIST_ELEM, Data: []byte("counter\x00")},
@ -753,10 +740,6 @@ func setsFromMsg(msg netlink.Message) (*Set, error) {
set.DataType = dt set.DataType = dt
case unix.NFTA_SET_DATA_LEN: case unix.NFTA_SET_DATA_LEN:
set.DataType.Bytes = binary.BigEndian.Uint32(ad.Bytes()) set.DataType.Bytes = binary.BigEndian.Uint32(ad.Bytes())
case unix.NFTA_SET_USERDATA:
data := ad.Bytes()
value, ok := userdata.GetUint32(data, userdata.NFTNL_UDATA_SET_MERGE_ELEMENTS)
set.AutoMerge = ok && value == 1
} }
} }
return &set, nil return &set, nil

View File

@ -31,21 +31,6 @@ const (
TypesCount TypesCount
) )
// TLV type values are defined in:
// https://git.netfilter.org/libnftnl/tree/include/libnftnl/udata.h#n39
const (
NFTNL_UDATA_SET_KEYBYTEORDER Type = iota
NFTNL_UDATA_SET_DATABYTEORDER
NFTNL_UDATA_SET_MERGE_ELEMENTS
NFTNL_UDATA_SET_KEY_TYPEOF
NFTNL_UDATA_SET_DATA_TYPEOF
NFTNL_UDATA_SET_EXPR
NFTNL_UDATA_SET_DATA_INTERVAL
NFTNL_UDATA_SET_COMMENT
NFTNL_UDATA_SET_MAX
)
func Append(udata []byte, typ Type, data []byte) []byte { func Append(udata []byte, typ Type, data []byte) []byte {
udata = append(udata, byte(typ), byte(len(data))) udata = append(udata, byte(typ), byte(len(data)))
udata = append(udata, data...) udata = append(udata, data...)