github.com/cilium/cilium@v1.16.2/pkg/datapath/linux/ipsec/probe_linux.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  //go:build linux
     5  
     6  package ipsec
     7  
     8  import (
     9  	"encoding/hex"
    10  	"errors"
    11  	"net"
    12  
    13  	"github.com/vishvananda/netlink"
    14  
    15  	"github.com/cilium/cilium/pkg/datapath/linux/linux_defaults"
    16  )
    17  
    18  const (
    19  	dummyIP  = "169.254.169.254"
    20  	aeadKey  = "4242424242424242424242424242424242424242"
    21  	aeadAlgo = "rfc4106(gcm(aes))"
    22  	stateId  = 42
    23  )
    24  
    25  func initDummyXfrmState() *netlink.XfrmState {
    26  	k, _ := hex.DecodeString(aeadKey)
    27  	return &netlink.XfrmState{
    28  		Mode:  netlink.XFRM_MODE_TUNNEL,
    29  		Proto: netlink.XFRM_PROTO_ESP,
    30  		ESN:   false,
    31  		Spi:   stateId,
    32  		Reqid: stateId,
    33  		Aead: &netlink.XfrmStateAlgo{
    34  			Name:   aeadAlgo,
    35  			Key:    k,
    36  			ICVLen: 128,
    37  		},
    38  		Src: net.ParseIP(dummyIP),
    39  		Dst: net.ParseIP(dummyIP),
    40  	}
    41  }
    42  
    43  func createDummyXfrmState(state *netlink.XfrmState) error {
    44  	state.Mark = &netlink.XfrmMark{
    45  		Value: linux_defaults.RouteMarkDecrypt,
    46  		Mask:  linux_defaults.IPsecMarkMaskIn,
    47  	}
    48  	state.OutputMark = &netlink.XfrmMark{
    49  		Value: linux_defaults.RouteMarkDecrypt,
    50  		Mask:  linux_defaults.RouteMarkMask,
    51  	}
    52  	return netlink.XfrmStateAdd(state)
    53  }
    54  
    55  // ProbeXfrmStateOutputMask probes the kernel to determine if it supports
    56  // setting the xfrm state output mask (Linux 4.19+). It returns an error if
    57  // the output mask is not supported or if an error occurred, nil otherwise.
    58  func ProbeXfrmStateOutputMask() (e error) {
    59  	state := initDummyXfrmState()
    60  	err := createDummyXfrmState(state)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	defer func() {
    65  		e = errors.Join(e, netlink.XfrmStateDel(state))
    66  	}()
    67  
    68  	var probedState *netlink.XfrmState
    69  	if probedState, err = netlink.XfrmStateGet(state); err != nil {
    70  		return err
    71  	}
    72  	if probedState == nil || probedState.OutputMark == nil {
    73  		return errors.New("IPSec output mark attribute missing from xfrm probe")
    74  	}
    75  	if probedState.OutputMark.Mask != linux_defaults.RouteMarkMask {
    76  		return errors.New("incorrect value for probed IPSec output mask attribute")
    77  	}
    78  	return
    79  }