summaryrefslogtreecommitdiff
path: root/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'vendor/github.com/vishvananda/netlink/xfrm_state_linux.go')
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go444
1 files changed, 444 insertions, 0 deletions
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
new file mode 100644
index 000000000..6a7bc0dec
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -0,0 +1,444 @@
+package netlink
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+
+ "github.com/vishvananda/netlink/nl"
+)
+
+func writeStateAlgo(a *XfrmStateAlgo) []byte {
+ algo := nl.XfrmAlgo{
+ AlgKeyLen: uint32(len(a.Key) * 8),
+ AlgKey: a.Key,
+ }
+ end := len(a.Name)
+ if end > 64 {
+ end = 64
+ }
+ copy(algo.AlgName[:end], a.Name)
+ return algo.Serialize()
+}
+
+func writeStateAlgoAuth(a *XfrmStateAlgo) []byte {
+ algo := nl.XfrmAlgoAuth{
+ AlgKeyLen: uint32(len(a.Key) * 8),
+ AlgTruncLen: uint32(a.TruncateLen),
+ AlgKey: a.Key,
+ }
+ end := len(a.Name)
+ if end > 64 {
+ end = 64
+ }
+ copy(algo.AlgName[:end], a.Name)
+ return algo.Serialize()
+}
+
+func writeStateAlgoAead(a *XfrmStateAlgo) []byte {
+ algo := nl.XfrmAlgoAEAD{
+ AlgKeyLen: uint32(len(a.Key) * 8),
+ AlgICVLen: uint32(a.ICVLen),
+ AlgKey: a.Key,
+ }
+ end := len(a.Name)
+ if end > 64 {
+ end = 64
+ }
+ copy(algo.AlgName[:end], a.Name)
+ return algo.Serialize()
+}
+
+func writeMark(m *XfrmMark) []byte {
+ mark := &nl.XfrmMark{
+ Value: m.Value,
+ Mask: m.Mask,
+ }
+ if mark.Mask == 0 {
+ mark.Mask = ^uint32(0)
+ }
+ return mark.Serialize()
+}
+
+func writeReplayEsn(replayWindow int) []byte {
+ replayEsn := &nl.XfrmReplayStateEsn{
+ OSeq: 0,
+ Seq: 0,
+ OSeqHi: 0,
+ SeqHi: 0,
+ ReplayWindow: uint32(replayWindow),
+ }
+
+ // taken from iproute2/ip/xfrm_state.c:
+ replayEsn.BmpLen = uint32((replayWindow + (4 * 8) - 1) / (4 * 8))
+
+ return replayEsn.Serialize()
+}
+
+// XfrmStateAdd will add an xfrm state to the system.
+// Equivalent to: `ip xfrm state add $state`
+func XfrmStateAdd(state *XfrmState) error {
+ return pkgHandle.XfrmStateAdd(state)
+}
+
+// XfrmStateAdd will add an xfrm state to the system.
+// Equivalent to: `ip xfrm state add $state`
+func (h *Handle) XfrmStateAdd(state *XfrmState) error {
+ return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA)
+}
+
+// XfrmStateAllocSpi will allocate an xfrm state in the system.
+// Equivalent to: `ip xfrm state allocspi`
+func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
+ return pkgHandle.xfrmStateAllocSpi(state)
+}
+
+// XfrmStateUpdate will update an xfrm state to the system.
+// Equivalent to: `ip xfrm state update $state`
+func XfrmStateUpdate(state *XfrmState) error {
+ return pkgHandle.XfrmStateUpdate(state)
+}
+
+// XfrmStateUpdate will update an xfrm state to the system.
+// Equivalent to: `ip xfrm state update $state`
+func (h *Handle) XfrmStateUpdate(state *XfrmState) error {
+ return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_UPDSA)
+}
+
+func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
+
+ // A state with spi 0 can't be deleted so don't allow it to be set
+ if state.Spi == 0 {
+ return fmt.Errorf("Spi must be set when adding xfrm state.")
+ }
+ req := h.newNetlinkRequest(nlProto, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+ msg := xfrmUsersaInfoFromXfrmState(state)
+
+ if state.ESN {
+ if state.ReplayWindow == 0 {
+ return fmt.Errorf("ESN flag set without ReplayWindow")
+ }
+ msg.Flags |= nl.XFRM_STATE_ESN
+ msg.ReplayWindow = 0
+ }
+
+ limitsToLft(state.Limits, &msg.Lft)
+ req.AddData(msg)
+
+ if state.Auth != nil {
+ out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth))
+ req.AddData(out)
+ }
+ if state.Crypt != nil {
+ out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt))
+ req.AddData(out)
+ }
+ if state.Aead != nil {
+ out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead))
+ req.AddData(out)
+ }
+ if state.Encap != nil {
+ encapData := make([]byte, nl.SizeofXfrmEncapTmpl)
+ encap := nl.DeserializeXfrmEncapTmpl(encapData)
+ encap.EncapType = uint16(state.Encap.Type)
+ encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort))
+ encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort))
+ encap.EncapOa.FromIP(state.Encap.OriginalAddress)
+ out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData)
+ req.AddData(out)
+ }
+ if state.Mark != nil {
+ out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark))
+ req.AddData(out)
+ }
+ if state.ESN {
+ out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
+ req.AddData(out)
+ }
+
+ _, err := req.Execute(syscall.NETLINK_XFRM, 0)
+ return err
+}
+
+func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
+ req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI,
+ syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+ msg := &nl.XfrmUserSpiInfo{}
+ msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state))
+ // 1-255 is reserved by IANA for future use
+ msg.Min = 0x100
+ msg.Max = 0xffffffff
+ req.AddData(msg)
+
+ if state.Mark != nil {
+ out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark))
+ req.AddData(out)
+ }
+
+ msgs, err := req.Execute(syscall.NETLINK_XFRM, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ s, err := parseXfrmState(msgs[0], FAMILY_ALL)
+ if err != nil {
+ return nil, err
+ }
+
+ return s, err
+}
+
+// XfrmStateDel will delete an xfrm state from the system. Note that
+// the Algos are ignored when matching the state to delete.
+// Equivalent to: `ip xfrm state del $state`
+func XfrmStateDel(state *XfrmState) error {
+ return pkgHandle.XfrmStateDel(state)
+}
+
+// XfrmStateDel will delete an xfrm state from the system. Note that
+// the Algos are ignored when matching the state to delete.
+// Equivalent to: `ip xfrm state del $state`
+func (h *Handle) XfrmStateDel(state *XfrmState) error {
+ _, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA)
+ return err
+}
+
+// XfrmStateList gets a list of xfrm states in the system.
+// Equivalent to: `ip [-4|-6] xfrm state show`.
+// The list can be filtered by ip family.
+func XfrmStateList(family int) ([]XfrmState, error) {
+ return pkgHandle.XfrmStateList(family)
+}
+
+// XfrmStateList gets a list of xfrm states in the system.
+// Equivalent to: `ip xfrm state show`.
+// The list can be filtered by ip family.
+func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) {
+ req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)
+
+ msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
+ if err != nil {
+ return nil, err
+ }
+
+ var res []XfrmState
+ for _, m := range msgs {
+ if state, err := parseXfrmState(m, family); err == nil {
+ res = append(res, *state)
+ } else if err == familyError {
+ continue
+ } else {
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+// XfrmStateGet gets the xfrm state described by the ID, if found.
+// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`.
+// Only the fields which constitue the SA ID must be filled in:
+// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]
+// mark is optional
+func XfrmStateGet(state *XfrmState) (*XfrmState, error) {
+ return pkgHandle.XfrmStateGet(state)
+}
+
+// XfrmStateGet gets the xfrm state described by the ID, if found.
+// Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`.
+// Only the fields which constitue the SA ID must be filled in:
+// ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]
+// mark is optional
+func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) {
+ return h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_GETSA)
+}
+
+func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) {
+ req := h.newNetlinkRequest(nlProto, syscall.NLM_F_ACK)
+
+ msg := &nl.XfrmUsersaId{}
+ msg.Family = uint16(nl.GetIPFamily(state.Dst))
+ msg.Daddr.FromIP(state.Dst)
+ msg.Proto = uint8(state.Proto)
+ msg.Spi = nl.Swap32(uint32(state.Spi))
+ req.AddData(msg)
+
+ if state.Mark != nil {
+ out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark))
+ req.AddData(out)
+ }
+ if state.Src != nil {
+ out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16())
+ req.AddData(out)
+ }
+
+ resType := nl.XFRM_MSG_NEWSA
+ if nlProto == nl.XFRM_MSG_DELSA {
+ resType = 0
+ }
+
+ msgs, err := req.Execute(syscall.NETLINK_XFRM, uint16(resType))
+ if err != nil {
+ return nil, err
+ }
+
+ if nlProto == nl.XFRM_MSG_DELSA {
+ return nil, nil
+ }
+
+ s, err := parseXfrmState(msgs[0], FAMILY_ALL)
+ if err != nil {
+ return nil, err
+ }
+
+ return s, nil
+}
+
+var familyError = fmt.Errorf("family error")
+
+func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState {
+ var state XfrmState
+
+ state.Dst = msg.Id.Daddr.ToIP()
+ state.Src = msg.Saddr.ToIP()
+ state.Proto = Proto(msg.Id.Proto)
+ state.Mode = Mode(msg.Mode)
+ state.Spi = int(nl.Swap32(msg.Id.Spi))
+ state.Reqid = int(msg.Reqid)
+ state.ReplayWindow = int(msg.ReplayWindow)
+ lftToLimits(&msg.Lft, &state.Limits)
+
+ return &state
+}
+
+func parseXfrmState(m []byte, family int) (*XfrmState, error) {
+ msg := nl.DeserializeXfrmUsersaInfo(m)
+
+ // This is mainly for the state dump
+ if family != FAMILY_ALL && family != int(msg.Family) {
+ return nil, familyError
+ }
+
+ state := xfrmStateFromXfrmUsersaInfo(msg)
+
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:])
+ if err != nil {
+ return nil, err
+ }
+
+ for _, attr := range attrs {
+ switch attr.Attr.Type {
+ case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT:
+ var resAlgo *XfrmStateAlgo
+ if attr.Attr.Type == nl.XFRMA_ALG_AUTH {
+ if state.Auth == nil {
+ state.Auth = new(XfrmStateAlgo)
+ }
+ resAlgo = state.Auth
+ } else {
+ state.Crypt = new(XfrmStateAlgo)
+ resAlgo = state.Crypt
+ }
+ algo := nl.DeserializeXfrmAlgo(attr.Value[:])
+ (*resAlgo).Name = nl.BytesToString(algo.AlgName[:])
+ (*resAlgo).Key = algo.AlgKey
+ case nl.XFRMA_ALG_AUTH_TRUNC:
+ if state.Auth == nil {
+ state.Auth = new(XfrmStateAlgo)
+ }
+ algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:])
+ state.Auth.Name = nl.BytesToString(algo.AlgName[:])
+ state.Auth.Key = algo.AlgKey
+ state.Auth.TruncateLen = int(algo.AlgTruncLen)
+ case nl.XFRMA_ALG_AEAD:
+ state.Aead = new(XfrmStateAlgo)
+ algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:])
+ state.Aead.Name = nl.BytesToString(algo.AlgName[:])
+ state.Aead.Key = algo.AlgKey
+ state.Aead.ICVLen = int(algo.AlgICVLen)
+ case nl.XFRMA_ENCAP:
+ encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
+ state.Encap = new(XfrmStateEncap)
+ state.Encap.Type = EncapType(encap.EncapType)
+ state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport))
+ state.Encap.DstPort = int(nl.Swap16(encap.EncapDport))
+ state.Encap.OriginalAddress = encap.EncapOa.ToIP()
+ case nl.XFRMA_MARK:
+ mark := nl.DeserializeXfrmMark(attr.Value[:])
+ state.Mark = new(XfrmMark)
+ state.Mark.Value = mark.Value
+ state.Mark.Mask = mark.Mask
+ }
+ }
+
+ return state, nil
+}
+
+// XfrmStateFlush will flush the xfrm state on the system.
+// proto = 0 means any transformation protocols
+// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
+func XfrmStateFlush(proto Proto) error {
+ return pkgHandle.XfrmStateFlush(proto)
+}
+
+// XfrmStateFlush will flush the xfrm state on the system.
+// proto = 0 means any transformation protocols
+// Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]`
+func (h *Handle) XfrmStateFlush(proto Proto) error {
+ req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, syscall.NLM_F_ACK)
+
+ req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)})
+
+ _, err := req.Execute(syscall.NETLINK_XFRM, 0)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) {
+ if lmts.ByteSoft != 0 {
+ lft.SoftByteLimit = lmts.ByteSoft
+ } else {
+ lft.SoftByteLimit = nl.XFRM_INF
+ }
+ if lmts.ByteHard != 0 {
+ lft.HardByteLimit = lmts.ByteHard
+ } else {
+ lft.HardByteLimit = nl.XFRM_INF
+ }
+ if lmts.PacketSoft != 0 {
+ lft.SoftPacketLimit = lmts.PacketSoft
+ } else {
+ lft.SoftPacketLimit = nl.XFRM_INF
+ }
+ if lmts.PacketHard != 0 {
+ lft.HardPacketLimit = lmts.PacketHard
+ } else {
+ lft.HardPacketLimit = nl.XFRM_INF
+ }
+ lft.SoftAddExpiresSeconds = lmts.TimeSoft
+ lft.HardAddExpiresSeconds = lmts.TimeHard
+ lft.SoftUseExpiresSeconds = lmts.TimeUseSoft
+ lft.HardUseExpiresSeconds = lmts.TimeUseHard
+}
+
+func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) {
+ *lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft))
+}
+
+func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo {
+ msg := &nl.XfrmUsersaInfo{}
+ msg.Family = uint16(nl.GetIPFamily(state.Dst))
+ msg.Id.Daddr.FromIP(state.Dst)
+ msg.Saddr.FromIP(state.Src)
+ msg.Id.Proto = uint8(state.Proto)
+ msg.Mode = uint8(state.Mode)
+ msg.Id.Spi = nl.Swap32(uint32(state.Spi))
+ msg.Reqid = uint32(state.Reqid)
+ msg.ReplayWindow = uint8(state.ReplayWindow)
+
+ return msg
+}