Added Other expression type to support types that are not explicitly supported.
This replaces the previous behaviour of silently ignoring unkown types when decoding
This commit is contained in:
parent
a285acebca
commit
79e321dfab
|
@ -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()
|
||||||
|
}
|
|
@ -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
rule.go
7
rule.go
|
@ -248,11 +248,8 @@ func exprsFromMsg(b []byte) ([]expr.Any, error) {
|
||||||
e = &expr.Limit{}
|
e = &expr.Limit{}
|
||||||
case "dynset":
|
case "dynset":
|
||||||
e = &expr.Dynset{}
|
e = &expr.Dynset{}
|
||||||
}
|
default:
|
||||||
if e == nil {
|
e = &expr.Other{Type: name}
|
||||||
// TODO: introduce an opaque expression type so that users know
|
|
||||||
// something is here.
|
|
||||||
continue // unsupported expression type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ad.Do(func(b []byte) error {
|
ad.Do(func(b []byte) error {
|
||||||
|
|
Loading…
Reference in New Issue