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