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
14 type XfrmStateAlgo struct {
15 Name string
16 Key []byte
17 TruncateLen int
18 ICVLen int
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
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
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
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
76
77
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
89
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
102
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
215
216 bytesPerElem := int(unsafe.Sizeof(replayEsn.BmpLen))
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
231
232 func XfrmStateAdd(state *XfrmState) error {
233 return pkgHandle.XfrmStateAdd(state)
234 }
235
236
237
238 func (h *Handle) XfrmStateAdd(state *XfrmState) error {
239 return h.xfrmStateAddOrUpdate(state, nl.XFRM_MSG_NEWSA)
240 }
241
242
243
244 func XfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) {
245 return pkgHandle.xfrmStateAllocSpi(state)
246 }
247
248
249
250 func XfrmStateUpdate(state *XfrmState) error {
251 return pkgHandle.XfrmStateUpdate(state)
252 }
253
254
255
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
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
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
368
369
370 func XfrmStateDel(state *XfrmState) error {
371 return pkgHandle.XfrmStateDel(state)
372 }
373
374
375
376
377 func (h *Handle) XfrmStateDel(state *XfrmState) error {
378 _, err := h.xfrmStateGetOrDelete(state, nl.XFRM_MSG_DELSA)
379 return err
380 }
381
382
383
384
385 func XfrmStateList(family int) ([]XfrmState, error) {
386 return pkgHandle.XfrmStateList(family)
387 }
388
389
390
391
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
414
415
416
417
418 func XfrmStateGet(state *XfrmState) (*XfrmState, error) {
419 return pkgHandle.XfrmStateGet(state)
420 }
421
422
423
424
425
426
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
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
594
595
596 func XfrmStateFlush(proto Proto) error {
597 return pkgHandle.XfrmStateFlush(proto)
598 }
599
600
601
602
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 }
669
View as plain text