Skip to content
Open
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
50 changes: 50 additions & 0 deletions expr/other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package expr

import (
"encoding/binary"

"github.com/mdlayher/netlink"
"golang.org/x/sys/unix"
)

// Other is a nft expression that this library don't know
// It can unmarshal/marshal it as list of attributes
type Other struct {
Type string // the type (name) of the expression
Attributes []OtherAttribute
}

// OtherAttribute is one of the attributes in an Other
type OtherAttribute struct {
Type uint16
Data []byte
}

func (e *Other) marshal() ([]byte, error) {
attrs := make([]netlink.Attribute, len(e.Attributes))
for i, a := range e.Attributes {
attrs[i].Type = a.Type
attrs[i].Data = a.Data
}

data, err := netlink.MarshalAttributes(attrs)
if err != nil {
return nil, err
}
return netlink.MarshalAttributes([]netlink.Attribute{
{Type: unix.NFTA_EXPR_NAME, Data: []byte(e.Type + "\x00")},
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
})
}

func (e *Other) unmarshal(data []byte) error {
ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
return err
}
ad.ByteOrder = binary.BigEndian
for ad.Next() {
e.Attributes = append(e.Attributes, OtherAttribute{Type: ad.Type(), Data: ad.Bytes()})
}
return ad.Err()
}
54 changes: 54 additions & 0 deletions expr/other_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package expr

import (
"encoding/binary"
"reflect"
"testing"

"github.com/mdlayher/netlink"
"golang.org/x/sys/unix"
)

func TestOther(t *testing.T) {
orig := &Other{
Type: "testing",
Attributes: []OtherAttribute{
{1, []byte{66, 5}},
{5, []byte("test")},
},
}

data, err := Marshal(orig)
if err != nil {
t.Fatal("Error marshalling other: ", err)
}

ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
t.Fatalf("NewAttributeDecoder() error: %+v", err)
}
ad.ByteOrder = binary.BigEndian
if !ad.Next() {
t.Fatal("too short")
}
if ad.Type() != unix.NFTA_EXPR_NAME || ad.String() != orig.Type {
t.Fatalf("wrong name %d:%q", ad.Type(), ad.String())
}

if !ad.Next() {
t.Fatal("too short")
}
decoded := &Other{Type: "testing"}
if ad.Type() != unix.NFTA_EXPR_DATA {
t.Fatal("Wrong type for data:", ad.Type())
}
if err := Unmarshal(ad.Bytes(), decoded); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(orig, decoded) {
t.Errorf("Wrong structure decoded: %+v vs %+v", decoded, orig)
}
if ad.Next() {
t.Error("Got extra attribute: ", ad.Type())
}
}
7 changes: 2 additions & 5 deletions rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,8 @@ func exprsFromMsg(b []byte) ([]expr.Any, error) {
e = &expr.Limit{}
case "dynset":
e = &expr.Dynset{}
}
if e == nil {
// TODO: introduce an opaque expression type so that users know
// something is here.
continue // unsupported expression type
default:
e = &expr.Other{Type: name}
}

ad.Do(func(b []byte) error {
Expand Down