From 211824995dcb277a4a8d86f605c3d11c21bc72f5 Mon Sep 17 00:00:00 2001 From: turekt <32360115+turekt@users.noreply.github.com> Date: Mon, 21 Feb 2022 21:42:39 +0000 Subject: [PATCH] Log expression refactor (#147) Fixes https://github.com/google/nftables/issues/113 Log expression implementation changed to better support different log options Added uint16 support to the binaryutil package Changed old log expression tests that were failing after change Added a new test to check the implementation for multiple log options --- binaryutil/binaryutil.go | 9 +++ expr/log.go | 128 ++++++++++++++++++++++++-------- nftables_test.go | 156 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 258 insertions(+), 35 deletions(-) diff --git a/binaryutil/binaryutil.go b/binaryutil/binaryutil.go index 11b5dac..27755f5 100644 --- a/binaryutil/binaryutil.go +++ b/binaryutil/binaryutil.go @@ -26,6 +26,7 @@ type ByteOrder interface { PutUint16(v uint16) []byte PutUint32(v uint32) []byte PutUint64(v uint64) []byte + Uint16(b []byte) uint16 Uint32(b []byte) uint32 Uint64(b []byte) uint64 } @@ -54,6 +55,10 @@ func (nativeEndian) PutUint64(v uint64) []byte { return buf } +func (nativeEndian) Uint16(b []byte) uint16 { + return *(*uint16)(unsafe.Pointer(&b[0])) +} + func (nativeEndian) Uint32(b []byte) uint32 { return *(*uint32)(unsafe.Pointer(&b[0])) } @@ -86,6 +91,10 @@ func (bigEndian) PutUint64(v uint64) []byte { return buf } +func (bigEndian) Uint16(b []byte) uint16 { + return binary.BigEndian.Uint16(b) +} + func (bigEndian) Uint32(b []byte) uint32 { return binary.BigEndian.Uint32(b) } diff --git a/expr/log.go b/expr/log.go index 27ec0e1..7730a92 100644 --- a/expr/log.go +++ b/expr/log.go @@ -17,43 +17,99 @@ package expr import ( "encoding/binary" + "github.com/google/nftables/binaryutil" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) +type LogLevel uint32 + +const ( + // See https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=5b364657a35f4e4cd5d220ba2a45303d729c8eca#n1226 + LogLevelEmerg LogLevel = iota + LogLevelAlert + LogLevelCrit + LogLevelErr + LogLevelWarning + LogLevelNotice + LogLevelInfo + LogLevelDebug + LogLevelAudit +) + +type LogFlags uint32 + +const ( + // See https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_log.h?id=5b364657a35f4e4cd5d220ba2a45303d729c8eca + LogFlagsTCPSeq LogFlags = 0x01 << iota + LogFlagsTCPOpt + LogFlagsIPOpt + LogFlagsUID + LogFlagsNFLog + LogFlagsMACDecode + LogFlagsMask LogFlags = 0x2f +) + // Log defines type for NFT logging +// See https://git.netfilter.org/libnftnl/tree/src/expr/log.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n25 type Log struct { - Key uint32 + Level LogLevel + // Refers to log flags (flags all, flags ip options, ...) + Flags LogFlags + // Equivalent to expression flags. + // Indicates that an option is set by setting a bit + // on index referred by the NFTA_LOG_* value. + // See https://cs.opensource.google/go/x/sys/+/3681064d:unix/ztypes_linux.go;l=2126;drc=3681064d51587c1db0324b3d5c23c2ddbcff6e8f + Key uint32 + Snaplen uint32 + Group uint16 + QThreshold uint16 + // Log prefix string content Data []byte } func (e *Log) marshal() ([]byte, error) { - var data []byte - var err error - switch e.Key { - case unix.NFTA_LOG_GROUP: - data, err = netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_LOG_GROUP, Data: e.Data}, - }) - case unix.NFTA_LOG_PREFIX: - prefix := append(e.Data, '\x00') - data, err = netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_LOG_PREFIX, Data: prefix}, - }) - case unix.NFTA_LOG_SNAPLEN: - data, err = netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_LOG_SNAPLEN, Data: e.Data}, - }) - case unix.NFTA_LOG_QTHRESHOLD: - data, err = netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_LOG_QTHRESHOLD, Data: e.Data}, - }) - case unix.NFTA_LOG_LEVEL: - level := append(e.Data, '\x00') - data, err = netlink.MarshalAttributes([]netlink.Attribute{ - {Type: unix.NFTA_LOG_LEVEL, Data: level}, + // Per https://git.netfilter.org/libnftnl/tree/src/expr/log.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n129 + attrs := make([]netlink.Attribute, 0) + if e.Key&(1<