From 97b2546ef6210c0d512e58a916e54826c5bbaeef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:15:05 +0000 Subject: [PATCH] build(deps): bump github.com/google/nftables from 0.2.0 to 0.3.0 Bumps [github.com/google/nftables](https://github.com/google/nftables) from 0.2.0 to 0.3.0. - [Commits](https://github.com/google/nftables/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: github.com/google/nftables dependency-version: 0.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 5 +- go.sum | 10 +- vendor/github.com/google/nftables/chain.go | 44 +++ vendor/github.com/google/nftables/conn.go | 48 ++- vendor/github.com/google/nftables/counter.go | 37 +-- .../google/nftables/expr/bitwise.go | 20 +- .../google/nftables/expr/byteorder.go | 18 +- .../google/nftables/expr/connlimit.go | 12 +- .../google/nftables/expr/counter.go | 12 +- vendor/github.com/google/nftables/expr/ct.go | 295 +++++++++++++++++- vendor/github.com/google/nftables/expr/dup.go | 23 +- .../github.com/google/nftables/expr/dynset.go | 28 +- .../github.com/google/nftables/expr/expr.go | 233 +++++++++----- .../github.com/google/nftables/expr/exthdr.go | 20 +- vendor/github.com/google/nftables/expr/fib.go | 40 ++- .../google/nftables/expr/flow_offload.go | 10 +- .../github.com/google/nftables/expr/hash.go | 20 +- .../google/nftables/expr/immediate.go | 20 +- .../github.com/google/nftables/expr/limit.go | 24 +- vendor/github.com/google/nftables/expr/log.go | 22 +- .../github.com/google/nftables/expr/lookup.go | 22 +- .../github.com/google/nftables/expr/match.go | 21 +- vendor/github.com/google/nftables/expr/nat.go | 25 +- .../google/nftables/expr/notrack.go | 4 + .../github.com/google/nftables/expr/numgen.go | 22 +- .../github.com/google/nftables/expr/objref.go | 12 +- .../google/nftables/expr/payload.go | 21 +- .../github.com/google/nftables/expr/queue.go | 27 +- .../github.com/google/nftables/expr/quota.go | 24 +- .../github.com/google/nftables/expr/range.go | 18 +- .../google/nftables/expr/redirect.go | 22 +- .../github.com/google/nftables/expr/reject.go | 12 +- vendor/github.com/google/nftables/expr/rt.go | 12 +- .../google/nftables/expr/secmark.go | 64 ++++ .../github.com/google/nftables/expr/socket.go | 21 +- .../google/nftables/expr/synproxy.go | 118 +++++++ .../github.com/google/nftables/expr/target.go | 21 +- .../github.com/google/nftables/expr/tproxy.go | 20 +- .../google/nftables/expr/verdict.go | 19 +- .../github.com/google/nftables/flowtable.go | 2 +- vendor/github.com/google/nftables/gen.go | 45 +++ .../internal/parseexprfunc/parseexprfunc.go | 5 +- vendor/github.com/google/nftables/monitor.go | 124 ++++++-- vendor/github.com/google/nftables/obj.go | 244 ++++++++++++--- vendor/github.com/google/nftables/quota.go | 49 ++- vendor/github.com/google/nftables/rule.go | 2 +- vendor/github.com/google/nftables/set.go | 102 +++++- vendor/github.com/google/nftables/table.go | 36 ++- .../google/nftables/userdata/userdata.go | 115 +++++++ vendor/github.com/google/nftables/util.go | 2 +- .../github.com/google/nftables/xt/comment.go | 34 ++ vendor/github.com/google/nftables/xt/info.go | 3 + vendor/github.com/josharian/native/doc.go | 8 - .../github.com/josharian/native/endian_big.go | 14 - .../josharian/native/endian_generic.go | 31 -- .../josharian/native/endian_little.go | 14 - vendor/github.com/josharian/native/license | 7 - vendor/github.com/josharian/native/readme.md | 10 - vendor/github.com/mdlayher/netlink/README.md | 8 + .../github.com/mdlayher/netlink/attribute.go | 5 +- .../github.com/mdlayher/netlink/nlenc/doc.go | 4 +- vendor/modules.txt | 10 +- 62 files changed, 1735 insertions(+), 585 deletions(-) create mode 100644 vendor/github.com/google/nftables/expr/secmark.go create mode 100644 vendor/github.com/google/nftables/expr/synproxy.go create mode 100644 vendor/github.com/google/nftables/gen.go create mode 100644 vendor/github.com/google/nftables/userdata/userdata.go create mode 100644 vendor/github.com/google/nftables/xt/comment.go delete mode 100644 vendor/github.com/josharian/native/doc.go delete mode 100644 vendor/github.com/josharian/native/endian_big.go delete mode 100644 vendor/github.com/josharian/native/endian_generic.go delete mode 100644 vendor/github.com/josharian/native/endian_little.go delete mode 100644 vendor/github.com/josharian/native/license delete mode 100644 vendor/github.com/josharian/native/readme.md diff --git a/go.mod b/go.mod index 02d8cda1..ddc59278 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-ini/ini v1.67.0 github.com/godbus/dbus/v5 v5.1.0 github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/google/nftables v0.2.0 + github.com/google/nftables v0.3.0 github.com/gorilla/mux v1.8.1 github.com/jaypipes/ghw v0.13.0 github.com/linuxkit/virtsock v0.0.0-20220523201153-1a23e78aa7a2 @@ -33,12 +33,11 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jaypipes/pcidb v1.0.1 // indirect - github.com/josharian/native v1.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect github.com/mdlayher/socket v0.5.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/go.sum b/go.sum index 187f4335..9f90677b 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/nftables v0.2.0 h1:PbJwaBmbVLzpeldoeUKGkE2RjstrjPKMl6oLrfEJ6/8= -github.com/google/nftables v0.2.0/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4= +github.com/google/nftables v0.3.0 h1:bkyZ0cbpVeMHXOrtlFc8ISmfVqq5gPJukoYieyVmITg= +github.com/google/nftables v0.3.0/go.mod h1:BCp9FsrbF1Fn/Yu6CLUc9GGZFw/+hsxfluNXXmxBfRM= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -40,8 +40,6 @@ github.com/jaypipes/ghw v0.13.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51M github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic= github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= -github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -57,8 +55,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= -github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 h1:A1Cq6Ysb0GM0tpKMbdCXCIfBclan4oHk1Jb+Hrejirg= +github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42/go.mod h1:BB4YCPDOzfy7FniQ/lxuYQ3dgmM2cZumHbK8RpTjN2o= github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI= github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= diff --git a/vendor/github.com/google/nftables/chain.go b/vendor/github.com/google/nftables/chain.go index e1bda29a..4f4c0a53 100644 --- a/vendor/github.com/google/nftables/chain.go +++ b/vendor/github.com/google/nftables/chain.go @@ -37,6 +37,7 @@ var ( ChainHookOutput *ChainHook = ChainHookRef(unix.NF_INET_LOCAL_OUT) ChainHookPostrouting *ChainHook = ChainHookRef(unix.NF_INET_POST_ROUTING) ChainHookIngress *ChainHook = ChainHookRef(unix.NF_NETDEV_INGRESS) + ChainHookEgress *ChainHook = ChainHookRef(unix.NF_NETDEV_EGRESS) ) // ChainHookRef returns a pointer to a ChainHookRef value. @@ -101,6 +102,7 @@ type Chain struct { Priority *ChainPriority Type ChainType Policy *ChainPolicy + Device string } // AddChain adds the specified Chain. See also @@ -118,6 +120,11 @@ func (cc *Conn) AddChain(c *Chain) *Chain { {Type: unix.NFTA_HOOK_HOOKNUM, Data: binaryutil.BigEndian.PutUint32(uint32(*c.Hooknum))}, {Type: unix.NFTA_HOOK_PRIORITY, Data: binaryutil.BigEndian.PutUint32(uint32(*c.Priority))}, } + + if c.Device != "" { + hookAttr = append(hookAttr, netlink.Attribute{Type: unix.NFTA_HOOK_DEV, Data: []byte(c.Device + "\x00")}) + } + data = append(data, cc.marshalAttr([]netlink.Attribute{ {Type: unix.NLA_F_NESTED | unix.NFTA_CHAIN_HOOK, Data: cc.marshalAttr(hookAttr)}, })...) @@ -186,6 +193,43 @@ func (cc *Conn) ListChains() ([]*Chain, error) { return cc.ListChainsOfTableFamily(TableFamilyUnspecified) } +// ListChain returns a single chain configured in the specified table +func (cc *Conn) ListChain(table *Table, chain string) (*Chain, error) { + conn, closer, err := cc.netlinkConn() + if err != nil { + return nil, err + } + defer func() { _ = closer() }() + + attrs := []netlink.Attribute{ + {Type: unix.NFTA_TABLE_NAME, Data: []byte(table.Name + "\x00")}, + {Type: unix.NFTA_CHAIN_NAME, Data: []byte(chain + "\x00")}, + } + msg := netlink.Message{ + Header: netlink.Header{ + Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETCHAIN), + Flags: netlink.Request, + }, + Data: append(extraHeader(uint8(table.Family), 0), cc.marshalAttr(attrs)...), + } + + response, err := conn.Execute(msg) + if err != nil { + return nil, fmt.Errorf("conn.Execute failed: %v", err) + } + + if got, want := len(response), 1; got != want { + return nil, fmt.Errorf("expected %d response message for chain, got %d", want, got) + } + + ch, err := chainFromMsg(response[0]) + if err != nil { + return nil, err + } + + return ch, nil +} + // ListChainsOfTableFamily returns currently configured chains for the specified // family in the kernel. It lists all chains ins all tables if family is // TableFamilyUnspecified. diff --git a/vendor/github.com/google/nftables/conn.go b/vendor/github.com/google/nftables/conn.go index a9fbf2b9..fef9c2a4 100644 --- a/vendor/github.com/google/nftables/conn.go +++ b/vendor/github.com/google/nftables/conn.go @@ -19,6 +19,7 @@ import ( "fmt" "os" "sync" + "syscall" "github.com/google/nftables/binaryutil" "github.com/google/nftables/expr" @@ -37,16 +38,20 @@ type Conn struct { TestDial nltest.Func // for testing only; passed to nltest.Dial NetNS int // fd referencing the network namespace netlink will interact with. - lasting bool // establish a lasting connection to be used across multiple netlink operations. - mu sync.Mutex // protects the following state - messages []netlink.Message - err error - nlconn *netlink.Conn // netlink socket using NETLINK_NETFILTER protocol. + lasting bool // establish a lasting connection to be used across multiple netlink operations. + mu sync.Mutex // protects the following state + messages []netlink.Message + err error + nlconn *netlink.Conn // netlink socket using NETLINK_NETFILTER protocol. + sockOptions []SockOption } // ConnOption is an option to change the behavior of the nftables Conn returned by Open. type ConnOption func(*Conn) +// SockOption is an option to change the behavior of the netlink socket used by the nftables Conn. +type SockOption func(*netlink.Conn) error + // New returns a netlink connection for querying and modifying nftables. Some // aspects of the new netlink connection can be configured using the options // WithNetNSFd, WithTestDial, and AsLasting. @@ -101,6 +106,14 @@ func WithTestDial(f nltest.Func) ConnOption { } } +// WithSockOptions sets the specified socket options when creating a new netlink +// connection. +func WithSockOptions(opts ...SockOption) ConnOption { + return func(cc *Conn) { + cc.sockOptions = append(cc.sockOptions, opts...) + } +} + // netlinkCloser is returned by netlinkConn(UnderLock) and must be called after // being done with the returned netlink connection in order to properly close // this connection, if necessary. @@ -254,8 +267,8 @@ func (cc *Conn) Flush() error { // Fetch the requested acknowledgement for each message we sent. for _, msg := range cc.messages { if _, err := receiveAckAware(conn, msg.Header.Flags); err != nil { - if errors.Is(err, os.ErrPermission) { - // Kernel will only send one permission error to user space. + if errors.Is(err, os.ErrPermission) || errors.Is(err, syscall.ENOBUFS) { + // Kernel will only send one error to user space. return err } errs = errors.Join(errs, err) @@ -284,11 +297,28 @@ func (cc *Conn) FlushRuleset() { } func (cc *Conn) dialNetlink() (*netlink.Conn, error) { + var ( + conn *netlink.Conn + err error + ) + if cc.TestDial != nil { - return nltest.Dial(cc.TestDial), nil + conn = nltest.Dial(cc.TestDial) + } else { + conn, err = netlink.Dial(unix.NETLINK_NETFILTER, &netlink.Config{NetNS: cc.NetNS}) + } + + if err != nil { + return nil, err + } + + for _, opt := range cc.sockOptions { + if err := opt(conn); err != nil { + return nil, err + } } - return netlink.Dial(unix.NETLINK_NETFILTER, &netlink.Config{NetNS: cc.NetNS}) + return conn, nil } func (cc *Conn) setErr(err error) { diff --git a/vendor/github.com/google/nftables/counter.go b/vendor/github.com/google/nftables/counter.go index e4282029..d18fc49c 100644 --- a/vendor/github.com/google/nftables/counter.go +++ b/vendor/github.com/google/nftables/counter.go @@ -15,12 +15,11 @@ package nftables import ( - "github.com/google/nftables/binaryutil" + "github.com/google/nftables/expr" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) -// CounterObj implements Obj. type CounterObj struct { Table *Table Name string // e.g. “fwded” @@ -41,6 +40,20 @@ func (c *CounterObj) unmarshal(ad *netlink.AttributeDecoder) error { return ad.Err() } +func (c *CounterObj) data() expr.Any { + return &expr.Counter{ + Bytes: c.Bytes, + Packets: c.Packets, + } +} + +func (c *CounterObj) name() string { + return c.Name +} +func (c *CounterObj) objType() ObjType { + return ObjTypeCounter +} + func (c *CounterObj) table() *Table { return c.Table } @@ -48,23 +61,3 @@ func (c *CounterObj) table() *Table { func (c *CounterObj) family() TableFamily { return c.Table.Family } - -func (c *CounterObj) marshal(data bool) ([]byte, error) { - obj, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_COUNTER_BYTES, Data: binaryutil.BigEndian.PutUint64(c.Bytes)}, - {Type: unix.NFTA_COUNTER_PACKETS, Data: binaryutil.BigEndian.PutUint64(c.Packets)}, - }) - if err != nil { - return nil, err - } - const NFT_OBJECT_COUNTER = 1 // TODO: get into x/sys/unix - attrs := []netlink.Attribute{ - {Type: unix.NFTA_OBJ_TABLE, Data: []byte(c.Table.Name + "\x00")}, - {Type: unix.NFTA_OBJ_NAME, Data: []byte(c.Name + "\x00")}, - {Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(NFT_OBJECT_COUNTER)}, - } - if data { - attrs = append(attrs, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA, Data: obj}) - } - return netlink.MarshalAttributes(attrs) -} diff --git a/vendor/github.com/google/nftables/expr/bitwise.go b/vendor/github.com/google/nftables/expr/bitwise.go index 62f7f9ba..5f3cdeac 100644 --- a/vendor/github.com/google/nftables/expr/bitwise.go +++ b/vendor/github.com/google/nftables/expr/bitwise.go @@ -31,6 +31,17 @@ type Bitwise struct { } func (e *Bitwise) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("bitwise\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Bitwise) marshalData(fam byte) ([]byte, error) { mask, err := netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_DATA_VALUE, Data: e.Mask}, }) @@ -44,20 +55,13 @@ func (e *Bitwise) marshal(fam byte) ([]byte, error) { return nil, err } - data, err := netlink.MarshalAttributes([]netlink.Attribute{ + return netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_BITWISE_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)}, {Type: unix.NFTA_BITWISE_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)}, {Type: unix.NFTA_BITWISE_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)}, {Type: unix.NLA_F_NESTED | unix.NFTA_BITWISE_MASK, Data: mask}, {Type: unix.NLA_F_NESTED | unix.NFTA_BITWISE_XOR, Data: xor}, }) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("bitwise\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) } func (e *Bitwise) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/byteorder.go b/vendor/github.com/google/nftables/expr/byteorder.go index 2450e8f8..cf9e2fe5 100644 --- a/vendor/github.com/google/nftables/expr/byteorder.go +++ b/vendor/github.com/google/nftables/expr/byteorder.go @@ -38,13 +38,7 @@ type Byteorder struct { } func (e *Byteorder) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_BYTEORDER_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)}, - {Type: unix.NFTA_BYTEORDER_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)}, - {Type: unix.NFTA_BYTEORDER_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))}, - {Type: unix.NFTA_BYTEORDER_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)}, - {Type: unix.NFTA_BYTEORDER_SIZE, Data: binaryutil.BigEndian.PutUint32(e.Size)}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -54,6 +48,16 @@ func (e *Byteorder) marshal(fam byte) ([]byte, error) { }) } +func (e *Byteorder) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_BYTEORDER_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)}, + {Type: unix.NFTA_BYTEORDER_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)}, + {Type: unix.NFTA_BYTEORDER_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))}, + {Type: unix.NFTA_BYTEORDER_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)}, + {Type: unix.NFTA_BYTEORDER_SIZE, Data: binaryutil.BigEndian.PutUint32(e.Size)}, + }) +} + func (e *Byteorder) unmarshal(fam byte, data []byte) error { return fmt.Errorf("not yet implemented") } diff --git a/vendor/github.com/google/nftables/expr/connlimit.go b/vendor/github.com/google/nftables/expr/connlimit.go index b712967a..11bd07bf 100644 --- a/vendor/github.com/google/nftables/expr/connlimit.go +++ b/vendor/github.com/google/nftables/expr/connlimit.go @@ -37,10 +37,7 @@ type Connlimit struct { } func (e *Connlimit) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: NFTA_CONNLIMIT_COUNT, Data: binaryutil.BigEndian.PutUint32(e.Count)}, - {Type: NFTA_CONNLIMIT_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -51,6 +48,13 @@ func (e *Connlimit) marshal(fam byte) ([]byte, error) { }) } +func (e *Connlimit) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: NFTA_CONNLIMIT_COUNT, Data: binaryutil.BigEndian.PutUint32(e.Count)}, + {Type: NFTA_CONNLIMIT_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)}, + }) +} + func (e *Connlimit) unmarshal(fam byte, data []byte) error { ad, err := netlink.NewAttributeDecoder(data) if err != nil { diff --git a/vendor/github.com/google/nftables/expr/counter.go b/vendor/github.com/google/nftables/expr/counter.go index dd6eab3f..7483ee45 100644 --- a/vendor/github.com/google/nftables/expr/counter.go +++ b/vendor/github.com/google/nftables/expr/counter.go @@ -28,10 +28,7 @@ type Counter struct { } func (e *Counter) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_COUNTER_BYTES, Data: binaryutil.BigEndian.PutUint64(e.Bytes)}, - {Type: unix.NFTA_COUNTER_PACKETS, Data: binaryutil.BigEndian.PutUint64(e.Packets)}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -42,6 +39,13 @@ func (e *Counter) marshal(fam byte) ([]byte, error) { }) } +func (e *Counter) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_COUNTER_BYTES, Data: binaryutil.BigEndian.PutUint64(e.Bytes)}, + {Type: unix.NFTA_COUNTER_PACKETS, Data: binaryutil.BigEndian.PutUint64(e.Packets)}, + }) +} + func (e *Counter) unmarshal(fam byte, data []byte) error { ad, err := netlink.NewAttributeDecoder(data) if err != nil { diff --git a/vendor/github.com/google/nftables/expr/ct.go b/vendor/github.com/google/nftables/expr/ct.go index 1a0ee68b..127b6fdd 100644 --- a/vendor/github.com/google/nftables/expr/ct.go +++ b/vendor/github.com/google/nftables/expr/ct.go @@ -56,15 +56,80 @@ const ( CtStateBitUNTRACKED uint32 = 64 ) +// Missing ct timeout consts +// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=be0bae0ad31b0adb506f96de083f52a2bd0d4fbf#n1592 +const ( + NFTA_CT_TIMEOUT_L3PROTO = 0x01 + NFTA_CT_TIMEOUT_L4PROTO = 0x02 + NFTA_CT_TIMEOUT_DATA = 0x03 +) + +type CtStatePolicyTimeout map[uint16]uint32 + +const ( + // https://git.netfilter.org/libnftnl/tree/src/obj/ct_timeout.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n24 + CtStateTCPSYNSENT = iota + CtStateTCPSYNRECV + CtStateTCPESTABLISHED + CtStateTCPFINWAIT + CtStateTCPCLOSEWAIT + CtStateTCPLASTACK + CtStateTCPTIMEWAIT + CtStateTCPCLOSE + CtStateTCPSYNSENT2 + CtStateTCPRETRANS + CtStateTCPUNACK +) + +// https://git.netfilter.org/libnftnl/tree/src/obj/ct_timeout.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n38 +var CtStateTCPTimeoutDefaults CtStatePolicyTimeout = map[uint16]uint32{ + CtStateTCPSYNSENT: 120, + CtStateTCPSYNRECV: 60, + CtStateTCPESTABLISHED: 43200, + CtStateTCPFINWAIT: 120, + CtStateTCPCLOSEWAIT: 60, + CtStateTCPLASTACK: 30, + CtStateTCPTIMEWAIT: 120, + CtStateTCPCLOSE: 10, + CtStateTCPSYNSENT2: 120, + CtStateTCPRETRANS: 300, + CtStateTCPUNACK: 300, +} + +const ( + // https://git.netfilter.org/libnftnl/tree/src/obj/ct_timeout.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n57 + CtStateUDPUNREPLIED = iota + CtStateUDPREPLIED +) + +// https://git.netfilter.org/libnftnl/tree/src/obj/ct_timeout.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n57 +var CtStateUDPTimeoutDefaults CtStatePolicyTimeout = map[uint16]uint32{ + CtStateUDPUNREPLIED: 30, + CtStateUDPREPLIED: 180, +} + // Ct defines type for NFT connection tracking type Ct struct { Register uint32 SourceRegister bool Key CtKey + Direction uint32 } func (e *Ct) marshal(fam byte) ([]byte, error) { - regData := []byte{} + exprData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("ct\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (e *Ct) marshalData(fam byte) ([]byte, error) { + var regData []byte exprData, err := netlink.MarshalAttributes( []netlink.Attribute{ {Type: unix.NFTA_CT_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))}, @@ -91,10 +156,20 @@ func (e *Ct) marshal(fam byte) ([]byte, error) { } exprData = append(exprData, regData...) - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("ct\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, - }) + switch e.Key { + case CtKeySRC, CtKeyDST, CtKeyPROTOSRC, CtKeyPROTODST: + regData, err = netlink.MarshalAttributes( + []netlink.Attribute{ + {Type: unix.NFTA_CT_DIRECTION, Data: binaryutil.BigEndian.PutUint32(e.Direction)}, + }, + ) + if err != nil { + return nil, err + } + exprData = append(exprData, regData...) + } + + return exprData, nil } func (e *Ct) unmarshal(fam byte, data []byte) error { @@ -109,6 +184,216 @@ func (e *Ct) unmarshal(fam byte, data []byte) error { e.Key = CtKey(ad.Uint32()) case unix.NFTA_CT_DREG: e.Register = ad.Uint32() + case unix.NFTA_CT_DIRECTION: + e.Direction = ad.Uint32() + } + } + return ad.Err() +} + +type CtHelper struct { + Name string + L3Proto uint16 + L4Proto uint8 +} + +func (c *CtHelper) marshal(fam byte) ([]byte, error) { + exprData, err := c.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("cthelper\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (c *CtHelper) marshalData(fam byte) ([]byte, error) { + exprData := []netlink.Attribute{ + {Type: unix.NFTA_CT_HELPER_NAME, Data: []byte(c.Name)}, + } + + if c.L3Proto != 0 { + exprData = append(exprData, netlink.Attribute{ + Type: unix.NFTA_CT_HELPER_L3PROTO, Data: binaryutil.BigEndian.PutUint16(c.L3Proto), + }) + } + if c.L4Proto != 0 { + exprData = append(exprData, netlink.Attribute{ + Type: unix.NFTA_CT_HELPER_L4PROTO, Data: []byte{c.L4Proto}, + }) + } + + return netlink.MarshalAttributes(exprData) +} + +func (c *CtHelper) unmarshal(fam byte, data []byte) error { + ad, err := netlink.NewAttributeDecoder(data) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + for ad.Next() { + switch ad.Type() { + case unix.NFTA_CT_HELPER_NAME: + c.Name = ad.String() + case unix.NFTA_CT_HELPER_L3PROTO: + c.L3Proto = ad.Uint16() + case unix.NFTA_CT_HELPER_L4PROTO: + c.L4Proto = ad.Uint8() + } + } + return ad.Err() +} + +// From https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=be0bae0ad31b0adb506f96de083f52a2bd0d4fbf#n1601 +// Currently not available in sys/unix +const ( + NFTA_CT_EXPECT_L3PROTO = 0x01 + NFTA_CT_EXPECT_L4PROTO = 0x02 + NFTA_CT_EXPECT_DPORT = 0x03 + NFTA_CT_EXPECT_TIMEOUT = 0x04 + NFTA_CT_EXPECT_SIZE = 0x05 +) + +type CtExpect struct { + L3Proto uint16 + L4Proto uint8 + DPort uint16 + Timeout uint32 + Size uint8 +} + +func (c *CtExpect) marshal(fam byte) ([]byte, error) { + exprData, err := c.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("ctexpect\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (c *CtExpect) marshalData(fam byte) ([]byte, error) { + // all elements except l3proto must be defined + // per https://git.netfilter.org/nftables/tree/doc/stateful-objects.txt?id=db70959a5ccf2952b218f51c3d529e186a5a43bb#n119 + // from man page: l3proto is derived from the table family by default + exprData := []netlink.Attribute{ + {Type: NFTA_CT_EXPECT_L4PROTO, Data: []byte{c.L4Proto}}, + {Type: NFTA_CT_EXPECT_DPORT, Data: binaryutil.BigEndian.PutUint16(c.DPort)}, + {Type: NFTA_CT_EXPECT_TIMEOUT, Data: binaryutil.BigEndian.PutUint32(c.Timeout)}, + {Type: NFTA_CT_EXPECT_SIZE, Data: []byte{c.Size}}, + } + + if c.L3Proto != 0 { + attr := netlink.Attribute{Type: NFTA_CT_EXPECT_L3PROTO, Data: binaryutil.BigEndian.PutUint16(c.L3Proto)} + exprData = append(exprData, attr) + } + return netlink.MarshalAttributes(exprData) +} + +func (c *CtExpect) unmarshal(fam byte, data []byte) error { + ad, err := netlink.NewAttributeDecoder(data) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + for ad.Next() { + switch ad.Type() { + case NFTA_CT_EXPECT_L3PROTO: + c.L3Proto = ad.Uint16() + case NFTA_CT_EXPECT_L4PROTO: + c.L4Proto = ad.Uint8() + case NFTA_CT_EXPECT_DPORT: + c.DPort = ad.Uint16() + case NFTA_CT_EXPECT_TIMEOUT: + c.Timeout = ad.Uint32() + case NFTA_CT_EXPECT_SIZE: + c.Size = ad.Uint8() + } + } + return ad.Err() +} + +type CtTimeout struct { + L3Proto uint16 + L4Proto uint8 + Policy CtStatePolicyTimeout +} + +func (c *CtTimeout) marshal(fam byte) ([]byte, error) { + exprData, err := c.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("cttimeout\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (c *CtTimeout) marshalData(fam byte) ([]byte, error) { + var policy CtStatePolicyTimeout + switch c.L4Proto { + case unix.IPPROTO_UDP: + policy = CtStateUDPTimeoutDefaults + default: + policy = CtStateTCPTimeoutDefaults + } + + for k, v := range c.Policy { + policy[k] = v + } + + var policyAttrs []netlink.Attribute + for k, v := range policy { + policyAttrs = append(policyAttrs, netlink.Attribute{Type: k + 1, Data: binaryutil.BigEndian.PutUint32(v)}) + } + policyData, err := netlink.MarshalAttributes(policyAttrs) + if err != nil { + return nil, err + } + + exprData := []netlink.Attribute{ + {Type: NFTA_CT_TIMEOUT_L3PROTO, Data: binaryutil.BigEndian.PutUint16(c.L3Proto)}, + {Type: NFTA_CT_TIMEOUT_L4PROTO, Data: []byte{c.L4Proto}}, + {Type: unix.NLA_F_NESTED | NFTA_CT_TIMEOUT_DATA, Data: policyData}, + } + + return netlink.MarshalAttributes(exprData) +} + +func (c *CtTimeout) unmarshal(fam byte, data []byte) error { + ad, err := netlink.NewAttributeDecoder(data) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + for ad.Next() { + switch ad.Type() { + case NFTA_CT_TIMEOUT_L3PROTO: + c.L3Proto = ad.Uint16() + case NFTA_CT_TIMEOUT_L4PROTO: + c.L4Proto = ad.Uint8() + case NFTA_CT_TIMEOUT_DATA: + decoder, err := netlink.NewAttributeDecoder(ad.Bytes()) + decoder.ByteOrder = binary.BigEndian + if err != nil { + return err + } + for decoder.Next() { + switch c.L4Proto { + case unix.IPPROTO_UDP: + c.Policy = CtStateUDPTimeoutDefaults + default: + c.Policy = CtStateTCPTimeoutDefaults + } + c.Policy[decoder.Type()-1] = decoder.Uint32() + } } } return ad.Err() diff --git a/vendor/github.com/google/nftables/expr/dup.go b/vendor/github.com/google/nftables/expr/dup.go index 0114fa79..9012fdac 100644 --- a/vendor/github.com/google/nftables/expr/dup.go +++ b/vendor/github.com/google/nftables/expr/dup.go @@ -29,16 +29,7 @@ type Dup struct { } func (e *Dup) marshal(fam byte) ([]byte, error) { - attrs := []netlink.Attribute{ - {Type: unix.NFTA_DUP_SREG_ADDR, Data: binaryutil.BigEndian.PutUint32(e.RegAddr)}, - } - - if e.IsRegDevSet { - attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_DUP_SREG_DEV, Data: binaryutil.BigEndian.PutUint32(e.RegDev)}) - } - - data, err := netlink.MarshalAttributes(attrs) - + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -49,6 +40,18 @@ func (e *Dup) marshal(fam byte) ([]byte, error) { }) } +func (e *Dup) marshalData(fam byte) ([]byte, error) { + attrs := []netlink.Attribute{ + {Type: unix.NFTA_DUP_SREG_ADDR, Data: binaryutil.BigEndian.PutUint32(e.RegAddr)}, + } + + if e.IsRegDevSet { + attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_DUP_SREG_DEV, Data: binaryutil.BigEndian.PutUint32(e.RegDev)}) + } + + return netlink.MarshalAttributes(attrs) +} + func (e *Dup) unmarshal(fam byte, data []byte) error { ad, err := netlink.NewAttributeDecoder(data) if err != nil { diff --git a/vendor/github.com/google/nftables/expr/dynset.go b/vendor/github.com/google/nftables/expr/dynset.go index e44f7727..0b3d9bf1 100644 --- a/vendor/github.com/google/nftables/expr/dynset.go +++ b/vendor/github.com/google/nftables/expr/dynset.go @@ -44,6 +44,18 @@ type Dynset struct { } func (e *Dynset) marshal(fam byte) ([]byte, error) { + opData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("dynset\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: opData}, + }) +} + +func (e *Dynset) marshalData(fam byte) ([]byte, error) { // See: https://git.netfilter.org/libnftnl/tree/src/expr/dynset.c var opAttrs []netlink.Attribute opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_SREG_KEY, Data: binaryutil.BigEndian.PutUint32(e.SrcRegKey)}) @@ -65,7 +77,6 @@ func (e *Dynset) marshal(fam byte) ([]byte, error) { // Per https://git.netfilter.org/libnftnl/tree/src/expr/dynset.c?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n170 if len(e.Exprs) > 0 { - flags |= NFT_DYNSET_F_EXPR switch len(e.Exprs) { case 1: exprData, err := Marshal(fam, e.Exprs[0]) @@ -74,6 +85,7 @@ func (e *Dynset) marshal(fam byte) ([]byte, error) { } opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_EXPR, Data: exprData}) default: + flags |= NFT_DYNSET_F_EXPR var elemAttrs []netlink.Attribute for _, ex := range e.Exprs { exprData, err := Marshal(fam, ex) @@ -89,17 +101,9 @@ func (e *Dynset) marshal(fam byte) ([]byte, error) { opAttrs = append(opAttrs, netlink.Attribute{Type: NFTA_DYNSET_EXPRESSIONS, Data: elemData}) } } - opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}) - - opData, err := netlink.MarshalAttributes(opAttrs) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("dynset\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: opData}, - }) + opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}) + return netlink.MarshalAttributes(opAttrs) } func (e *Dynset) unmarshal(fam byte, data []byte) error { @@ -125,7 +129,7 @@ func (e *Dynset) unmarshal(fam byte, data []byte) error { case unix.NFTA_DYNSET_FLAGS: e.Invert = (ad.Uint32() & unix.NFT_DYNSET_F_INV) != 0 case unix.NFTA_DYNSET_EXPR: - exprs, err := parseexprfunc.ParseExprBytesFunc(fam, ad, ad.Bytes()) + exprs, err := parseexprfunc.ParseExprBytesFunc(fam, ad) if err != nil { return err } diff --git a/vendor/github.com/google/nftables/expr/expr.go b/vendor/github.com/google/nftables/expr/expr.go index 13267312..0a363233 100644 --- a/vendor/github.com/google/nftables/expr/expr.go +++ b/vendor/github.com/google/nftables/expr/expr.go @@ -25,8 +25,8 @@ import ( ) func init() { - parseexprfunc.ParseExprBytesFunc = func(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]interface{}, error) { - exprs, err := exprsFromBytes(fam, ad, b) + parseExprBytesCommonFunc := func(exprsFromBytesFunc func() ([]Any, error)) ([]interface{}, error) { + exprs, err := exprsFromBytesFunc() if err != nil { return nil, err } @@ -36,6 +36,17 @@ func init() { } return result, nil } + + parseexprfunc.ParseExprBytesFromNameFunc = func(fam byte, ad *netlink.AttributeDecoder, exprName string) ([]interface{}, error) { + return parseExprBytesCommonFunc(func() ([]Any, error) { + return exprsBytesFromName(fam, ad, exprName) + }) + } + parseexprfunc.ParseExprBytesFunc = func(fam byte, ad *netlink.AttributeDecoder) ([]interface{}, error) { + return parseExprBytesCommonFunc(func() ([]Any, error) { + return exprsFromBytes(fam, ad) + }) + } parseexprfunc.ParseExprMsgFunc = func(fam byte, b []byte) ([]interface{}, error) { ad, err := netlink.NewAttributeDecoder(b) if err != nil { @@ -44,7 +55,7 @@ func init() { ad.ByteOrder = binary.BigEndian var exprs []interface{} for ad.Next() { - e, err := parseexprfunc.ParseExprBytesFunc(fam, ad, b) + e, err := parseexprfunc.ParseExprBytesFunc(fam, ad) if err != nil { return e, err } @@ -59,15 +70,35 @@ func Marshal(fam byte, e Any) ([]byte, error) { return e.marshal(fam) } +func MarshalExprData(fam byte, e Any) ([]byte, error) { + return e.marshalData(fam) +} + // Unmarshal fills an expression from the specified byte slice. func Unmarshal(fam byte, data []byte, e Any) error { return e.unmarshal(fam, data) } +// exprsBytesFromName parses raw expressions bytes +// based on provided expr name +func exprsBytesFromName(fam byte, ad *netlink.AttributeDecoder, name string) ([]Any, error) { + var exprs []Any + e := exprFromName(name) + ad.Do(func(b []byte) error { + if err := Unmarshal(fam, b, e); err != nil { + return err + } + exprs = append(exprs, e) + return nil + }) + return exprs, ad.Err() +} + // exprsFromBytes parses nested raw expressions bytes // to construct nftables expressions -func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]Any, error) { +func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder) ([]Any, error) { var exprs []Any + ad.Do(func(b []byte) error { ad, err := netlink.NewAttributeDecoder(b) if err != nil { @@ -84,65 +115,12 @@ func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]Any, er exprs = append(exprs, e) } case unix.NFTA_EXPR_DATA: - var e Any - switch name { - case "ct": - e = &Ct{} - case "range": - e = &Range{} - case "meta": - e = &Meta{} - case "cmp": - e = &Cmp{} - case "counter": - e = &Counter{} - case "objref": - e = &Objref{} - case "payload": - e = &Payload{} - case "lookup": - e = &Lookup{} - case "immediate": - e = &Immediate{} - case "bitwise": - e = &Bitwise{} - case "redir": - e = &Redir{} - case "nat": - e = &NAT{} - case "limit": - e = &Limit{} - case "quota": - e = &Quota{} - case "dynset": - e = &Dynset{} - case "log": - e = &Log{} - case "exthdr": - e = &Exthdr{} - case "match": - e = &Match{} - case "target": - e = &Target{} - case "connlimit": - e = &Connlimit{} - case "queue": - e = &Queue{} - case "flow_offload": - e = &FlowOffload{} - case "reject": - e = &Reject{} - case "masq": - e = &Masq{} - case "hash": - e = &Hash{} - } + e := exprFromName(name) if e == nil { // TODO: introduce an opaque expression type so that users know // something is here. continue // unsupported expression type } - ad.Do(func(b []byte) error { if err := Unmarshal(fam, b, e); err != nil { return err @@ -166,9 +144,81 @@ func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]Any, er return exprs, ad.Err() } +func exprFromName(name string) Any { + var e Any + switch name { + case "ct": + e = &Ct{} + case "range": + e = &Range{} + case "meta": + e = &Meta{} + case "cmp": + e = &Cmp{} + case "counter": + e = &Counter{} + case "objref": + e = &Objref{} + case "payload": + e = &Payload{} + case "lookup": + e = &Lookup{} + case "immediate": + e = &Immediate{} + case "bitwise": + e = &Bitwise{} + case "redir": + e = &Redir{} + case "nat": + e = &NAT{} + case "limit": + e = &Limit{} + case "quota": + e = &Quota{} + case "dynset": + e = &Dynset{} + case "log": + e = &Log{} + case "exthdr": + e = &Exthdr{} + case "match": + e = &Match{} + case "target": + e = &Target{} + case "connlimit": + e = &Connlimit{} + case "queue": + e = &Queue{} + case "flow_offload": + e = &FlowOffload{} + case "reject": + e = &Reject{} + case "masq": + e = &Masq{} + case "hash": + e = &Hash{} + case "cthelper": + e = &CtHelper{} + case "synproxy": + e = &SynProxy{} + case "ctexpect": + e = &CtExpect{} + case "secmark": + e = &SecMark{} + case "cttimeout": + e = &CtTimeout{} + case "fib": + e = &Fib{} + case "numgen": + e = &Numgen{} + } + return e +} + // Any is an interface implemented by any expression type. type Any interface { marshal(fam byte) ([]byte, error) + marshalData(fam byte) ([]byte, error) unmarshal(fam byte, data []byte) error } @@ -214,7 +264,19 @@ type Meta struct { } func (e *Meta) marshal(fam byte) ([]byte, error) { - regData := []byte{} + exprData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("meta\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (e *Meta) marshalData(fam byte) ([]byte, error) { + var regData []byte exprData, err := netlink.MarshalAttributes( []netlink.Attribute{ {Type: unix.NFTA_META_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))}, @@ -240,11 +302,7 @@ func (e *Meta) marshal(fam byte) ([]byte, error) { return nil, err } exprData = append(exprData, regData...) - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("meta\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, - }) + return exprData, nil } func (e *Meta) unmarshal(fam byte, data []byte) error { @@ -279,19 +337,31 @@ type Masq struct { RegProtoMax uint32 } -// TODO, Once the constants below are available in golang.org/x/sys/unix, switch to use those. const ( // NF_NAT_RANGE_PROTO_RANDOM defines flag for a random masquerade - NF_NAT_RANGE_PROTO_RANDOM = 0x4 + NF_NAT_RANGE_PROTO_RANDOM = unix.NF_NAT_RANGE_PROTO_RANDOM // NF_NAT_RANGE_PROTO_RANDOM_FULLY defines flag for a fully random masquerade - NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10 + NF_NAT_RANGE_PROTO_RANDOM_FULLY = unix.NF_NAT_RANGE_PROTO_RANDOM_FULLY // NF_NAT_RANGE_PERSISTENT defines flag for a persistent masquerade - NF_NAT_RANGE_PERSISTENT = 0x8 + NF_NAT_RANGE_PERSISTENT = unix.NF_NAT_RANGE_PERSISTENT // NF_NAT_RANGE_PREFIX defines flag for a prefix masquerade - NF_NAT_RANGE_PREFIX = 0x40 + NF_NAT_RANGE_PREFIX = unix.NF_NAT_RANGE_NETMAP + // NF_NAT_RANGE_PROTO_SPECIFIED defines flag for a specified range + NF_NAT_RANGE_PROTO_SPECIFIED = unix.NF_NAT_RANGE_PROTO_SPECIFIED ) func (e *Masq) marshal(fam byte) ([]byte, error) { + msgData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("masq\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: msgData}, + }) +} + +func (e *Masq) marshalData(fam byte) ([]byte, error) { msgData := []byte{} if !e.ToPorts { flags := uint32(0) @@ -328,10 +398,7 @@ func (e *Masq) marshal(fam byte) ([]byte, error) { msgData = append(msgData, regsData...) } } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("masq\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: msgData}, - }) + return msgData, nil } func (e *Masq) unmarshal(fam byte, data []byte) error { @@ -378,24 +445,28 @@ type Cmp struct { } func (e *Cmp) marshal(fam byte) ([]byte, error) { + exprData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("cmp\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (e *Cmp) marshalData(fam byte) ([]byte, error) { cmpData, err := netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_DATA_VALUE, Data: e.Data}, }) if err != nil { return nil, err } - exprData, err := netlink.MarshalAttributes([]netlink.Attribute{ + return netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_CMP_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, {Type: unix.NFTA_CMP_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))}, {Type: unix.NLA_F_NESTED | unix.NFTA_CMP_DATA, Data: cmpData}, }) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("cmp\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, - }) } func (e *Cmp) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/exthdr.go b/vendor/github.com/google/nftables/expr/exthdr.go index df0c7db0..0a9d9fcd 100644 --- a/vendor/github.com/google/nftables/expr/exthdr.go +++ b/vendor/github.com/google/nftables/expr/exthdr.go @@ -40,6 +40,17 @@ type Exthdr struct { } func (e *Exthdr) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("exthdr\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Exthdr) marshalData(fam byte) ([]byte, error) { var attr []netlink.Attribute // Operations are differentiated by the Op and whether the SourceRegister @@ -64,14 +75,7 @@ func (e *Exthdr) marshal(fam byte) ([]byte, error) { netlink.Attribute{Type: unix.NFTA_EXTHDR_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)}) } - data, err := netlink.MarshalAttributes(attr) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("exthdr\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(attr) } func (e *Exthdr) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/fib.go b/vendor/github.com/google/nftables/expr/fib.go index f7ee7043..ea6c059b 100644 --- a/vendor/github.com/google/nftables/expr/fib.go +++ b/vendor/github.com/google/nftables/expr/fib.go @@ -37,6 +37,17 @@ type Fib struct { } func (e *Fib) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("fib\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Fib) marshalData(fam byte) ([]byte, error) { data := []byte{} reg, err := netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_FIB_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, @@ -92,11 +103,7 @@ func (e *Fib) marshal(fam byte) ([]byte, error) { } data = append(data, rslt...) } - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("fib\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return data, nil } func (e *Fib) unmarshal(fam byte, data []byte) error { @@ -111,17 +118,22 @@ func (e *Fib) unmarshal(fam byte, data []byte) error { e.Register = ad.Uint32() case unix.NFTA_FIB_RESULT: result := ad.Uint32() - e.ResultOIF = (result & unix.NFT_FIB_RESULT_OIF) == 1 - e.ResultOIFNAME = (result & unix.NFT_FIB_RESULT_OIFNAME) == 1 - e.ResultADDRTYPE = (result & unix.NFT_FIB_RESULT_ADDRTYPE) == 1 + switch result { + case unix.NFT_FIB_RESULT_OIF: + e.ResultOIF = true + case unix.NFT_FIB_RESULT_OIFNAME: + e.ResultOIFNAME = true + case unix.NFT_FIB_RESULT_ADDRTYPE: + e.ResultADDRTYPE = true + } case unix.NFTA_FIB_FLAGS: flags := ad.Uint32() - e.FlagSADDR = (flags & unix.NFTA_FIB_F_SADDR) == 1 - e.FlagDADDR = (flags & unix.NFTA_FIB_F_DADDR) == 1 - e.FlagMARK = (flags & unix.NFTA_FIB_F_MARK) == 1 - e.FlagIIF = (flags & unix.NFTA_FIB_F_IIF) == 1 - e.FlagOIF = (flags & unix.NFTA_FIB_F_OIF) == 1 - e.FlagPRESENT = (flags & unix.NFTA_FIB_F_PRESENT) == 1 + e.FlagSADDR = (flags & unix.NFTA_FIB_F_SADDR) != 0 + e.FlagDADDR = (flags & unix.NFTA_FIB_F_DADDR) != 0 + e.FlagMARK = (flags & unix.NFTA_FIB_F_MARK) != 0 + e.FlagIIF = (flags & unix.NFTA_FIB_F_IIF) != 0 + e.FlagOIF = (flags & unix.NFTA_FIB_F_OIF) != 0 + e.FlagPRESENT = (flags & unix.NFTA_FIB_F_PRESENT) != 0 } } return ad.Err() diff --git a/vendor/github.com/google/nftables/expr/flow_offload.go b/vendor/github.com/google/nftables/expr/flow_offload.go index 54f956f1..de4949a6 100644 --- a/vendor/github.com/google/nftables/expr/flow_offload.go +++ b/vendor/github.com/google/nftables/expr/flow_offload.go @@ -28,9 +28,7 @@ type FlowOffload struct { } func (e *FlowOffload) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: NFTNL_EXPR_FLOW_TABLE_NAME, Data: []byte(e.Name)}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -41,6 +39,12 @@ func (e *FlowOffload) marshal(fam byte) ([]byte, error) { }) } +func (e *FlowOffload) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: NFTNL_EXPR_FLOW_TABLE_NAME, Data: []byte(e.Name)}, + }) +} + func (e *FlowOffload) unmarshal(fam byte, data []byte) error { ad, err := netlink.NewAttributeDecoder(data) if err != nil { diff --git a/vendor/github.com/google/nftables/expr/hash.go b/vendor/github.com/google/nftables/expr/hash.go index e8506b93..92b9eea3 100644 --- a/vendor/github.com/google/nftables/expr/hash.go +++ b/vendor/github.com/google/nftables/expr/hash.go @@ -41,6 +41,17 @@ type Hash struct { } func (e *Hash) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("hash\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Hash) marshalData(fam byte) ([]byte, error) { hashAttrs := []netlink.Attribute{ {Type: unix.NFTA_HASH_SREG, Data: binaryutil.BigEndian.PutUint32(uint32(e.SourceRegister))}, {Type: unix.NFTA_HASH_DREG, Data: binaryutil.BigEndian.PutUint32(uint32(e.DestRegister))}, @@ -56,14 +67,7 @@ func (e *Hash) marshal(fam byte) ([]byte, error) { {Type: unix.NFTA_HASH_OFFSET, Data: binaryutil.BigEndian.PutUint32(uint32(e.Offset))}, {Type: unix.NFTA_HASH_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Type))}, }...) - data, err := netlink.MarshalAttributes(hashAttrs) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("hash\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(hashAttrs) } func (e *Hash) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/immediate.go b/vendor/github.com/google/nftables/expr/immediate.go index 99531f86..19eea448 100644 --- a/vendor/github.com/google/nftables/expr/immediate.go +++ b/vendor/github.com/google/nftables/expr/immediate.go @@ -29,23 +29,27 @@ type Immediate struct { } func (e *Immediate) marshal(fam byte) ([]byte, error) { - immData, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_DATA_VALUE, Data: e.Data}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_IMMEDIATE_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, - {Type: unix.NLA_F_NESTED | unix.NFTA_IMMEDIATE_DATA, Data: immData}, +func (e *Immediate) marshalData(fam byte) ([]byte, error) { + immData, err := netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_DATA_VALUE, Data: e.Data}, }) if err != nil { return nil, err } + return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + {Type: unix.NFTA_IMMEDIATE_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, + {Type: unix.NLA_F_NESTED | unix.NFTA_IMMEDIATE_DATA, Data: immData}, }) } diff --git a/vendor/github.com/google/nftables/expr/limit.go b/vendor/github.com/google/nftables/expr/limit.go index 9ecb41f0..1e170ac3 100644 --- a/vendor/github.com/google/nftables/expr/limit.go +++ b/vendor/github.com/google/nftables/expr/limit.go @@ -72,6 +72,18 @@ type Limit struct { } func (l *Limit) marshal(fam byte) ([]byte, error) { + data, err := l.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("limit\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (l *Limit) marshalData(fam byte) ([]byte, error) { var flags uint32 if l.Over { flags = unix.NFT_LIMIT_F_INV @@ -84,15 +96,7 @@ func (l *Limit) marshal(fam byte) ([]byte, error) { {Type: unix.NFTA_LIMIT_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}, } - data, err := netlink.MarshalAttributes(attrs) - if err != nil { - return nil, err - } - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("limit\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(attrs) } func (l *Limit) unmarshal(fam byte, data []byte) error { @@ -119,7 +123,7 @@ func (l *Limit) unmarshal(fam byte, data []byte) error { return fmt.Errorf("expr: invalid limit type %d", l.Type) } case unix.NFTA_LIMIT_FLAGS: - l.Over = (ad.Uint32() & unix.NFT_LIMIT_F_INV) == 1 + l.Over = (ad.Uint32() & unix.NFT_LIMIT_F_INV) != 0 default: return errors.New("expr: unhandled limit netlink attribute") } diff --git a/vendor/github.com/google/nftables/expr/log.go b/vendor/github.com/google/nftables/expr/log.go index a712b990..eaa057a6 100644 --- a/vendor/github.com/google/nftables/expr/log.go +++ b/vendor/github.com/google/nftables/expr/log.go @@ -69,6 +69,18 @@ type Log struct { } func (e *Log) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("log\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Log) marshalData(fam byte) ([]byte, error) { // Per https://git.netfilter.org/libnftnl/tree/src/expr/log.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n129 attrs := make([]netlink.Attribute, 0) if e.Key&(1< 0 { attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_REDIR_REG_PROTO_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegisterProtoMin)}) @@ -40,15 +52,7 @@ func (e *Redir) marshal(fam byte) ([]byte, error) { attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_REDIR_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)}) } - data, err := netlink.MarshalAttributes(attrs) - if err != nil { - return nil, err - } - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("redir\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(attrs) } func (e *Redir) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/reject.go b/vendor/github.com/google/nftables/expr/reject.go index a7426261..7fe216db 100644 --- a/vendor/github.com/google/nftables/expr/reject.go +++ b/vendor/github.com/google/nftables/expr/reject.go @@ -28,10 +28,7 @@ type Reject struct { } func (e *Reject) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_REJECT_TYPE, Data: binaryutil.BigEndian.PutUint32(e.Type)}, - {Type: unix.NFTA_REJECT_ICMP_CODE, Data: []byte{e.Code}}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -41,6 +38,13 @@ func (e *Reject) marshal(fam byte) ([]byte, error) { }) } +func (e *Reject) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_REJECT_TYPE, Data: binaryutil.BigEndian.PutUint32(e.Type)}, + {Type: unix.NFTA_REJECT_ICMP_CODE, Data: []byte{e.Code}}, + }) +} + func (e *Reject) unmarshal(fam byte, data []byte) error { ad, err := netlink.NewAttributeDecoder(data) if err != nil { diff --git a/vendor/github.com/google/nftables/expr/rt.go b/vendor/github.com/google/nftables/expr/rt.go index c3be7ffc..21c3a637 100644 --- a/vendor/github.com/google/nftables/expr/rt.go +++ b/vendor/github.com/google/nftables/expr/rt.go @@ -37,10 +37,7 @@ type Rt struct { } func (e *Rt) marshal(fam byte) ([]byte, error) { - data, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_RT_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))}, - {Type: unix.NFTA_RT_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, - }) + data, err := e.marshalData(fam) if err != nil { return nil, err } @@ -50,6 +47,13 @@ func (e *Rt) marshal(fam byte) ([]byte, error) { }) } +func (e *Rt) marshalData(fam byte) ([]byte, error) { + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_RT_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))}, + {Type: unix.NFTA_RT_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, + }) +} + func (e *Rt) unmarshal(fam byte, data []byte) error { return fmt.Errorf("not yet implemented") } diff --git a/vendor/github.com/google/nftables/expr/secmark.go b/vendor/github.com/google/nftables/expr/secmark.go new file mode 100644 index 00000000..3faf87f5 --- /dev/null +++ b/vendor/github.com/google/nftables/expr/secmark.go @@ -0,0 +1,64 @@ +// Copyright 2024 Google LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package expr + +import ( + "encoding/binary" + + "github.com/mdlayher/netlink" + "golang.org/x/sys/unix" +) + +// From https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=be0bae0ad31b0adb506f96de083f52a2bd0d4fbf#n1338 +const ( + NFTA_SECMARK_CTX = 0x01 +) + +type SecMark struct { + Ctx string +} + +func (e *SecMark) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("secmark\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *SecMark) marshalData(fam byte) ([]byte, error) { + attrs := []netlink.Attribute{ + {Type: NFTA_SECMARK_CTX, Data: []byte(e.Ctx)}, + } + return netlink.MarshalAttributes(attrs) +} + +func (e *SecMark) unmarshal(fam byte, data []byte) error { + ad, err := netlink.NewAttributeDecoder(data) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + for ad.Next() { + switch ad.Type() { + case NFTA_SECMARK_CTX: + e.Ctx = ad.String() + } + } + return ad.Err() +} diff --git a/vendor/github.com/google/nftables/expr/socket.go b/vendor/github.com/google/nftables/expr/socket.go index 1b6bc24a..e3843ccd 100644 --- a/vendor/github.com/google/nftables/expr/socket.go +++ b/vendor/github.com/google/nftables/expr/socket.go @@ -49,23 +49,26 @@ const ( ) func (e *Socket) marshal(fam byte) ([]byte, error) { + exprData, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("socket\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, + }) +} + +func (e *Socket) marshalData(fam byte) ([]byte, error) { // NOTE: Socket.Level is only used when Socket.Key == SocketKeyCgroupv2. But `nft` always encoding it. Check link below: // http://git.netfilter.org/nftables/tree/src/netlink_linearize.c?id=0583bac241ea18c9d7f61cb20ca04faa1e043b78#n319 - exprData, err := netlink.MarshalAttributes( + return netlink.MarshalAttributes( []netlink.Attribute{ {Type: NFTA_SOCKET_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)}, {Type: NFTA_SOCKET_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))}, {Type: NFTA_SOCKET_LEVEL, Data: binaryutil.BigEndian.PutUint32(uint32(e.Level))}, }, ) - if err != nil { - return nil, err - } - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("socket\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData}, - }) } func (e *Socket) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/synproxy.go b/vendor/github.com/google/nftables/expr/synproxy.go new file mode 100644 index 00000000..a93b8bb2 --- /dev/null +++ b/vendor/github.com/google/nftables/expr/synproxy.go @@ -0,0 +1,118 @@ +// Copyright 2024 Google LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package expr + +import ( + "encoding/binary" + + "github.com/google/nftables/binaryutil" + "github.com/mdlayher/netlink" + "golang.org/x/sys/unix" +) + +type SynProxy struct { + Mss uint16 + Wscale uint8 + Timestamp bool + SackPerm bool + // Probably not expected to be set by users + // https://github.com/torvalds/linux/blob/521b1e7f4cf0b05a47995b103596978224b380a8/net/netfilter/nft_synproxy.c#L30-L31 + Ecn bool + // True when Mss is set to a value or if 0 is an intended value of Mss + MssValueSet bool + // True when Wscale is set to a value or if 0 is an intended value of Wscale + WscaleValueSet bool +} + +// From https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=be0bae0ad31b0adb506f96de083f52a2bd0d4fbf#n1723 +// Currently not available in golang.org/x/sys/unix +const ( + NFTA_SYNPROXY_MSS = 0x01 + NFTA_SYNPROXY_WSCALE = 0x02 + NFTA_SYNPROXY_FLAGS = 0x03 +) + +// From https://github.com/torvalds/linux/blob/521b1e7f4cf0b05a47995b103596978224b380a8/include/uapi/linux/netfilter/nf_synproxy.h#L7-L15 +// Currently not available in golang.org/x/sys/unix +const ( + NF_SYNPROXY_OPT_MSS = 0x01 + NF_SYNPROXY_OPT_WSCALE = 0x02 + NF_SYNPROXY_OPT_SACK_PERM = 0x04 + NF_SYNPROXY_OPT_TIMESTAMP = 0x08 + NF_SYNPROXY_OPT_ECN = 0x10 +) + +func (e *SynProxy) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("synproxy\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *SynProxy) marshalData(fam byte) ([]byte, error) { + var flags uint32 + if e.Mss != 0 || e.MssValueSet { + flags |= NF_SYNPROXY_OPT_MSS + } + if e.Wscale != 0 || e.WscaleValueSet { + flags |= NF_SYNPROXY_OPT_WSCALE + } + if e.SackPerm { + flags |= NF_SYNPROXY_OPT_SACK_PERM + } + if e.Timestamp { + flags |= NF_SYNPROXY_OPT_TIMESTAMP + } + if e.Ecn { + flags |= NF_SYNPROXY_OPT_ECN + } + attrs := []netlink.Attribute{ + {Type: NFTA_SYNPROXY_MSS, Data: binaryutil.BigEndian.PutUint16(e.Mss)}, + {Type: NFTA_SYNPROXY_WSCALE, Data: []byte{e.Wscale}}, + {Type: NFTA_SYNPROXY_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}, + } + return netlink.MarshalAttributes(attrs) +} + +func (e *SynProxy) unmarshal(fam byte, data []byte) error { + ad, err := netlink.NewAttributeDecoder(data) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + for ad.Next() { + switch ad.Type() { + case NFTA_SYNPROXY_MSS: + e.Mss = ad.Uint16() + case NFTA_SYNPROXY_WSCALE: + e.Wscale = ad.Uint8() + case NFTA_SYNPROXY_FLAGS: + flags := ad.Uint32() + checkFlag := func(flag uint32) bool { + return (flags & flag) == flag + } + e.MssValueSet = checkFlag(NF_SYNPROXY_OPT_MSS) + e.WscaleValueSet = checkFlag(NF_SYNPROXY_OPT_WSCALE) + e.SackPerm = checkFlag(NF_SYNPROXY_OPT_SACK_PERM) + e.Timestamp = checkFlag(NF_SYNPROXY_OPT_TIMESTAMP) + e.Ecn = checkFlag(NF_SYNPROXY_OPT_ECN) + } + } + return ad.Err() +} diff --git a/vendor/github.com/google/nftables/expr/target.go b/vendor/github.com/google/nftables/expr/target.go index e531a9f7..d1c800bb 100644 --- a/vendor/github.com/google/nftables/expr/target.go +++ b/vendor/github.com/google/nftables/expr/target.go @@ -21,6 +21,17 @@ type Target struct { } func (e *Target) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("target\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *Target) marshalData(fam byte) ([]byte, error) { // Per https://git.netfilter.org/libnftnl/tree/src/expr/target.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n38 name := e.Name // limit the extension name as (some) user-space tools do and leave room for @@ -40,15 +51,7 @@ func (e *Target) marshal(fam byte) ([]byte, error) { {Type: unix.NFTA_TARGET_INFO, Data: info}, } - data, err := netlink.MarshalAttributes(attrs) - if err != nil { - return nil, err - } - - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("target\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(attrs) } func (e *Target) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/tproxy.go b/vendor/github.com/google/nftables/expr/tproxy.go index 2846aab7..142740c4 100644 --- a/vendor/github.com/google/nftables/expr/tproxy.go +++ b/vendor/github.com/google/nftables/expr/tproxy.go @@ -40,6 +40,17 @@ type TProxy struct { } func (e *TProxy) marshal(fam byte) ([]byte, error) { + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("tproxy\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} + +func (e *TProxy) marshalData(fam byte) ([]byte, error) { attrs := []netlink.Attribute{ {Type: NFTA_TPROXY_FAMILY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Family))}, {Type: NFTA_TPROXY_REG_PORT, Data: binaryutil.BigEndian.PutUint32(e.RegPort)}, @@ -52,14 +63,7 @@ func (e *TProxy) marshal(fam byte) ([]byte, error) { }) } - data, err := netlink.MarshalAttributes(attrs) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("tproxy\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) + return netlink.MarshalAttributes(attrs) } func (e *TProxy) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/expr/verdict.go b/vendor/github.com/google/nftables/expr/verdict.go index 421fa066..239b4087 100644 --- a/vendor/github.com/google/nftables/expr/verdict.go +++ b/vendor/github.com/google/nftables/expr/verdict.go @@ -64,7 +64,17 @@ func (e *Verdict) marshal(fam byte) ([]byte, error) { // } // } // } + data, err := e.marshalData(fam) + if err != nil { + return nil, err + } + return netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")}, + {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, + }) +} +func (e *Verdict) marshalData(fam byte) ([]byte, error) { attrs := []netlink.Attribute{ {Type: unix.NFTA_VERDICT_CODE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Kind))}, } @@ -83,17 +93,10 @@ func (e *Verdict) marshal(fam byte) ([]byte, error) { return nil, err } - data, err := netlink.MarshalAttributes([]netlink.Attribute{ + return netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_IMMEDIATE_DREG, Data: binaryutil.BigEndian.PutUint32(unix.NFT_REG_VERDICT)}, {Type: unix.NLA_F_NESTED | unix.NFTA_IMMEDIATE_DATA, Data: immData}, }) - if err != nil { - return nil, err - } - return netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")}, - {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data}, - }) } func (e *Verdict) unmarshal(fam byte, data []byte) error { diff --git a/vendor/github.com/google/nftables/flowtable.go b/vendor/github.com/google/nftables/flowtable.go index 01df08eb..93dbcb55 100644 --- a/vendor/github.com/google/nftables/flowtable.go +++ b/vendor/github.com/google/nftables/flowtable.go @@ -219,7 +219,7 @@ func (cc *Conn) getFlowtables(t *Table) ([]netlink.Message, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %v", err) + return nil, fmt.Errorf("receiveAckAware: %v", err) } return reply, nil diff --git a/vendor/github.com/google/nftables/gen.go b/vendor/github.com/google/nftables/gen.go new file mode 100644 index 00000000..4ebcfbeb --- /dev/null +++ b/vendor/github.com/google/nftables/gen.go @@ -0,0 +1,45 @@ +package nftables + +import ( + "encoding/binary" + "fmt" + "github.com/mdlayher/netlink" + "golang.org/x/sys/unix" +) + +type GenMsg struct { + ID uint32 + ProcPID uint32 + ProcComm string // [16]byte - max 16bytes - kernel TASK_COMM_LEN +} + +var genHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWGEN) + +func genFromMsg(msg netlink.Message) (*GenMsg, error) { + if got, want := msg.Header.Type, genHeaderType; got != want { + return nil, fmt.Errorf("unexpected header type: got %v, want %v", got, want) + } + ad, err := netlink.NewAttributeDecoder(msg.Data[4:]) + if err != nil { + return nil, err + } + ad.ByteOrder = binary.BigEndian + + msgOut := &GenMsg{} + for ad.Next() { + switch ad.Type() { + case unix.NFTA_GEN_ID: + msgOut.ID = ad.Uint32() + case unix.NFTA_GEN_PROC_PID: + msgOut.ProcPID = ad.Uint32() + case unix.NFTA_GEN_PROC_NAME: + msgOut.ProcComm = ad.String() + default: + return nil, fmt.Errorf("Unknown attribute: %d %v\n", ad.Type(), ad.Bytes()) + } + } + if err := ad.Err(); err != nil { + return nil, err + } + return msgOut, nil +} diff --git a/vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go b/vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go index 523859d7..58614617 100644 --- a/vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go +++ b/vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go @@ -5,6 +5,7 @@ import ( ) var ( - ParseExprBytesFunc func(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]interface{}, error) - ParseExprMsgFunc func(fam byte, b []byte) ([]interface{}, error) + ParseExprBytesFromNameFunc func(fam byte, ad *netlink.AttributeDecoder, exprName string) ([]interface{}, error) + ParseExprBytesFunc func(fam byte, ad *netlink.AttributeDecoder) ([]interface{}, error) + ParseExprMsgFunc func(fam byte, b []byte) ([]interface{}, error) ) diff --git a/vendor/github.com/google/nftables/monitor.go b/vendor/github.com/google/nftables/monitor.go index 853d5fd8..7a25e3b4 100644 --- a/vendor/github.com/google/nftables/monitor.go +++ b/vendor/github.com/google/nftables/monitor.go @@ -116,9 +116,15 @@ const ( // nftables.MonitorEventTypeNewTable, you can access the corresponding table // details via Data.(*nftables.Table). type MonitorEvent struct { - Type MonitorEventType - Data any - Error error + Header netlink.Header + Type MonitorEventType + Data any + Error error +} + +type MonitorEvents struct { + GeneratedBy *MonitorEvent + Changes []*MonitorEvent } const ( @@ -139,7 +145,7 @@ type Monitor struct { // mu covers eventCh and status mu sync.Mutex - eventCh chan *MonitorEvent + eventCh chan *MonitorEvents status int } @@ -147,7 +153,7 @@ type MonitorOption func(*Monitor) func WithMonitorEventBuffer(size int) MonitorOption { return func(monitor *Monitor) { - monitor.eventCh = make(chan *MonitorEvent, size) + monitor.eventCh = make(chan *MonitorEvents, size) } } @@ -177,7 +183,7 @@ func NewMonitor(opts ...MonitorOption) *Monitor { opt(monitor) } if monitor.eventCh == nil { - monitor.eventCh = make(chan *MonitorEvent) + monitor.eventCh = make(chan *MonitorEvents) } objects, ok := monitorFlags[monitor.action] if !ok { @@ -192,6 +198,8 @@ func NewMonitor(opts ...MonitorOption) *Monitor { } func (monitor *Monitor) monitor() { + var changesEvents []*MonitorEvent + for { msgs, err := monitor.conn.Receive() if err != nil { @@ -199,13 +207,21 @@ func (monitor *Monitor) monitor() { // ignore the error that be closed break } else { - // any other errors will be send to user, and then to close eventCh + // any other errors will be sent to user, and then to close eventCh event := &MonitorEvent{ Type: MonitorEventTypeOOB, Data: nil, Error: err, } - monitor.eventCh <- event + + changesEvents = append(changesEvents, event) + + monitor.eventCh <- &MonitorEvents{ + GeneratedBy: event, + Changes: changesEvents, + } + changesEvents = nil + break } } @@ -221,54 +237,76 @@ func (monitor *Monitor) monitor() { case unix.NFT_MSG_NEWTABLE, unix.NFT_MSG_DELTABLE: table, err := tableFromMsg(msg) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: table, - Error: err, + Type: MonitorEventType(msgType), + Data: table, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + changesEvents = append(changesEvents, event) case unix.NFT_MSG_NEWCHAIN, unix.NFT_MSG_DELCHAIN: chain, err := chainFromMsg(msg) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: chain, - Error: err, + Type: MonitorEventType(msgType), + Data: chain, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + changesEvents = append(changesEvents, event) case unix.NFT_MSG_NEWRULE, unix.NFT_MSG_DELRULE: rule, err := parseRuleFromMsg(msg) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: rule, - Error: err, + Type: MonitorEventType(msgType), + Data: rule, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + changesEvents = append(changesEvents, event) case unix.NFT_MSG_NEWSET, unix.NFT_MSG_DELSET: set, err := setsFromMsg(msg) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: set, - Error: err, + Type: MonitorEventType(msgType), + Data: set, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + changesEvents = append(changesEvents, event) case unix.NFT_MSG_NEWSETELEM, unix.NFT_MSG_DELSETELEM: elems, err := elementsFromMsg(uint8(TableFamilyUnspecified), msg) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: elems, - Error: err, + Type: MonitorEventType(msgType), + Data: elems, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + changesEvents = append(changesEvents, event) case unix.NFT_MSG_NEWOBJ, unix.NFT_MSG_DELOBJ: - obj, err := objFromMsg(msg) + obj, err := objFromMsg(msg, true) event := &MonitorEvent{ - Type: MonitorEventType(msgType), - Data: obj, - Error: err, + Type: MonitorEventType(msgType), + Data: obj, + Error: err, + Header: msg.Header, + } + changesEvents = append(changesEvents, event) + case unix.NFT_MSG_NEWGEN: + gen, err := genFromMsg(msg) + event := &MonitorEvent{ + Type: MonitorEventType(msgType), + Data: gen, + Error: err, + Header: msg.Header, } - monitor.eventCh <- event + + monitor.eventCh <- &MonitorEvents{ + GeneratedBy: event, + Changes: changesEvents, + } + + changesEvents = nil } } } + monitor.mu.Lock() defer monitor.mu.Unlock() @@ -294,6 +332,26 @@ func (monitor *Monitor) Close() error { // Caller may receive a MonitorEventTypeOOB event which contains an error we didn't // handle, for now. func (cc *Conn) AddMonitor(monitor *Monitor) (chan *MonitorEvent, error) { + generationalEventCh, err := cc.AddGenerationalMonitor(monitor) + if err != nil { + return nil, err + } + + eventCh := make(chan *MonitorEvent) + + go func() { + defer close(eventCh) + for monitorEvents := range generationalEventCh { + for _, event := range monitorEvents.Changes { + eventCh <- event + } + } + }() + + return eventCh, nil +} + +func (cc *Conn) AddGenerationalMonitor(monitor *Monitor) (chan *MonitorEvents, error) { conn, closer, err := cc.netlinkConn() if err != nil { return nil, err diff --git a/vendor/github.com/google/nftables/obj.go b/vendor/github.com/google/nftables/obj.go index 50f83f46..3fcd6d7f 100644 --- a/vendor/github.com/google/nftables/obj.go +++ b/vendor/github.com/google/nftables/obj.go @@ -18,6 +18,9 @@ import ( "encoding/binary" "fmt" + "github.com/google/nftables/binaryutil" + "github.com/google/nftables/expr" + "github.com/google/nftables/internal/parseexprfunc" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) @@ -27,13 +30,73 @@ var ( delObjHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELOBJ) ) +type ObjType uint32 + +// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=be0bae0ad31b0adb506f96de083f52a2bd0d4fbf#n1612 +const ( + ObjTypeCounter ObjType = unix.NFT_OBJECT_COUNTER + ObjTypeQuota ObjType = unix.NFT_OBJECT_QUOTA + ObjTypeCtHelper ObjType = unix.NFT_OBJECT_CT_HELPER + ObjTypeLimit ObjType = unix.NFT_OBJECT_LIMIT + ObjTypeConnLimit ObjType = unix.NFT_OBJECT_CONNLIMIT + ObjTypeTunnel ObjType = unix.NFT_OBJECT_TUNNEL + ObjTypeCtTimeout ObjType = unix.NFT_OBJECT_CT_TIMEOUT + ObjTypeSecMark ObjType = unix.NFT_OBJECT_SECMARK + ObjTypeCtExpect ObjType = unix.NFT_OBJECT_CT_EXPECT + ObjTypeSynProxy ObjType = unix.NFT_OBJECT_SYNPROXY +) + +var objByObjTypeMagic = map[ObjType]string{ + ObjTypeCounter: "counter", + ObjTypeQuota: "quota", + ObjTypeLimit: "limit", + ObjTypeConnLimit: "connlimit", + ObjTypeCtHelper: "cthelper", + ObjTypeTunnel: "tunnel", // not implemented in expr + ObjTypeCtTimeout: "cttimeout", + ObjTypeSecMark: "secmark", + ObjTypeCtExpect: "ctexpect", + ObjTypeSynProxy: "synproxy", +} + // Obj represents a netfilter stateful object. See also // https://wiki.nftables.org/wiki-nftables/index.php/Stateful_objects type Obj interface { table() *Table family() TableFamily - unmarshal(*netlink.AttributeDecoder) error - marshal(data bool) ([]byte, error) + data() expr.Any + name() string + objType() ObjType +} + +// NamedObj represents nftables stateful object attributes +// Corresponds to netfilter nft_object_attributes as per +// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=116e95aa7b6358c917de8c69f6f173874030b46b#n1626 +type NamedObj struct { + Table *Table + Name string + Type ObjType + Obj expr.Any +} + +func (o *NamedObj) table() *Table { + return o.Table +} + +func (o *NamedObj) family() TableFamily { + return o.Table.Family +} + +func (o *NamedObj) data() expr.Any { + return o.Obj +} + +func (o *NamedObj) name() string { + return o.Name +} + +func (o *NamedObj) objType() ObjType { + return o.Type } // AddObject adds the specified Obj. Alias of AddObj. @@ -46,18 +109,27 @@ func (cc *Conn) AddObject(o Obj) Obj { func (cc *Conn) AddObj(o Obj) Obj { cc.mu.Lock() defer cc.mu.Unlock() - data, err := o.marshal(true) + data, err := expr.MarshalExprData(byte(o.family()), o.data()) if err != nil { cc.setErr(err) return nil } + attrs := []netlink.Attribute{ + {Type: unix.NFTA_OBJ_TABLE, Data: []byte(o.table().Name + "\x00")}, + {Type: unix.NFTA_OBJ_NAME, Data: []byte(o.name() + "\x00")}, + {Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(o.objType()))}, + } + if len(data) > 0 { + attrs = append(attrs, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA, Data: data}) + } + cc.messages = append(cc.messages, netlink.Message{ Header: netlink.Header{ Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWOBJ), Flags: netlink.Request | netlink.Acknowledge | netlink.Create, }, - Data: append(extraHeader(uint8(o.family()), 0), data...), + Data: append(extraHeader(uint8(o.family()), 0), cc.marshalAttr(attrs)...), }) return o } @@ -66,12 +138,12 @@ func (cc *Conn) AddObj(o Obj) Obj { func (cc *Conn) DeleteObject(o Obj) { cc.mu.Lock() defer cc.mu.Unlock() - data, err := o.marshal(false) - if err != nil { - cc.setErr(err) - return + attrs := []netlink.Attribute{ + {Type: unix.NFTA_OBJ_TABLE, Data: []byte(o.table().Name + "\x00")}, + {Type: unix.NFTA_OBJ_NAME, Data: []byte(o.name() + "\x00")}, + {Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(o.objType()))}, } - + data := cc.marshalAttr(attrs) data = append(data, cc.marshalAttr([]netlink.Attribute{{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA}})...) cc.messages = append(cc.messages, netlink.Message{ @@ -85,17 +157,26 @@ func (cc *Conn) DeleteObject(o Obj) { // GetObj is a legacy method that return all Obj that belongs // to the same table as the given one +// This function returns the same concrete type as passed, +// e.g. QuotaObj, CounterObj or NamedObj. Prefer using the more +// generic NamedObj over the legacy QuotaObj and CounterObj types. func (cc *Conn) GetObj(o Obj) ([]Obj, error) { - return cc.getObj(nil, o.table(), unix.NFT_MSG_GETOBJ) + return cc.getObjWithLegacyType(nil, o.table(), unix.NFT_MSG_GETOBJ, cc.useLegacyObjType(o)) } // GetObjReset is a legacy method that reset all Obj that belongs // the same table as the given one +// This function returns the same concrete type as passed, +// e.g. QuotaObj, CounterObj or NamedObj. Prefer using the more +// generic NamedObj over the legacy QuotaObj and CounterObj types. func (cc *Conn) GetObjReset(o Obj) ([]Obj, error) { - return cc.getObj(nil, o.table(), unix.NFT_MSG_GETOBJ_RESET) + return cc.getObjWithLegacyType(nil, o.table(), unix.NFT_MSG_GETOBJ_RESET, cc.useLegacyObjType(o)) } // GetObject gets the specified Object +// This function returns the same concrete type as passed, +// e.g. QuotaObj, CounterObj or NamedObj. Prefer using the more +// generic NamedObj over the legacy QuotaObj and CounterObj types. func (cc *Conn) GetObject(o Obj) (Obj, error) { objs, err := cc.getObj(o, o.table(), unix.NFT_MSG_GETOBJ) @@ -107,11 +188,22 @@ func (cc *Conn) GetObject(o Obj) (Obj, error) { } // GetObjects get all the Obj that belongs to the given table +// This function will always return legacy QuotaObj/CounterObj +// types for backwards compatibility func (cc *Conn) GetObjects(t *Table) ([]Obj, error) { return cc.getObj(nil, t, unix.NFT_MSG_GETOBJ) } +// GetNamedObjects get all the Obj that belongs to the given table +// This function always return NamedObj types +func (cc *Conn) GetNamedObjects(t *Table) ([]Obj, error) { + return cc.getObjWithLegacyType(nil, t, unix.NFT_MSG_GETOBJ, false) +} + // ResetObject reset the given Obj +// This function returns the same concrete type as passed, +// e.g. QuotaObj, CounterObj or NamedObj. Prefer using the more +// generic NamedObj over the legacy QuotaObj and CounterObj types. func (cc *Conn) ResetObject(o Obj) (Obj, error) { objs, err := cc.getObj(o, o.table(), unix.NFT_MSG_GETOBJ_RESET) @@ -123,11 +215,19 @@ func (cc *Conn) ResetObject(o Obj) (Obj, error) { } // ResetObjects reset all the Obj that belongs to the given table +// This function will always return legacy QuotaObj/CounterObj +// types for backwards compatibility func (cc *Conn) ResetObjects(t *Table) ([]Obj, error) { return cc.getObj(nil, t, unix.NFT_MSG_GETOBJ_RESET) } -func objFromMsg(msg netlink.Message) (Obj, error) { +// ResetNamedObjects reset all the Obj that belongs to the given table +// This function always return NamedObj types +func (cc *Conn) ResetNamedObjects(t *Table) ([]Obj, error) { + return cc.getObjWithLegacyType(nil, t, unix.NFT_MSG_GETOBJ_RESET, false) +} + +func objFromMsg(msg netlink.Message, returnLegacyType bool) (Obj, error) { if got, want1, want2 := msg.Header.Type, newObjHeaderType, delObjHeaderType; got != want1 && got != want2 { return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2) } @@ -141,7 +241,6 @@ func objFromMsg(msg netlink.Message) (Obj, error) { name string objectType uint32 ) - const NFT_OBJECT_COUNTER = 1 // TODO: get into x/sys/unix for ad.Next() { switch ad.Type() { case unix.NFTA_OBJ_TABLE: @@ -151,38 +250,30 @@ func objFromMsg(msg netlink.Message) (Obj, error) { case unix.NFTA_OBJ_TYPE: objectType = ad.Uint32() case unix.NFTA_OBJ_DATA: - switch objectType { - case NFT_OBJECT_COUNTER: - o := CounterObj{ - Table: table, - Name: name, - } - - ad.Do(func(b []byte) error { - ad, err := netlink.NewAttributeDecoder(b) - if err != nil { - return err - } - ad.ByteOrder = binary.BigEndian - return o.unmarshal(ad) - }) - return &o, ad.Err() - case NFT_OBJECT_QUOTA: - o := QuotaObj{ - Table: table, - Name: name, - } - - ad.Do(func(b []byte) error { - ad, err := netlink.NewAttributeDecoder(b) - if err != nil { - return err - } - ad.ByteOrder = binary.BigEndian - return o.unmarshal(ad) - }) - return &o, ad.Err() + if returnLegacyType { + return objDataFromMsgLegacy(ad, table, name, objectType) + } + + o := NamedObj{ + Table: table, + Name: name, + Type: ObjType(objectType), + } + + objs, err := parseexprfunc.ParseExprBytesFromNameFunc(byte(o.family()), ad, objByObjTypeMagic[o.Type]) + if err != nil { + return nil, err + } + if len(objs) == 0 { + return nil, fmt.Errorf("objFromMsg: objs is empty for obj %v", o) } + exprs := make([]expr.Any, len(objs)) + for i := range exprs { + exprs[i] = objs[i].(expr.Any) + } + + o.Obj = exprs[0] + return &o, ad.Err() } } if err := ad.Err(); err != nil { @@ -191,7 +282,50 @@ func objFromMsg(msg netlink.Message) (Obj, error) { return nil, fmt.Errorf("malformed stateful object") } +func objDataFromMsgLegacy(ad *netlink.AttributeDecoder, table *Table, name string, objectType uint32) (Obj, error) { + switch objectType { + case unix.NFT_OBJECT_COUNTER: + o := CounterObj{ + Table: table, + Name: name, + } + + ad.Do(func(b []byte) error { + ad, err := netlink.NewAttributeDecoder(b) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + return o.unmarshal(ad) + }) + return &o, ad.Err() + case unix.NFT_OBJECT_QUOTA: + o := QuotaObj{ + Table: table, + Name: name, + } + + ad.Do(func(b []byte) error { + ad, err := netlink.NewAttributeDecoder(b) + if err != nil { + return err + } + ad.ByteOrder = binary.BigEndian + return o.unmarshal(ad) + }) + return &o, ad.Err() + } + if err := ad.Err(); err != nil { + return nil, err + } + return nil, fmt.Errorf("malformed stateful object") +} + func (cc *Conn) getObj(o Obj, t *Table, msgType uint16) ([]Obj, error) { + return cc.getObjWithLegacyType(o, t, msgType, cc.useLegacyObjType(o)) +} + +func (cc *Conn) getObjWithLegacyType(o Obj, t *Table, msgType uint16, returnLegacyObjType bool) ([]Obj, error) { conn, closer, err := cc.netlinkConn() if err != nil { return nil, err @@ -202,7 +336,12 @@ func (cc *Conn) getObj(o Obj, t *Table, msgType uint16) ([]Obj, error) { var flags netlink.HeaderFlags if o != nil { - data, err = o.marshal(false) + attrs := []netlink.Attribute{ + {Type: unix.NFTA_OBJ_TABLE, Data: []byte(o.table().Name + "\x00")}, + {Type: unix.NFTA_OBJ_NAME, Data: []byte(o.name() + "\x00")}, + {Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(o.objType()))}, + } + data = cc.marshalAttr(attrs) } else { flags = netlink.Dump data, err = netlink.MarshalAttributes([]netlink.Attribute{ @@ -227,11 +366,11 @@ func (cc *Conn) getObj(o Obj, t *Table, msgType uint16) ([]Obj, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %v", err) + return nil, fmt.Errorf("receiveAckAware: %v", err) } var objs []Obj for _, msg := range reply { - o, err := objFromMsg(msg) + o, err := objFromMsg(msg, returnLegacyObjType) if err != nil { return nil, err } @@ -240,3 +379,14 @@ func (cc *Conn) getObj(o Obj, t *Table, msgType uint16) ([]Obj, error) { return objs, nil } + +func (cc *Conn) useLegacyObjType(o Obj) bool { + useLegacyType := true + if o != nil { + switch o.(type) { + case *NamedObj: + useLegacyType = false + } + } + return useLegacyType +} diff --git a/vendor/github.com/google/nftables/quota.go b/vendor/github.com/google/nftables/quota.go index 71cb9bb5..a8be6346 100644 --- a/vendor/github.com/google/nftables/quota.go +++ b/vendor/github.com/google/nftables/quota.go @@ -15,16 +15,11 @@ package nftables import ( - "github.com/google/nftables/binaryutil" + "github.com/google/nftables/expr" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) -const ( - NFTA_OBJ_USERDATA = 8 - NFT_OBJECT_QUOTA = 2 -) - type QuotaObj struct { Table *Table Name string @@ -41,36 +36,12 @@ func (q *QuotaObj) unmarshal(ad *netlink.AttributeDecoder) error { case unix.NFTA_QUOTA_CONSUMED: q.Consumed = ad.Uint64() case unix.NFTA_QUOTA_FLAGS: - q.Over = (ad.Uint32() & unix.NFT_QUOTA_F_INV) == 1 + q.Over = (ad.Uint32() & unix.NFT_QUOTA_F_INV) != 0 } } return nil } -func (q *QuotaObj) marshal(data bool) ([]byte, error) { - flags := uint32(0) - if q.Over { - flags = unix.NFT_QUOTA_F_INV - } - obj, err := netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_QUOTA_BYTES, Data: binaryutil.BigEndian.PutUint64(q.Bytes)}, - {Type: unix.NFTA_QUOTA_CONSUMED, Data: binaryutil.BigEndian.PutUint64(q.Consumed)}, - {Type: unix.NFTA_QUOTA_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}, - }) - if err != nil { - return nil, err - } - attrs := []netlink.Attribute{ - {Type: unix.NFTA_OBJ_TABLE, Data: []byte(q.Table.Name + "\x00")}, - {Type: unix.NFTA_OBJ_NAME, Data: []byte(q.Name + "\x00")}, - {Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(NFT_OBJECT_QUOTA)}, - } - if data { - attrs = append(attrs, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA, Data: obj}) - } - return netlink.MarshalAttributes(attrs) -} - func (q *QuotaObj) table() *Table { return q.Table } @@ -78,3 +49,19 @@ func (q *QuotaObj) table() *Table { func (q *QuotaObj) family() TableFamily { return q.Table.Family } + +func (q *QuotaObj) data() expr.Any { + return &expr.Quota{ + Bytes: q.Bytes, + Consumed: q.Consumed, + Over: q.Over, + } +} + +func (q *QuotaObj) name() string { + return q.Name +} + +func (q *QuotaObj) objType() ObjType { + return ObjTypeQuota +} diff --git a/vendor/github.com/google/nftables/rule.go b/vendor/github.com/google/nftables/rule.go index 8bcfda18..07068344 100644 --- a/vendor/github.com/google/nftables/rule.go +++ b/vendor/github.com/google/nftables/rule.go @@ -92,7 +92,7 @@ func (cc *Conn) GetRules(t *Table, c *Chain) ([]*Rule, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %v", err) + return nil, fmt.Errorf("receiveAckAware: %v", err) } var rules []*Rule for _, msg := range reply { diff --git a/vendor/github.com/google/nftables/set.go b/vendor/github.com/google/nftables/set.go index 192c6190..a7441d9a 100644 --- a/vendor/github.com/google/nftables/set.go +++ b/vendor/github.com/google/nftables/set.go @@ -21,10 +21,10 @@ import ( "strings" "time" + "github.com/google/nftables/binaryutil" "github.com/google/nftables/expr" "github.com/google/nftables/internal/parseexprfunc" - - "github.com/google/nftables/binaryutil" + "github.com/google/nftables/userdata" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) @@ -249,6 +249,7 @@ type Set struct { Anonymous bool Constant bool Interval bool + AutoMerge bool IsMap bool HasTimeout bool Counter bool @@ -265,6 +266,9 @@ type Set struct { // Either host (binaryutil.NativeEndian) or big (binaryutil.BigEndian) endian as per // https://git.netfilter.org/nftables/tree/include/datatype.h?id=d486c9e626405e829221b82d7355558005b26d8a#n109 KeyByteOrder binaryutil.ByteOrder + Comment string + // Indicates that the set has "size" specifier + Size uint32 } // SetElement represents a data point within a set. @@ -286,6 +290,7 @@ type SetElement struct { Expires time.Duration Counter *expr.Counter + Comment string } func (s *SetElement) decode(fam byte) func(b []byte) error { @@ -320,8 +325,14 @@ func (s *SetElement) decode(fam byte) func(b []byte) error { s.Timeout = time.Millisecond * time.Duration(ad.Uint64()) case unix.NFTA_SET_ELEM_EXPIRATION: s.Expires = time.Millisecond * time.Duration(ad.Uint64()) + case unix.NFTA_SET_ELEM_USERDATA: + userData := ad.Bytes() + // Try to extract comment from userdata if present + if comment, ok := userdata.GetString(userData, userdata.NFTNL_UDATA_SET_ELEM_COMMENT); ok { + s.Comment = comment + } case unix.NFTA_SET_ELEM_EXPR: - elems, err := parseexprfunc.ParseExprBytesFunc(fam, ad, ad.Bytes()) + elems, err := parseexprfunc.ParseExprBytesFunc(fam, ad) if err != nil { return err } @@ -452,6 +463,12 @@ func (s *Set) makeElemList(vals []SetElement, id uint32) ([]netlink.Attribute, e // If niether of previous cases matche, it means 'e' is an element of a regular Set, no need to add to the attributes } + // Add comment to userdata if present + if len(v.Comment) > 0 { + userData := userdata.AppendString(nil, userdata.NFTNL_UDATA_SET_ELEM_COMMENT, v.Comment) + item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_USERDATA, Data: userData}) + } + encodedItem, err := netlink.MarshalAttributes(item) if err != nil { return nil, fmt.Errorf("marshal item %d: %v", i, err) @@ -551,6 +568,21 @@ func (cc *Conn) AddSet(s *Set, vals []SetElement) error { } tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: numberOfElements}) } + + var descBytes []byte + + if s.Size > 0 { + // Marshal set size description + descSizeBytes, err := netlink.MarshalAttributes([]netlink.Attribute{ + {Type: unix.NFTA_SET_DESC_SIZE, Data: binaryutil.BigEndian.PutUint32(s.Size)}, + }) + if err != nil { + return fmt.Errorf("fail to marshal set size description: %w", err) + } + + descBytes = append(descBytes, descSizeBytes...) + } + if s.Concatenation { // Length of concatenated types is a must, otherwise segfaults when executing nft list ruleset var concatDefinition []byte @@ -577,18 +609,39 @@ func (cc *Conn) AddSet(s *Set, vals []SetElement) error { if err != nil { return fmt.Errorf("fail to marshal concat definition %v", err) } - // Marshal concat size description as set description - tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: concatBytes}) + + descBytes = append(descBytes, concatBytes...) + } + + if len(descBytes) > 0 { + // Marshal set description + tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: descBytes}) } + + // https://git.netfilter.org/libnftnl/tree/include/udata.h#n17 + var userData []byte + if s.Anonymous || s.Constant || s.Interval || s.KeyByteOrder == binaryutil.BigEndian { - tableInfo = append(tableInfo, - // Semantically useless - kept for binary compatability with nft - netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x02\x00\x00\x00")}) + // Semantically useless - kept for binary compatability with nft + userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_KEYBYTEORDER, 2) } else if s.KeyByteOrder == binaryutil.NativeEndian { // Per https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1165 - tableInfo = append(tableInfo, - netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x01\x00\x00\x00")}) + userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_KEYBYTEORDER, 1) + } + + if s.Interval && s.AutoMerge { + // https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1174 + userData = userdata.AppendUint32(userData, userdata.NFTNL_UDATA_SET_MERGE_ELEMENTS, 1) + } + + if len(s.Comment) != 0 { + userData = userdata.AppendString(userData, userdata.NFTNL_UDATA_SET_COMMENT, s.Comment) + } + + if len(userData) > 0 { + tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: userData}) } + if s.Counter { data, err := netlink.MarshalAttributes([]netlink.Attribute{ {Type: unix.NFTA_LIST_ELEM, Data: []byte("counter\x00")}, @@ -716,6 +769,7 @@ func setsFromMsg(msg netlink.Message) (*Set, error) { set.Interval = (flags & unix.NFT_SET_INTERVAL) != 0 set.IsMap = (flags & unix.NFT_SET_MAP) != 0 set.HasTimeout = (flags & unix.NFT_SET_TIMEOUT) != 0 + set.Dynamic = (flags & unix.NFT_SET_EVAL) != 0 set.Concatenation = (flags & NFT_SET_CONCAT) != 0 case unix.NFTA_SET_KEY_TYPE: nftMagic := ad.Uint32() @@ -740,6 +794,24 @@ func setsFromMsg(msg netlink.Message) (*Set, error) { set.DataType = dt case unix.NFTA_SET_DATA_LEN: set.DataType.Bytes = binary.BigEndian.Uint32(ad.Bytes()) + case unix.NFTA_SET_USERDATA: + data := ad.Bytes() + value, ok := userdata.GetUint32(data, userdata.NFTNL_UDATA_SET_MERGE_ELEMENTS) + set.AutoMerge = ok && value == 1 + case unix.NFTA_SET_DESC: + nestedAD, err := netlink.NewAttributeDecoder(ad.Bytes()) + if err != nil { + return nil, fmt.Errorf("nested NewAttributeDecoder() failed: %w", err) + } + for nestedAD.Next() { + switch nestedAD.Type() { + case unix.NFTA_SET_DESC_SIZE: + set.Size = binary.BigEndian.Uint32(nestedAD.Bytes()) + } + } + if nestedAD.Err() != nil { + return nil, fmt.Errorf("decoding set description: %w", nestedAD.Err()) + } } } return &set, nil @@ -785,6 +857,7 @@ func elementsFromMsg(fam byte, msg netlink.Message) ([]SetElement, error) { b := ad.Bytes() if ad.Type() == unix.NFTA_SET_ELEM_LIST_ELEMENTS { ad, err := netlink.NewAttributeDecoder(b) + if err != nil { return nil, err } @@ -796,6 +869,7 @@ func elementsFromMsg(fam byte, msg netlink.Message) ([]SetElement, error) { case unix.NFTA_LIST_ELEM: ad.Do(elem.decode(fam)) } + elements = append(elements, elem) } } @@ -832,7 +906,7 @@ func (cc *Conn) GetSets(t *Table) ([]*Set, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %v", err) + return nil, fmt.Errorf("receiveAckAware: %v", err) } var sets []*Set for _, msg := range reply { @@ -877,11 +951,11 @@ func (cc *Conn) GetSetByName(t *Table, name string) (*Set, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %w", err) + return nil, fmt.Errorf("receiveAckAware: %w", err) } if len(reply) != 1 { - return nil, fmt.Errorf("Receive: expected to receive 1 message but got %d", len(reply)) + return nil, fmt.Errorf("receiveAckAware: expected to receive 1 message but got %d", len(reply)) } rs, err := setsFromMsg(reply[0]) if err != nil { @@ -922,7 +996,7 @@ func (cc *Conn) GetSetElements(s *Set) ([]SetElement, error) { reply, err := receiveAckAware(conn, message.Header.Flags) if err != nil { - return nil, fmt.Errorf("Receive: %v", err) + return nil, fmt.Errorf("receiveAckAware: %v", err) } var elems []SetElement for _, msg := range reply { diff --git a/vendor/github.com/google/nftables/table.go b/vendor/github.com/google/nftables/table.go index ff3b5928..c391b7be 100644 --- a/vendor/github.com/google/nftables/table.go +++ b/vendor/github.com/google/nftables/table.go @@ -112,6 +112,25 @@ func (cc *Conn) FlushTable(t *Table) { }) } +// ListTable returns table found for the specified name. Searches for +// the table under IPv4 family. As per nft man page: "When no address +// family is specified, ip is used by default." +func (cc *Conn) ListTable(name string) (*Table, error) { + return cc.ListTableOfFamily(name, TableFamilyIPv4) +} + +// ListTableOfFamily returns table found for the specified name and table family +func (cc *Conn) ListTableOfFamily(name string, family TableFamily) (*Table, error) { + t, err := cc.listTablesOfNameAndFamily(name, family) + if err != nil { + return nil, err + } + if got, want := len(t), 1; got != want { + return nil, fmt.Errorf("expected table count %d, got %d", want, got) + } + return t[0], nil +} + // ListTables returns currently configured tables in the kernel func (cc *Conn) ListTables() ([]*Table, error) { return cc.ListTablesOfFamily(TableFamilyUnspecified) @@ -120,18 +139,31 @@ func (cc *Conn) ListTables() ([]*Table, error) { // ListTablesOfFamily returns currently configured tables for the specified table family // in the kernel. It lists all tables if family is TableFamilyUnspecified. func (cc *Conn) ListTablesOfFamily(family TableFamily) ([]*Table, error) { + return cc.listTablesOfNameAndFamily("", family) +} + +func (cc *Conn) listTablesOfNameAndFamily(name string, family TableFamily) ([]*Table, error) { conn, closer, err := cc.netlinkConn() if err != nil { return nil, err } defer func() { _ = closer() }() + data := extraHeader(uint8(family), 0) + flags := netlink.Request | netlink.Dump + if name != "" { + data = append(data, cc.marshalAttr([]netlink.Attribute{ + {Type: unix.NFTA_TABLE_NAME, Data: []byte(name + "\x00")}, + })...) + flags = netlink.Request + } + msg := netlink.Message{ Header: netlink.Header{ Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETTABLE), - Flags: netlink.Request | netlink.Dump, + Flags: flags, }, - Data: extraHeader(uint8(family), 0), + Data: data, } response, err := conn.Execute(msg) diff --git a/vendor/github.com/google/nftables/userdata/userdata.go b/vendor/github.com/google/nftables/userdata/userdata.go new file mode 100644 index 00000000..984d84c8 --- /dev/null +++ b/vendor/github.com/google/nftables/userdata/userdata.go @@ -0,0 +1,115 @@ +// Copyright 2018 Google LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package userdata implements a TLV parser/serializer for libnftables-compatible comments +package userdata + +import ( + "bytes" + "encoding/binary" +) + +type Type byte + +// TLV type values are defined in: +// https://git.netfilter.org/iptables/tree/iptables/nft.c?id=73611d5582e72367a698faf1b5301c836e981465#n1659 +const ( + TypeComment Type = iota + TypeEbtablesPolicy + + TypesCount +) + +// TLV type values are defined in: +// https://git.netfilter.org/libnftnl/tree/include/libnftnl/udata.h#n39 +const ( + NFTNL_UDATA_SET_KEYBYTEORDER Type = iota + NFTNL_UDATA_SET_DATABYTEORDER + NFTNL_UDATA_SET_MERGE_ELEMENTS + NFTNL_UDATA_SET_KEY_TYPEOF + NFTNL_UDATA_SET_DATA_TYPEOF + NFTNL_UDATA_SET_EXPR + NFTNL_UDATA_SET_DATA_INTERVAL + NFTNL_UDATA_SET_COMMENT + + NFTNL_UDATA_SET_MAX +) + +// Set element userdata types +const ( + NFTNL_UDATA_SET_ELEM_COMMENT Type = iota + NFTNL_UDATA_SET_ELEM_FLAGS +) + +func Append(udata []byte, typ Type, data []byte) []byte { + udata = append(udata, byte(typ), byte(len(data))) + udata = append(udata, data...) + + return udata +} + +func Get(udata []byte, styp Type) []byte { + for { + if len(udata) < 2 { + break + } + + typ := Type(udata[0]) + length := int(udata[1]) + data := udata[2 : 2+length] + + if styp == typ { + return data + } + + if len(udata) < 2+length { + break + } else { + udata = udata[2+length:] + } + } + + return nil +} + +func AppendUint32(udata []byte, typ Type, num uint32) []byte { + data := binary.LittleEndian.AppendUint32(nil, num) + + return Append(udata, typ, data) +} + +func GetUint32(udata []byte, typ Type) (uint32, bool) { + data := Get(udata, typ) + if data == nil { + return 0, false + } + + return binary.LittleEndian.Uint32(data), true +} + +func AppendString(udata []byte, typ Type, str string) []byte { + data := append([]byte(str), 0) + return Append(udata, typ, data) +} + +func GetString(udata []byte, typ Type) (string, bool) { + data := Get(udata, typ) + if data == nil { + return "", false + } + + data, _ = bytes.CutSuffix(data, []byte{0}) + + return string(data), true +} diff --git a/vendor/github.com/google/nftables/util.go b/vendor/github.com/google/nftables/util.go index 4f03dc09..b040ae4c 100644 --- a/vendor/github.com/google/nftables/util.go +++ b/vendor/github.com/google/nftables/util.go @@ -38,7 +38,7 @@ type NFGenMsg struct { } func (genmsg *NFGenMsg) Decode(b []byte) { - if len(b) < 16 { + if len(b) < 4 { return } genmsg.NFGenFamily = b[0] diff --git a/vendor/github.com/google/nftables/xt/comment.go b/vendor/github.com/google/nftables/xt/comment.go new file mode 100644 index 00000000..830773a9 --- /dev/null +++ b/vendor/github.com/google/nftables/xt/comment.go @@ -0,0 +1,34 @@ +package xt + +import ( + "bytes" + "fmt" +) + +// CommentSize is the fixed size of a comment info xt blob, see: +// https://elixir.bootlin.com/linux/v6.8.7/source/include/uapi/linux/netfilter/xt_comment.h#L5 +const CommentSize = 256 + +// Comment gets marshalled and unmarshalled as a fixed-sized char array, filled +// with zeros as necessary, see: +// https://elixir.bootlin.com/linux/v6.8.7/source/include/uapi/linux/netfilter/xt_comment.h#L7 +type Comment string + +func (c *Comment) marshal(fam TableFamily, rev uint32) ([]byte, error) { + if len(*c) >= CommentSize { + return nil, fmt.Errorf("comment must be less than %d bytes, got %d bytes", + CommentSize, len(*c)) + } + data := make([]byte, CommentSize) + copy(data, []byte(*c)) + return data, nil +} + +func (c *Comment) unmarshal(fam TableFamily, rev uint32, data []byte) error { + if len(data) != CommentSize { + return fmt.Errorf("malformed comment: got %d bytes, expected exactly %d bytes", + len(data), CommentSize) + } + *c = Comment(bytes.TrimRight(data, "\x00")) + return nil +} diff --git a/vendor/github.com/google/nftables/xt/info.go b/vendor/github.com/google/nftables/xt/info.go index 0cf9ab95..4706ba5f 100644 --- a/vendor/github.com/google/nftables/xt/info.go +++ b/vendor/github.com/google/nftables/xt/info.go @@ -34,6 +34,9 @@ func Unmarshal(name string, fam TableFamily, rev uint32, data []byte) (InfoAny, case 1: i = &AddrTypeV1{} } + case "comment": + var c Comment + i = &c case "conntrack": switch rev { case 1: diff --git a/vendor/github.com/josharian/native/doc.go b/vendor/github.com/josharian/native/doc.go deleted file mode 100644 index 2ca7ddc8..00000000 --- a/vendor/github.com/josharian/native/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Package native provides easy access to native byte order. -// -// Usage: use native.Endian where you need the native binary.ByteOrder. -// -// Please think twice before using this package. -// It can break program portability. -// Native byte order is usually not the right answer. -package native diff --git a/vendor/github.com/josharian/native/endian_big.go b/vendor/github.com/josharian/native/endian_big.go deleted file mode 100644 index 77744fdd..00000000 --- a/vendor/github.com/josharian/native/endian_big.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build mips || mips64 || ppc64 || s390x -// +build mips mips64 ppc64 s390x - -package native - -import "encoding/binary" - -// Endian is the encoding/binary.ByteOrder implementation for the -// current CPU's native byte order. -var Endian = binary.BigEndian - -// IsBigEndian is whether the current CPU's native byte order is big -// endian. -const IsBigEndian = true diff --git a/vendor/github.com/josharian/native/endian_generic.go b/vendor/github.com/josharian/native/endian_generic.go deleted file mode 100644 index c15228f3..00000000 --- a/vendor/github.com/josharian/native/endian_generic.go +++ /dev/null @@ -1,31 +0,0 @@ -//go:build !mips && !mips64 && !ppc64 && !s390x && !amd64 && !386 && !arm && !arm64 && !loong64 && !mipsle && !mips64le && !ppc64le && !riscv64 && !wasm -// +build !mips,!mips64,!ppc64,!s390x,!amd64,!386,!arm,!arm64,!loong64,!mipsle,!mips64le,!ppc64le,!riscv64,!wasm - -// This file is a fallback, so that package native doesn't break -// the instant the Go project adds support for a new architecture. -// - -package native - -import ( - "encoding/binary" - "log" - "runtime" - "unsafe" -) - -var Endian binary.ByteOrder - -var IsBigEndian bool - -func init() { - b := uint16(0xff) // one byte - if *(*byte)(unsafe.Pointer(&b)) == 0 { - Endian = binary.BigEndian - IsBigEndian = true - } else { - Endian = binary.LittleEndian - IsBigEndian = false - } - log.Printf("github.com/josharian/native: unrecognized arch %v (%v), please file an issue", runtime.GOARCH, Endian) -} diff --git a/vendor/github.com/josharian/native/endian_little.go b/vendor/github.com/josharian/native/endian_little.go deleted file mode 100644 index 5098fec2..00000000 --- a/vendor/github.com/josharian/native/endian_little.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build amd64 || 386 || arm || arm64 || loong64 || mipsle || mips64le || ppc64le || riscv64 || wasm -// +build amd64 386 arm arm64 loong64 mipsle mips64le ppc64le riscv64 wasm - -package native - -import "encoding/binary" - -// Endian is the encoding/binary.ByteOrder implementation for the -// current CPU's native byte order. -var Endian = binary.LittleEndian - -// IsBigEndian is whether the current CPU's native byte order is big -// endian. -const IsBigEndian = false diff --git a/vendor/github.com/josharian/native/license b/vendor/github.com/josharian/native/license deleted file mode 100644 index 6e617a9c..00000000 --- a/vendor/github.com/josharian/native/license +++ /dev/null @@ -1,7 +0,0 @@ -Copyright 2020 Josh Bleecher Snyder - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/josharian/native/readme.md b/vendor/github.com/josharian/native/readme.md deleted file mode 100644 index 1fc5a01b..00000000 --- a/vendor/github.com/josharian/native/readme.md +++ /dev/null @@ -1,10 +0,0 @@ -Package native provides easy access to native byte order. - -`go get github.com/josharian/native` - -Usage: Use `native.Endian` where you need the native binary.ByteOrder. - -Please think twice before using this package. -It can break program portability. -Native byte order is usually not the right answer. - diff --git a/vendor/github.com/mdlayher/netlink/README.md b/vendor/github.com/mdlayher/netlink/README.md index 768d2149..c41de0d3 100644 --- a/vendor/github.com/mdlayher/netlink/README.md +++ b/vendor/github.com/mdlayher/netlink/README.md @@ -165,11 +165,19 @@ flowchart LR click go-onewire "https://github.com/SpComb/go-onewire" end + subgraph "NETLINK_SOCK_DIAG" + direction LR + + go-diag["github.com/florianl/go-diag"] + click go-diag "https://github.com/florianl/go-diag" + end + NETLINK_CONNECTOR --> netlink NETLINK_CRYPTO --> netlink NETLINK_GENERIC --> netlink NETLINK_KOBJECT_UEVENT --> netlink NETLINK_NETFILTER --> netlink NETLINK_ROUTE --> netlink + NETLINK_SOCK_DIAG --> netlink NETLINK_W1 --> netlink ``` diff --git a/vendor/github.com/mdlayher/netlink/attribute.go b/vendor/github.com/mdlayher/netlink/attribute.go index 4d3cfd35..1c81c323 100644 --- a/vendor/github.com/mdlayher/netlink/attribute.go +++ b/vendor/github.com/mdlayher/netlink/attribute.go @@ -6,7 +6,6 @@ import ( "fmt" "math" - "github.com/josharian/native" "github.com/mdlayher/netlink/nlenc" ) @@ -168,7 +167,7 @@ type AttributeDecoder struct { func NewAttributeDecoder(b []byte) (*AttributeDecoder, error) { ad := &AttributeDecoder{ // By default, use native byte order. - ByteOrder: native.Endian, + ByteOrder: binary.NativeEndian, b: b, } @@ -485,7 +484,7 @@ type AttributeEncoder struct { // NewAttributeEncoder creates an AttributeEncoder that encodes Attributes. func NewAttributeEncoder() *AttributeEncoder { - return &AttributeEncoder{ByteOrder: native.Endian} + return &AttributeEncoder{ByteOrder: binary.NativeEndian} } // Uint8 encodes uint8 data into an Attribute specified by typ. diff --git a/vendor/github.com/mdlayher/netlink/nlenc/doc.go b/vendor/github.com/mdlayher/netlink/nlenc/doc.go index 3b42119a..990d12e6 100644 --- a/vendor/github.com/mdlayher/netlink/nlenc/doc.go +++ b/vendor/github.com/mdlayher/netlink/nlenc/doc.go @@ -4,12 +4,10 @@ package nlenc import ( "encoding/binary" - - "github.com/josharian/native" ) // NativeEndian returns the native byte order of this system. func NativeEndian() binary.ByteOrder { // TODO(mdlayher): consider deprecating and removing this function for v2. - return native.Endian + return binary.NativeEndian } diff --git a/vendor/modules.txt b/vendor/modules.txt index 43a629dc..61127231 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -36,13 +36,14 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/nftables v0.2.0 +# github.com/google/nftables v0.3.0 ## explicit; go 1.21 github.com/google/nftables github.com/google/nftables/alignedbuff github.com/google/nftables/binaryutil github.com/google/nftables/expr github.com/google/nftables/internal/parseexprfunc +github.com/google/nftables/userdata github.com/google/nftables/xt # github.com/gorilla/mux v1.8.1 ## explicit; go 1.20 @@ -85,9 +86,6 @@ github.com/jaypipes/ghw/pkg/util # github.com/jaypipes/pcidb v1.0.1 ## explicit; go 1.21 github.com/jaypipes/pcidb -# github.com/josharian/native v1.1.0 -## explicit; go 1.13 -github.com/josharian/native # github.com/linuxkit/virtsock v0.0.0-20220523201153-1a23e78aa7a2 ## explicit; go 1.17 github.com/linuxkit/virtsock/pkg/vsock @@ -103,8 +101,8 @@ github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/mdlayher/netlink v1.7.2 -## explicit; go 1.18 +# github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 +## explicit; go 1.21 github.com/mdlayher/netlink github.com/mdlayher/netlink/nlenc github.com/mdlayher/netlink/nltest