Compare commits

...

3 Commits

Author SHA1 Message Date
Mikhail Sennikovsky 18a13e3ad8
Merge a0423c9897 into 8a8ad2be81 2025-06-23 08:44:00 -04:00
Gleb Zhizhchenko 8a8ad2be81
ct: Add optional direction fields (#317) 2025-06-06 11:18:25 +02:00
Mikhail Sennikovsky a0423c9897 Fix set verdict data type unmarshalling
Currently unmarshalling sets with "verdict" data type results in
the "verdict" type to be set as the key type, and the data type
remaining zero.

Properly set the verdict type to Set DataType field instead of
the KeyType.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@ionos.com>
2024-11-18 16:23:28 +01:00
3 changed files with 41 additions and 3 deletions

View File

@ -110,6 +110,12 @@ const (
CtStateUDPREPLIED
)
const (
// https://git.netfilter.org/libnftnl/tree/src/expr/ct.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n31
CtDirOriginal = iota
CtDirReply
)
// https://git.netfilter.org/libnftnl/tree/src/obj/ct_timeout.c?id=116e95aa7b6358c917de8c69f6f173874030b46b#n57
var CtStateUDPTimeoutDefaults CtStatePolicyTimeout = map[uint16]uint32{
CtStateUDPUNREPLIED: 30,
@ -122,6 +128,7 @@ type Ct struct {
SourceRegister bool
Key CtKey
Direction uint32
OptDirection bool
}
func (e *Ct) marshal(fam byte) ([]byte, error) {
@ -165,10 +172,16 @@ func (e *Ct) marshalData(fam byte) ([]byte, error) {
exprData = append(exprData, regData...)
switch e.Key {
case CtKeyPKTS, CtKeyBYTES, CtKeyAVGPKT, CtKeyL3PROTOCOL, CtKeyPROTOCOL:
if !e.OptDirection {
break
}
fallthrough
case CtKeySRC, CtKeyDST, CtKeyPROTOSRC, CtKeyPROTODST, CtKeySRCIP, CtKeyDSTIP, CtKeySRCIP6, CtKeyDSTIP6:
regData, err = netlink.MarshalAttributes(
[]netlink.Attribute{
{Type: unix.NFTA_CT_DIRECTION, Data: binaryutil.BigEndian.PutUint32(e.Direction)},
{Type: unix.NFTA_CT_DIRECTION, Data: []byte{uint8(e.Direction)}},
},
)
if err != nil {
@ -186,6 +199,8 @@ func (e *Ct) unmarshal(fam byte, data []byte) error {
return err
}
ad.ByteOrder = binary.BigEndian
var hasDirection bool
for ad.Next() {
switch ad.Type() {
case unix.NFTA_CT_KEY:
@ -193,12 +208,19 @@ func (e *Ct) unmarshal(fam byte, data []byte) error {
case unix.NFTA_CT_DREG:
e.Register = ad.Uint32()
case unix.NFTA_CT_DIRECTION:
e.Direction = ad.Uint32()
e.Direction = uint32(ad.Uint8())
hasDirection = true
case unix.NFTA_CT_SREG:
e.SourceRegister = true
e.Register = ad.Uint32()
}
}
switch e.Key {
case CtKeyPKTS, CtKeyBYTES, CtKeyAVGPKT, CtKeyL3PROTOCOL, CtKeyPROTOCOL:
e.OptDirection = hasDirection
}
return ad.Err()
}

View File

@ -78,6 +78,22 @@ func TestCt(t *testing.T) {
Direction: 1,
},
},
{
name: "Unmarshal Ct packets direction original case",
ct: Ct{
Register: 1,
Key: CtKeyPKTS,
Direction: CtDirOriginal,
OptDirection: true,
},
},
{
name: "Unmarshal Ct bytes without direction case",
ct: Ct{
Register: 1,
Key: CtKeyBYTES,
},
},
}
for _, tt := range tests {

2
set.go
View File

@ -773,7 +773,7 @@ func setsFromMsg(msg netlink.Message) (*Set, error) {
nftMagic := ad.Uint32()
// Special case for the data type verdict, in the message it is stored as 0xffffff00 but it is defined as 1
if nftMagic == 0xffffff00 {
set.KeyType = TypeVerdict
set.DataType = TypeVerdict
break
}
dt, err := parseSetDatatype(nftMagic)