Support XFRMA_REPLAY_VAL attribute

Add support of XFRMA_REPLAY_VAL which can be used with various XFRM
state-related messages.
This commit is contained in:
Yutaro Hayakawa 2022-05-08 17:20:44 +09:00 committed by Alessandro Boch
parent 1f7c9af2fa
commit ef1d7077fb
3 changed files with 57 additions and 2 deletions

View File

@ -15,6 +15,7 @@ const (
SizeofXfrmEncapTmpl = 0x18
SizeofXfrmUsersaFlush = 0x1
SizeofXfrmReplayStateEsn = 0x18
SizeofXfrmReplayState = 0x0c
)
const (
@ -338,3 +339,23 @@ func (msg *XfrmReplayStateEsn) Serialize() []byte {
// We deliberately do not pass Bmp, as it gets set by the kernel.
return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_replay_state {
// __u32 oseq;
// __u32 seq;
// __u32 bitmap;
// };
type XfrmReplayState struct {
OSeq uint32
Seq uint32
BitMap uint32
}
func DeserializeXfrmReplayState(b []byte) *XfrmReplayState {
return (*XfrmReplayState)(unsafe.Pointer(&b[0:SizeofXfrmReplayState][0]))
}
func (msg *XfrmReplayState) Serialize() []byte {
return (*(*[SizeofXfrmReplayState]byte)(unsafe.Pointer(msg)))[:]
}

View File

@ -81,6 +81,19 @@ type XfrmStateStats struct {
UseTime uint64
}
// XfrmReplayState represents the sequence number states for
// "legacy" anti-replay mode.
type XfrmReplayState struct {
OSeq uint32
Seq uint32
BitMap uint32
}
func (r XfrmReplayState) String() string {
return fmt.Sprintf("{OSeq: 0x%x, Seq: 0x%x, BitMap: 0x%x}",
r.OSeq, r.Seq, r.BitMap)
}
// XfrmState represents the state of an ipsec policy. It optionally
// contains an XfrmStateAlgo for encryption and one for authentication.
type XfrmState struct {
@ -103,11 +116,12 @@ type XfrmState struct {
ESN bool
DontEncapDSCP bool
OSeqMayWrap bool
Replay *XfrmReplayState
}
func (sa XfrmState) String() string {
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap)
return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay)
}
func (sa XfrmState) Print(stats bool) string {
if !stats {

View File

@ -77,6 +77,14 @@ func writeReplayEsn(replayWindow int) []byte {
return replayEsn.Serialize()
}
func writeReplay(r *XfrmReplayState) []byte {
return (&nl.XfrmReplayState{
OSeq: r.OSeq,
Seq: r.Seq,
BitMap: r.BitMap,
}).Serialize()
}
// XfrmStateAdd will add an xfrm state to the system.
// Equivalent to: `ip xfrm state add $state`
func XfrmStateAdd(state *XfrmState) error {
@ -177,6 +185,10 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
out := nl.NewRtAttr(nl.XFRMA_SA_EXTRA_FLAGS, nl.Uint32Attr(flags))
req.AddData(out)
}
if state.Replay != nil {
out := nl.NewRtAttr(nl.XFRMA_REPLAY_VAL, writeReplay(state.Replay))
req.AddData(out)
}
if state.Ifid != 0 {
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
@ -419,6 +431,14 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
}
case nl.XFRMA_IF_ID:
state.Ifid = int(native.Uint32(attr.Value))
case nl.XFRMA_REPLAY_VAL:
if state.Replay == nil {
state.Replay = new(XfrmReplayState)
}
replay := nl.DeserializeXfrmReplayState(attr.Value[:])
state.Replay.OSeq = replay.OSeq
state.Replay.Seq = replay.Seq
state.Replay.BitMap = replay.BitMap
}
}