github.com/vishvananda/netlink@v1.3.1/xfrm_state_linux.go (about) 1 package netlink 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "time" 8 "unsafe" 9 10 "github.com/vishvananda/netlink/nl" 11 "golang.org/x/sys/unix" 12 ) 13 14 // XfrmStateAlgo represents the algorithm to use for the ipsec encryption. 15 type XfrmStateAlgo struct { 16 Name string 17 Key []byte 18 TruncateLen int // Auth only 19 ICVLen int // AEAD only 20 } 21 22 func (a XfrmStateAlgo) String() string { 23 base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) 24 if a.TruncateLen != 0 { 25 base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) 26 } 27 if a.ICVLen != 0 { 28 base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) 29 } 30 return fmt.Sprintf("%s}", base) 31 } 32 33 // EncapType is an enum representing the optional packet encapsulation. 34 type EncapType uint8 35 36 const ( 37 XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 38 XFRM_ENCAP_ESPINUDP 39 ) 40 41 func (e EncapType) String() string { 42 switch e { 43 case XFRM_ENCAP_ESPINUDP_NONIKE: 44 return "espinudp-non-ike" 45 case XFRM_ENCAP_ESPINUDP: 46 return "espinudp" 47 } 48 return "unknown" 49 } 50 51 // XfrmStateEncap represents the encapsulation to use for the ipsec encryption. 52 type XfrmStateEncap struct { 53 Type EncapType 54 SrcPort int 55 DstPort int 56 OriginalAddress net.IP 57 } 58 59 func (e XfrmStateEncap) String() string { 60 return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", 61 e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) 62 } 63 64 // XfrmStateLimits represents the configured limits for the state. 65 type XfrmStateLimits struct { 66 ByteSoft uint64 67 ByteHard uint64 68 PacketSoft uint64 69 PacketHard uint64 70 TimeSoft uint64 71 TimeHard uint64 72 TimeUseSoft uint64 73 TimeUseHard uint64 74 } 75 76 // XfrmStateStats represents the current number of bytes/packets 77 // processed by this State, the State's installation and first use 78 // time and the replay window counters. 79 type XfrmStateStats struct { 80 ReplayWindow uint32 81 Replay uint32 82 Failed uint32 83 Bytes uint64 84 Packets uint64 85 AddTime uint64 86 UseTime uint64 87 } 88 89 // XfrmReplayState represents the sequence number states for 90 // "legacy" anti-replay mode. 91 type XfrmReplayState struct { 92 OSeq uint32 93 Seq uint32 94 BitMap uint32 95 } 96 97 func (r XfrmReplayState) String() string { 98 return fmt.Sprintf("{OSeq: 0x%x, Seq: 0x%x, BitMap: 0x%x}", 99 r.OSeq, r.Seq, r.BitMap) 100 } 101 102 // XfrmState represents the state of an ipsec policy. It optionally 103 // contains an XfrmStateAlgo for encryption and one for authentication. 104 type XfrmState struct { 105 Dst net.IP 106 Src net.IP 107 Proto Proto 108 Mode Mode 109 Spi int 110 Reqid int 111 ReplayWindow int 112 Limits XfrmStateLimits 113 Statistics XfrmStateStats 114 Mark *XfrmMark 115 OutputMark *XfrmMark 116 SADir SADir 117 Ifid int 118 Pcpunum *uint32 119 Auth *XfrmStateAlgo 120 Crypt *XfrmStateAlgo 121 Aead *XfrmStateAlgo 122 Encap *XfrmStateEncap 123 ESN bool 124 DontEncapDSCP bool 125 OSeqMayWrap bool 126 Replay *XfrmReplayState 127 Selector *XfrmPolicy 128 } 129 130 func (sa XfrmState) String() string { 131 return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, SADir: %d, Ifid: %d, Pcpunum: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v", 132 sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.SADir, sa.Ifid, *sa.Pcpunum, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay) 133 } 134 func (sa XfrmState) Print(stats bool) string { 135 if !stats { 136 return sa.String() 137 } 138 at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) 139 ut := "-" 140 if sa.Statistics.UseTime > 0 { 141 ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) 142 } 143 return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ 144 "AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", 145 sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), 146 sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, 147 sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) 148 } 149 150 func printLimit(lmt uint64) string { 151 if lmt == ^uint64(0) { 152 return "(INF)" 153 } 154 return fmt.Sprintf("%d", lmt) 155 } 156 func writeStateAlgo(a *XfrmStateAlgo) []byte { 157 algo := nl.XfrmAlgo{ 158 AlgKeyLen: uint32(len(a.Key) * 8), 159 AlgKey: a.Key, 160 } 161 end := len(a.Name) 162 if end > 64 { 163 end = 64 164 } 165 copy(algo.AlgName[:end], a.Name) 166 return algo.Serialize() 167 } 168 169 func writeStateAlgoAuth(a *XfrmStateAlgo) []byte { 170 algo := nl.XfrmAlgoAuth{ 171 AlgKeyLen: uint32(len(a.Key) * 8), 172 AlgTruncLen: uint32(a.TruncateLen), 173 AlgKey: a.Key, 174 } 175 end := len(a.Name) 176 if end > 64 { 177 end = 64 178 } 179 copy(algo.AlgName[:end], a.Name) 180 return algo.Serialize() 181 } 182 183 func writeStateAlgoAead(a *XfrmStateAlgo) []byte { 184 algo := nl.XfrmAlgoAEAD{ 185 AlgKeyLen: uint32(len(a.Key) * 8), 186 AlgICVLen: uint32(a.ICVLen), 187 AlgKey: a.Key, 188 } 189 end := len(a.Name) 190 if end > 64 { 191 end = 64 192 } 193 copy(algo.AlgName[:end], a.Name) 194 return algo.Serialize() 195 } 196 197 func writeMark(m *XfrmMark) []byte { 198 mark := &nl.XfrmMark{ 199 Value: m.Value, 200 Mask: m.Mask, 201 } 202 if mark.Mask == 0 { 203 mark.Mask = ^uint32(0) 204 } 205 return mark.Serialize() 206 } 207 208 func writeReplayEsn(replayWindow int) []byte { 209 replayEsn := &nl.XfrmReplayStateEsn{ 210 OSeq: 0, 211 Seq: 0, 212 OSeqHi: 0, 213 SeqHi: 0, 214 ReplayWindow: uint32(replayWindow), 215 } 216 217 // Linux stores the bitmap to identify the already received sequence packets in blocks of uint32 elements. 218 // Therefore bitmap length is the minimum number of uint32 elements needed. The following is a ceiling operation. 219 bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen)) // Any uint32 variable is good for this 220 replayEsn.BmpLen = uint32((replayWindow + (bytesPerElem * 8) - 1) / (bytesPerElem * 8)) 221 222 return replayEsn.Serialize() 223 } 224 225 func writeReplay(r *XfrmReplayState) []byte { 226 return (&nl.XfrmReplayState{ 227 OSeq: r.OSeq, 228 Seq: r.Seq, 229 BitMap: r.BitMap, 230 }).Serialize() 231 } 232 233 // XfrmStateAdd will add an xfrm state to the system. 234 // Equivalent to: `ip xfrm state add $state` 235 func XfrmStateAdd(state *XfrmState) error { 236 return pkgHandle.XfrmStateAdd(state) 237 } 238 239 // XfrmStateAdd will add an xfrm state to the system. 240 // Equivalent to: `ip xfrm state add $state` 241 func (h *Handle) XfrmStateAdd(state *XfrmState) error { 242 return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA) 243 } 244 245 // XfrmStateAllocSpi will allocate an xfrm state in the system. 246 // Equivalent to: `ip xfrm state allocspi` 247 func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { 248 return pkgHandle.xfrmStateAllocSpi(state) 249 } 250 251 // XfrmStateUpdate will update an xfrm state to the system. 252 // Equivalent to: `ip xfrm state update $state` 253 func XfrmStateUpdate(state *XfrmState) error { 254 return pkgHandle.XfrmStateUpdate(state) 255 } 256 257 // XfrmStateUpdate will update an xfrm state to the system. 258 // Equivalent to: `ip xfrm state update $state` 259 func (h *Handle) XfrmStateUpdate(state *XfrmState) error { 260 return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_UPDSA) 261 } 262 263 func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { 264 265 // A state with spi 0 can't be deleted so don't allow it to be set 266 if state.Spi == 0 { 267 return fmt.Errorf("Spi must be set when adding xfrm state") 268 } 269 req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) 270 271 msg := xfrmUsersaInfoFromXfrmState(state) 272 273 if state.ESN { 274 if state.ReplayWindow == 0 { 275 return fmt.Errorf("ESN flag set without ReplayWindow") 276 } 277 msg.Flags |= nl.XFRM_STATE_ESN 278 msg.ReplayWindow = 0 279 } 280 281 limitsToLft(state.Limits, &msg.Lft) 282 req.AddData(msg) 283 284 if state.Auth != nil { 285 out := nl.NewRtAttr(nl.XFRMA_ALG_AUTH_TRUNC, writeStateAlgoAuth(state.Auth)) 286 req.AddData(out) 287 } 288 if state.Crypt != nil { 289 out := nl.NewRtAttr(nl.XFRMA_ALG_CRYPT, writeStateAlgo(state.Crypt)) 290 req.AddData(out) 291 } 292 if state.Aead != nil { 293 out := nl.NewRtAttr(nl.XFRMA_ALG_AEAD, writeStateAlgoAead(state.Aead)) 294 req.AddData(out) 295 } 296 if state.Encap != nil { 297 encapData := make([]byte, nl.SizeofXfrmEncapTmpl) 298 encap := nl.DeserializeXfrmEncapTmpl(encapData) 299 encap.EncapType = uint16(state.Encap.Type) 300 encap.EncapSport = nl.Swap16(uint16(state.Encap.SrcPort)) 301 encap.EncapDport = nl.Swap16(uint16(state.Encap.DstPort)) 302 encap.EncapOa.FromIP(state.Encap.OriginalAddress) 303 out := nl.NewRtAttr(nl.XFRMA_ENCAP, encapData) 304 req.AddData(out) 305 } 306 if state.Mark != nil { 307 out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) 308 req.AddData(out) 309 } 310 if state.ESN { 311 out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) 312 req.AddData(out) 313 } 314 if state.OutputMark != nil { 315 out := nl.NewRtAttr(nl.XFRMA_SET_MARK, nl.Uint32Attr(state.OutputMark.Value)) 316 req.AddData(out) 317 if state.OutputMark.Mask != 0 { 318 out = nl.NewRtAttr(nl.XFRMA_SET_MARK_MASK, nl.Uint32Attr(state.OutputMark.Mask)) 319 req.AddData(out) 320 } 321 } 322 if state.OSeqMayWrap || state.DontEncapDSCP { 323 var flags uint32 324 if state.DontEncapDSCP { 325 flags |= nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP 326 } 327 if state.OSeqMayWrap { 328 flags |= nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP 329 } 330 out := nl.NewRtAttr(nl.XFRMA_SA_EXTRA_FLAGS, nl.Uint32Attr(flags)) 331 req.AddData(out) 332 } 333 if state.Replay != nil { 334 out := nl.NewRtAttr(nl.XFRMA_REPLAY_VAL, writeReplay(state.Replay)) 335 req.AddData(out) 336 } 337 338 if state.SADir != 0 { 339 saDir := nl.NewRtAttr(nl.XFRMA_SA_DIR, nl.Uint8Attr(uint8(state.SADir))) 340 req.AddData(saDir) 341 } 342 343 if state.Ifid != 0 { 344 ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) 345 req.AddData(ifId) 346 } 347 348 if state.Pcpunum != nil { 349 pcpuNum := nl.NewRtAttr(nl.XFRMA_SA_PCPU, nl.Uint32Attr(uint32(*state.Pcpunum))) 350 req.AddData(pcpuNum) 351 } 352 353 _, err := req.Execute(unix.NETLINK_XFRM, 0) 354 return err 355 } 356 357 func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { 358 req := h.newNetlinkRequest(nl.XFRM_MSG_ALLOCSPI, 359 unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) 360 361 msg := &nl.XfrmUserSpiInfo{} 362 msg.XfrmUsersaInfo = *(xfrmUsersaInfoFromXfrmState(state)) 363 // 1-255 is reserved by IANA for future use 364 msg.Min = 0x100 365 msg.Max = 0xffffffff 366 req.AddData(msg) 367 if state.Mark != nil { 368 out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) 369 req.AddData(out) 370 } 371 372 msgs, err := req.Execute(unix.NETLINK_XFRM, 0) 373 if err != nil { 374 return nil, err 375 } 376 377 return parseXfrmState(msgs[0], FAMILY_ALL) 378 } 379 380 // XfrmStateDel will delete an xfrm state from the system. Note that 381 // the Algos are ignored when matching the state to delete. 382 // Equivalent to: `ip xfrm state del $state` 383 func XfrmStateDel(state *XfrmState) error { 384 return pkgHandle.XfrmStateDel(state) 385 } 386 387 // XfrmStateDel will delete an xfrm state from the system. Note that 388 // the Algos are ignored when matching the state to delete. 389 // Equivalent to: `ip xfrm state del $state` 390 func (h *Handle) XfrmStateDel(state *XfrmState) error { 391 _, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA) 392 return err 393 } 394 395 // XfrmStateList gets a list of xfrm states in the system. 396 // Equivalent to: `ip [-4|-6] xfrm state show`. 397 // The list can be filtered by ip family. 398 // 399 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 400 // or incomplete. 401 func XfrmStateList(family int) ([]XfrmState, error) { 402 return pkgHandle.XfrmStateList(family) 403 } 404 405 // XfrmStateList gets a list of xfrm states in the system. 406 // Equivalent to: `ip xfrm state show`. 407 // The list can be filtered by ip family. 408 // 409 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 410 // or incomplete. 411 func (h *Handle) XfrmStateList(family int) ([]XfrmState, error) { 412 req := h.newNetlinkRequest(nl.XFRM_MSG_GETSA, unix.NLM_F_DUMP) 413 414 msgs, executeErr := req.Execute(unix.NETLINK_XFRM, nl.XFRM_MSG_NEWSA) 415 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 416 return nil, executeErr 417 } 418 419 var res []XfrmState 420 for _, m := range msgs { 421 if state, err := parseXfrmState(m, family); err == nil { 422 res = append(res, *state) 423 } else if err == familyError { 424 continue 425 } else { 426 return nil, err 427 } 428 } 429 return res, executeErr 430 } 431 432 // XfrmStateGet gets the xfrm state described by the ID, if found. 433 // Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. 434 // Only the fields which constitue the SA ID must be filled in: 435 // ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] 436 // mark is optional 437 func XfrmStateGet(state *XfrmState) (*XfrmState, error) { 438 return pkgHandle.XfrmStateGet(state) 439 } 440 441 // XfrmStateGet gets the xfrm state described by the ID, if found. 442 // Equivalent to: `ip xfrm state get ID [ mark MARK [ mask MASK ] ]`. 443 // Only the fields which constitue the SA ID must be filled in: 444 // ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ] 445 // mark is optional 446 func (h *Handle) XfrmStateGet(state *XfrmState) (*XfrmState, error) { 447 return h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_GETSA) 448 } 449 450 func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState, error) { 451 req := h.newNetlinkRequest(nlProto, unix.NLM_F_ACK) 452 453 msg := &nl.XfrmUsersaId{} 454 msg.Family = uint16(nl.GetIPFamily(state.Dst)) 455 msg.Daddr.FromIP(state.Dst) 456 msg.Proto = uint8(state.Proto) 457 msg.Spi = nl.Swap32(uint32(state.Spi)) 458 req.AddData(msg) 459 460 if state.Mark != nil { 461 out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) 462 req.AddData(out) 463 } 464 if state.Src != nil { 465 out := nl.NewRtAttr(nl.XFRMA_SRCADDR, state.Src.To16()) 466 req.AddData(out) 467 } 468 469 if state.Ifid != 0 { 470 ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) 471 req.AddData(ifId) 472 } 473 474 if state.Pcpunum != nil { 475 pcpuNum := nl.NewRtAttr(nl.XFRMA_SA_PCPU, nl.Uint32Attr(uint32(*state.Pcpunum))) 476 req.AddData(pcpuNum) 477 } 478 479 resType := nl.XFRM_MSG_NEWSA 480 if nlProto == nl.XFRM_MSG_DELSA { 481 resType = 0 482 } 483 484 msgs, err := req.Execute(unix.NETLINK_XFRM, uint16(resType)) 485 if err != nil { 486 return nil, err 487 } 488 489 if nlProto == nl.XFRM_MSG_DELSA { 490 return nil, nil 491 } 492 493 s, err := parseXfrmState(msgs[0], FAMILY_ALL) 494 if err != nil { 495 return nil, err 496 } 497 498 return s, nil 499 } 500 501 var familyError = fmt.Errorf("family error") 502 503 func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { 504 var state XfrmState 505 state.Dst = msg.Id.Daddr.ToIP() 506 state.Src = msg.Saddr.ToIP() 507 state.Proto = Proto(msg.Id.Proto) 508 state.Mode = Mode(msg.Mode) 509 state.Spi = int(nl.Swap32(msg.Id.Spi)) 510 state.Reqid = int(msg.Reqid) 511 state.ReplayWindow = int(msg.ReplayWindow) 512 lftToLimits(&msg.Lft, &state.Limits) 513 curToStats(&msg.Curlft, &msg.Stats, &state.Statistics) 514 state.Selector = &XfrmPolicy{ 515 Dst: msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, msg.Sel.Family), 516 Src: msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, msg.Sel.Family), 517 Proto: Proto(msg.Sel.Proto), 518 DstPort: int(nl.Swap16(msg.Sel.Dport)), 519 SrcPort: int(nl.Swap16(msg.Sel.Sport)), 520 Ifindex: int(msg.Sel.Ifindex), 521 } 522 523 return &state 524 } 525 526 func parseXfrmState(m []byte, family int) (*XfrmState, error) { 527 msg := nl.DeserializeXfrmUsersaInfo(m) 528 // This is mainly for the state dump 529 if family != FAMILY_ALL && family != int(msg.Family) { 530 return nil, familyError 531 } 532 state := xfrmStateFromXfrmUsersaInfo(msg) 533 attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) 534 if err != nil { 535 return nil, err 536 } 537 538 for _, attr := range attrs { 539 switch attr.Attr.Type { 540 case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT: 541 var resAlgo *XfrmStateAlgo 542 if attr.Attr.Type == nl.XFRMA_ALG_AUTH { 543 if state.Auth == nil { 544 state.Auth = new(XfrmStateAlgo) 545 } 546 resAlgo = state.Auth 547 } else { 548 state.Crypt = new(XfrmStateAlgo) 549 resAlgo = state.Crypt 550 } 551 algo := nl.DeserializeXfrmAlgo(attr.Value[:]) 552 (*resAlgo).Name = nl.BytesToString(algo.AlgName[:]) 553 (*resAlgo).Key = algo.AlgKey 554 case nl.XFRMA_ALG_AUTH_TRUNC: 555 if state.Auth == nil { 556 state.Auth = new(XfrmStateAlgo) 557 } 558 algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:]) 559 state.Auth.Name = nl.BytesToString(algo.AlgName[:]) 560 state.Auth.Key = algo.AlgKey 561 state.Auth.TruncateLen = int(algo.AlgTruncLen) 562 case nl.XFRMA_ALG_AEAD: 563 state.Aead = new(XfrmStateAlgo) 564 algo := nl.DeserializeXfrmAlgoAEAD(attr.Value[:]) 565 state.Aead.Name = nl.BytesToString(algo.AlgName[:]) 566 state.Aead.Key = algo.AlgKey 567 state.Aead.ICVLen = int(algo.AlgICVLen) 568 case nl.XFRMA_ENCAP: 569 encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:]) 570 state.Encap = new(XfrmStateEncap) 571 state.Encap.Type = EncapType(encap.EncapType) 572 state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport)) 573 state.Encap.DstPort = int(nl.Swap16(encap.EncapDport)) 574 state.Encap.OriginalAddress = encap.EncapOa.ToIP() 575 case nl.XFRMA_MARK: 576 mark := nl.DeserializeXfrmMark(attr.Value[:]) 577 state.Mark = new(XfrmMark) 578 state.Mark.Value = mark.Value 579 state.Mark.Mask = mark.Mask 580 case nl.XFRMA_SA_EXTRA_FLAGS: 581 flags := native.Uint32(attr.Value) 582 if (flags & nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP) != 0 { 583 state.DontEncapDSCP = true 584 } 585 if (flags & nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP) != 0 { 586 state.OSeqMayWrap = true 587 } 588 case nl.XFRMA_SET_MARK: 589 if state.OutputMark == nil { 590 state.OutputMark = new(XfrmMark) 591 } 592 state.OutputMark.Value = native.Uint32(attr.Value) 593 case nl.XFRMA_SET_MARK_MASK: 594 if state.OutputMark == nil { 595 state.OutputMark = new(XfrmMark) 596 } 597 state.OutputMark.Mask = native.Uint32(attr.Value) 598 if state.OutputMark.Mask == 0xffffffff { 599 state.OutputMark.Mask = 0 600 } 601 case nl.XFRMA_SA_DIR: 602 state.SADir = SADir(attr.Value[0]) 603 case nl.XFRMA_IF_ID: 604 state.Ifid = int(native.Uint32(attr.Value)) 605 case nl.XFRMA_SA_PCPU: 606 pcpuNum := native.Uint32(attr.Value) 607 state.Pcpunum = &pcpuNum 608 case nl.XFRMA_REPLAY_VAL: 609 if state.Replay == nil { 610 state.Replay = new(XfrmReplayState) 611 } 612 replay := nl.DeserializeXfrmReplayState(attr.Value[:]) 613 state.Replay.OSeq = replay.OSeq 614 state.Replay.Seq = replay.Seq 615 state.Replay.BitMap = replay.BitMap 616 } 617 } 618 619 return state, nil 620 } 621 622 // XfrmStateFlush will flush the xfrm state on the system. 623 // proto = 0 means any transformation protocols 624 // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` 625 func XfrmStateFlush(proto Proto) error { 626 return pkgHandle.XfrmStateFlush(proto) 627 } 628 629 // XfrmStateFlush will flush the xfrm state on the system. 630 // proto = 0 means any transformation protocols 631 // Equivalent to: `ip xfrm state flush [ proto XFRM-PROTO ]` 632 func (h *Handle) XfrmStateFlush(proto Proto) error { 633 req := h.newNetlinkRequest(nl.XFRM_MSG_FLUSHSA, unix.NLM_F_ACK) 634 635 req.AddData(&nl.XfrmUsersaFlush{Proto: uint8(proto)}) 636 637 _, err := req.Execute(unix.NETLINK_XFRM, 0) 638 return err 639 } 640 641 func limitsToLft(lmts XfrmStateLimits, lft *nl.XfrmLifetimeCfg) { 642 if lmts.ByteSoft != 0 { 643 lft.SoftByteLimit = lmts.ByteSoft 644 } else { 645 lft.SoftByteLimit = nl.XFRM_INF 646 } 647 if lmts.ByteHard != 0 { 648 lft.HardByteLimit = lmts.ByteHard 649 } else { 650 lft.HardByteLimit = nl.XFRM_INF 651 } 652 if lmts.PacketSoft != 0 { 653 lft.SoftPacketLimit = lmts.PacketSoft 654 } else { 655 lft.SoftPacketLimit = nl.XFRM_INF 656 } 657 if lmts.PacketHard != 0 { 658 lft.HardPacketLimit = lmts.PacketHard 659 } else { 660 lft.HardPacketLimit = nl.XFRM_INF 661 } 662 lft.SoftAddExpiresSeconds = lmts.TimeSoft 663 lft.HardAddExpiresSeconds = lmts.TimeHard 664 lft.SoftUseExpiresSeconds = lmts.TimeUseSoft 665 lft.HardUseExpiresSeconds = lmts.TimeUseHard 666 } 667 668 func lftToLimits(lft *nl.XfrmLifetimeCfg, lmts *XfrmStateLimits) { 669 *lmts = *(*XfrmStateLimits)(unsafe.Pointer(lft)) 670 } 671 672 func curToStats(cur *nl.XfrmLifetimeCur, wstats *nl.XfrmStats, stats *XfrmStateStats) { 673 stats.Bytes = cur.Bytes 674 stats.Packets = cur.Packets 675 stats.AddTime = cur.AddTime 676 stats.UseTime = cur.UseTime 677 stats.ReplayWindow = wstats.ReplayWindow 678 stats.Replay = wstats.Replay 679 stats.Failed = wstats.IntegrityFailed 680 } 681 682 func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { 683 msg := &nl.XfrmUsersaInfo{} 684 msg.Family = uint16(nl.GetIPFamily(state.Dst)) 685 msg.Id.Daddr.FromIP(state.Dst) 686 msg.Saddr.FromIP(state.Src) 687 msg.Id.Proto = uint8(state.Proto) 688 msg.Mode = uint8(state.Mode) 689 msg.Id.Spi = nl.Swap32(uint32(state.Spi)) 690 msg.Reqid = uint32(state.Reqid) 691 msg.ReplayWindow = uint8(state.ReplayWindow) 692 msg.Sel = nl.XfrmSelector{} 693 if state.Selector != nil { 694 selFromPolicy(&msg.Sel, state.Selector) 695 } 696 return msg 697 }