Skip to content

Commit

Permalink
Added Other expression type to support types that are not explicitly …
Browse files Browse the repository at this point in the history
…supported.

This replaces the previous behaviour of silently ignoring unkown types
when decoding
  • Loading branch information
moshelitvin-MS committed Jun 1, 2021
1 parent a285ace commit 5a47357
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 5 deletions.
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

0 comments on commit 5a47357

Please sign in to comment.