xfrm_monitor_linux.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package netlink
  2. import (
  3. "fmt"
  4. "github.com/vishvananda/netlink/nl"
  5. "github.com/vishvananda/netns"
  6. "golang.org/x/sys/unix"
  7. )
  8. type XfrmMsg interface {
  9. Type() nl.XfrmMsgType
  10. }
  11. type XfrmMsgExpire struct {
  12. XfrmState *XfrmState
  13. Hard bool
  14. }
  15. func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType {
  16. return nl.XFRM_MSG_EXPIRE
  17. }
  18. func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire {
  19. var e XfrmMsgExpire
  20. msg := nl.DeserializeXfrmUserExpire(b)
  21. e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo)
  22. e.Hard = msg.Hard == 1
  23. return &e
  24. }
  25. func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error,
  26. types ...nl.XfrmMsgType) error {
  27. groups, err := xfrmMcastGroups(types)
  28. if err != nil {
  29. return nil
  30. }
  31. s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...)
  32. if err != nil {
  33. return err
  34. }
  35. if done != nil {
  36. go func() {
  37. <-done
  38. s.Close()
  39. }()
  40. }
  41. go func() {
  42. defer close(ch)
  43. for {
  44. msgs, from, err := s.Receive()
  45. if err != nil {
  46. errorChan <- err
  47. return
  48. }
  49. if from.Pid != nl.PidKernel {
  50. errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
  51. return
  52. }
  53. for _, m := range msgs {
  54. switch m.Header.Type {
  55. case nl.XFRM_MSG_EXPIRE:
  56. ch <- parseXfrmMsgExpire(m.Data)
  57. default:
  58. errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type)
  59. }
  60. }
  61. }
  62. }()
  63. return nil
  64. }
  65. func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) {
  66. groups := make([]uint, 0)
  67. if len(types) == 0 {
  68. return nil, fmt.Errorf("no xfrm msg type specified")
  69. }
  70. for _, t := range types {
  71. var group uint
  72. switch t {
  73. case nl.XFRM_MSG_EXPIRE:
  74. group = nl.XFRMNLGRP_EXPIRE
  75. default:
  76. return nil, fmt.Errorf("unsupported group: %x", t)
  77. }
  78. groups = append(groups, group)
  79. }
  80. return groups, nil
  81. }