Add bitwise decoder logic (#71)

This commit is contained in:
Serguei Bezverkhi 2019-11-07 09:38:12 -05:00 committed by Michael Stapelberg
parent dc8c451012
commit e0f4f3f8f8
5 changed files with 121 additions and 13 deletions

View File

@ -15,7 +15,7 @@
package expr package expr
import ( import (
"fmt" "encoding/binary"
"github.com/google/nftables/binaryutil" "github.com/google/nftables/binaryutil"
"github.com/mdlayher/netlink" "github.com/mdlayher/netlink"
@ -61,5 +61,42 @@ func (e *Bitwise) marshal() ([]byte, error) {
} }
func (e *Bitwise) unmarshal(data []byte) error { func (e *Bitwise) unmarshal(data []byte) error {
return fmt.Errorf("not yet implemented") ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
return err
}
ad.ByteOrder = binary.BigEndian
for ad.Next() {
switch ad.Type() {
case unix.NFTA_BITWISE_SREG:
e.SourceRegister = ad.Uint32()
case unix.NFTA_BITWISE_DREG:
e.DestRegister = ad.Uint32()
case unix.NFTA_BITWISE_LEN:
e.Len = ad.Uint32()
case unix.NFTA_BITWISE_MASK:
// Since NFTA_BITWISE_MASK is nested, it requires additional decoding
ad.Nested(func(nad *netlink.AttributeDecoder) error {
for nad.Next() {
switch nad.Type() {
case unix.NFTA_DATA_VALUE:
e.Mask = nad.Bytes()
}
}
return nil
})
case unix.NFTA_BITWISE_XOR:
// Since NFTA_BITWISE_XOR is nested, it requires additional decoding
ad.Nested(func(nad *netlink.AttributeDecoder) error {
for nad.Next() {
switch nad.Type() {
case unix.NFTA_DATA_VALUE:
e.Xor = nad.Bytes()
}
}
return nil
})
}
}
return ad.Err()
} }

58
expr/bitwise_test.go Normal file
View File

@ -0,0 +1,58 @@
package expr
import (
"encoding/binary"
"reflect"
"testing"
"github.com/mdlayher/netlink"
"golang.org/x/sys/unix"
)
func TestBitwise(t *testing.T) {
t.Parallel()
tests := []struct {
name string
bw Bitwise
}{
{
name: "Unmarshal Bitwise IPv4 case",
bw: Bitwise{
SourceRegister: 1,
DestRegister: 2,
Len: 4,
// By specifying Xor to 0x0,0x0,0x0,0x0 and Mask to 0xff,0xff,0x0,0x0
// an expression will match /16 IPv4 address.
Xor: []byte{0x0, 0x0, 0x0, 0x0},
Mask: []byte{0xff, 0xff, 0x0, 0x0},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
nbw := Bitwise{}
data, err := tt.bw.marshal()
if err != nil {
t.Fatalf("marshal error: %+v", err)
}
ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
t.Fatalf("NewAttributeDecoder() error: %+v", err)
}
ad.ByteOrder = binary.BigEndian
for ad.Next() {
if ad.Type() == unix.NFTA_EXPR_DATA {
if err := nbw.unmarshal(ad.Bytes()); err != nil {
t.Errorf("unmarshal error: %+v", err)
break
}
}
}
if !reflect.DeepEqual(tt.bw, nbw) {
t.Fatalf("original %+v and recovered %+v Bitwise structs are different", tt.bw, nbw)
}
})
}
}

5
go.mod
View File

@ -4,7 +4,8 @@ go 1.12
require ( require (
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d
github.com/mdlayher/netlink v0.0.0-20190516121005-0087c778e469 github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5 golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 // indirect
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c
) )

28
go.sum
View File

@ -1,16 +1,26 @@
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a h1:84IpUNXj4mCR9CuCEvSiCArMbzr/TMbuPIadKDwypkI=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0= github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4= github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4=
github.com/mdlayher/netlink v0.0.0-20190516121005-0087c778e469 h1:6XwSkpIirmRxmstYmbL5PshChpqazkNfFNJ+Uj1iJlU= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v0.0.0-20190516121005-0087c778e469/go.mod h1:gOrA34zDL0K3RsACQe54bDYLF/CeFspQ9m5DOycycQ8= github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b h1:W3er9pI7mt2gOqOWzwvx20iJ8Akiqz1mUMTxU6wdvl8=
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5 h1:sM3evRHxE/1RuMe1FYAL3j7C7fUfIjkbE+NiDAYUF8U= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -190,6 +190,8 @@ func exprsFromMsg(b []byte) ([]expr.Any, error) {
e = &expr.Lookup{} e = &expr.Lookup{}
case "immediate": case "immediate":
e = &expr.Immediate{} e = &expr.Immediate{}
case "bitwise":
e = &expr.Bitwise{}
} }
if e == nil { if e == nil {
// TODO: introduce an opaque expression type so that users know // TODO: introduce an opaque expression type so that users know