Skip to content

Commit 79e321d

Browse files
committed
Added Other expression type to support types that are not explicitly supported.
This replaces the previous behaviour of silently ignoring unkown types when decoding
1 parent a285ace commit 79e321d

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

expr/other.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package expr
2+
3+
import (
4+
"encoding/binary"
5+
6+
"github.com/mdlayher/netlink"
7+
"golang.org/x/sys/unix"
8+
)
9+
10+
// Other is a nft expression that this library don't know
11+
// It can unmarshal/marshal it as list of attributes
12+
type Other struct {
13+
Type string // the type (name) of the expression
14+
Attributes []OtherAttribute
15+
}
16+
17+
// OtherAttribute is one of the attributes in an Other
18+
type OtherAttribute struct {
19+
Type uint16
20+
Data []byte
21+
}
22+
23+
func (e *Other) marshal() ([]byte, error) {
24+
attrs := make([]netlink.Attribute, len(e.Attributes))
25+
for i, a := range e.Attributes {
26+
attrs[i].Type = a.Type
27+
attrs[i].Data = a.Data
28+
}
29+
30+
data, err := netlink.MarshalAttributes(attrs)
31+
if err != nil {
32+
return nil, err
33+
}
34+
return netlink.MarshalAttributes([]netlink.Attribute{
35+
{Type: unix.NFTA_EXPR_NAME, Data: []byte(e.Type + "\x00")},
36+
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
37+
})
38+
}
39+
40+
func (e *Other) unmarshal(data []byte) error {
41+
ad, err := netlink.NewAttributeDecoder(data)
42+
if err != nil {
43+
return err
44+
}
45+
ad.ByteOrder = binary.BigEndian
46+
for ad.Next() {
47+
e.Attributes = append(e.Attributes, OtherAttribute{Type: ad.Type(), Data: ad.Bytes()})
48+
}
49+
return ad.Err()
50+
}

expr/other_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package expr
2+
3+
import (
4+
"encoding/binary"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/mdlayher/netlink"
9+
"golang.org/x/sys/unix"
10+
)
11+
12+
func TestOther(t *testing.T) {
13+
orig := &Other{
14+
Type: "testing",
15+
Attributes: []OtherAttribute{
16+
{1, []byte{66, 5}},
17+
{5, []byte("test")},
18+
},
19+
}
20+
21+
data, err := Marshal(orig)
22+
if err != nil {
23+
t.Fatal("Error marshalling other: ", err)
24+
}
25+
26+
ad, err := netlink.NewAttributeDecoder(data)
27+
if err != nil {
28+
t.Fatalf("NewAttributeDecoder() error: %+v", err)
29+
}
30+
ad.ByteOrder = binary.BigEndian
31+
if !ad.Next() {
32+
t.Fatal("too short")
33+
}
34+
if ad.Type() != unix.NFTA_EXPR_NAME || ad.String() != orig.Type {
35+
t.Fatalf("wrong name %d:%q", ad.Type(), ad.String())
36+
}
37+
38+
if !ad.Next() {
39+
t.Fatal("too short")
40+
}
41+
decoded := &Other{Type: "testing"}
42+
if ad.Type() != unix.NFTA_EXPR_DATA {
43+
t.Fatal("Wrong type for data:", ad.Type())
44+
}
45+
if err := Unmarshal(ad.Bytes(), decoded); err != nil {
46+
t.Fatal(err)
47+
}
48+
if !reflect.DeepEqual(orig, decoded) {
49+
t.Errorf("Wrong structure decoded: %+v vs %+v", decoded, orig)
50+
}
51+
if ad.Next() {
52+
t.Error("Got extra attribute: ", ad.Type())
53+
}
54+
}

rule.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,8 @@ func exprsFromMsg(b []byte) ([]expr.Any, error) {
248248
e = &expr.Limit{}
249249
case "dynset":
250250
e = &expr.Dynset{}
251-
}
252-
if e == nil {
253-
// TODO: introduce an opaque expression type so that users know
254-
// something is here.
255-
continue // unsupported expression type
251+
default:
252+
e = &expr.Other{Type: name}
256253
}
257254

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

0 commit comments

Comments
 (0)