Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions nftables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7462,6 +7462,61 @@ func TestSetElementComment(t *testing.T) {
}
}

func TestSetElementIntervalOpen(t *testing.T) {
conn, newNS := nftest.OpenSystemConn(t, *enableSysTests)
defer nftest.CleanupSystemConn(t, newNS)
conn.FlushRuleset()
defer conn.FlushRuleset()

table := &nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "test-table",
}
conn.AddTable(table)
set := &nftables.Set{
Name: "test-set",
Table: table,
KeyType: nftables.TypeIPAddr,
Interval: true,
}
elements := []nftables.SetElement{
// 10.0.0.0/24
{
Key: net.ParseIP("10.0.0.0").To4(),
},
{
Key: net.ParseIP("10.0.1.0").To4(),
IntervalEnd: true,
},
// 255.255.255.254/31 (open interval)
{
Key: net.ParseIP("255.255.255.254").To4(),
IntervalOpen: true,
},
}
if err := conn.AddSet(set, elements); err != nil {
t.Fatalf("failed to add set: %v", err)
}
if err := conn.Flush(); err != nil {
t.Fatalf("failed to flush: %v", err)
}

gotElements, err := conn.GetSetElements(set)
if err != nil {
t.Fatalf("failed to get set elements: %v", err)
}
if got, want := len(gotElements), len(elements); got != want {
t.Fatalf("got %d elements, want %d", got, want)
}

// Reverse the gotElements slice to match the order of elements
slices.Reverse(gotElements)

if !reflect.DeepEqual(gotElements, elements) {
t.Errorf("got elements %+v, want %+v", gotElements, elements)
}
}

func TestAutoBufferSize(t *testing.T) {
conn, newNS := nftest.OpenSystemConn(t, *enableSysTests)
defer nftest.CleanupSystemConn(t, newNS)
Expand Down
13 changes: 12 additions & 1 deletion set.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ type SetElement struct {

Counter *expr.Counter
Comment string
// Indicates an unbounded interval [start, ∞) with no end element.
IntervalOpen bool
}

func (s *SetElement) decode(fam byte) func(b []byte) error {
Expand Down Expand Up @@ -333,6 +335,9 @@ func (s *SetElement) decode(fam byte) func(b []byte) error {
if comment, ok := userdata.GetString(userData, userdata.NFTNL_UDATA_SET_ELEM_COMMENT); ok {
s.Comment = comment
}
if userDataFlags, ok := userdata.GetUint32(userData, userdata.NFTNL_UDATA_SET_ELEM_FLAGS); ok {
s.IntervalOpen = (userDataFlags & userdata.NFTNL_UDATA_SET_ELEM_F_INTERVAL_OPEN) != 0
}
case unix.NFTA_SET_ELEM_EXPR:
elems, err := parseexprfunc.ParseExprBytesFunc(fam, ad)
if err != nil {
Expand Down Expand Up @@ -541,9 +546,15 @@ func (cc *Conn) marshalSetElement(s *Set, e *SetElement) ([]byte, error) {
// If niether of previous cases matche, it means 'e' is an element of a regular Set, no need to add to the attributes
}

userData := []byte{}
// Add comment to userdata if present
if len(e.Comment) > 0 {
userData := userdata.AppendString(nil, userdata.NFTNL_UDATA_SET_ELEM_COMMENT, e.Comment)
userData = userdata.AppendString(userData, userdata.NFTNL_UDATA_SET_ELEM_COMMENT, e.Comment)
}
if e.IntervalOpen {
userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_ELEM_FLAGS, userdata.NFTNL_UDATA_SET_ELEM_F_INTERVAL_OPEN)
}
if len(userData) > 0 {
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_USERDATA, Data: userData})
}

Expand Down
6 changes: 6 additions & 0 deletions userdata/userdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ const (
NFTNL_UDATA_SET_ELEM_FLAGS
)

// Set element userdata flags
// https://git.netfilter.org/libnftnl/tree/include/libnftnl/udata.h?id=d36691a4ac486857fd437d3a9aa3701a073a9539#n71
const (
NFTNL_UDATA_SET_ELEM_F_INTERVAL_OPEN uint32 = 0x01
)

func Append(udata []byte, typ Type, data []byte) []byte {
udata = append(udata, byte(typ), byte(len(data)))
udata = append(udata, data...)
Expand Down