12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package netlink
- import (
- "fmt"
- "github.com/vishvananda/netlink/nl"
- "github.com/vishvananda/netns"
- "golang.org/x/sys/unix"
- )
- type XfrmMsg interface {
- Type() nl.XfrmMsgType
- }
- type XfrmMsgExpire struct {
- XfrmState *XfrmState
- Hard bool
- }
- func (ue *XfrmMsgExpire) Type() nl.XfrmMsgType {
- return nl.XFRM_MSG_EXPIRE
- }
- func parseXfrmMsgExpire(b []byte) *XfrmMsgExpire {
- var e XfrmMsgExpire
- msg := nl.DeserializeXfrmUserExpire(b)
- e.XfrmState = xfrmStateFromXfrmUsersaInfo(&msg.XfrmUsersaInfo)
- e.Hard = msg.Hard == 1
- return &e
- }
- func XfrmMonitor(ch chan<- XfrmMsg, done <-chan struct{}, errorChan chan<- error,
- types ...nl.XfrmMsgType) error {
- groups, err := xfrmMcastGroups(types)
- if err != nil {
- return nil
- }
- s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_XFRM, groups...)
- if err != nil {
- return err
- }
- if done != nil {
- go func() {
- <-done
- s.Close()
- }()
- }
- go func() {
- defer close(ch)
- for {
- msgs, err := s.Receive()
- if err != nil {
- errorChan <- err
- return
- }
- for _, m := range msgs {
- switch m.Header.Type {
- case nl.XFRM_MSG_EXPIRE:
- ch <- parseXfrmMsgExpire(m.Data)
- default:
- errorChan <- fmt.Errorf("unsupported msg type: %x", m.Header.Type)
- }
- }
- }
- }()
- return nil
- }
- func xfrmMcastGroups(types []nl.XfrmMsgType) ([]uint, error) {
- groups := make([]uint, 0)
- if len(types) == 0 {
- return nil, fmt.Errorf("no xfrm msg type specified")
- }
- for _, t := range types {
- var group uint
- switch t {
- case nl.XFRM_MSG_EXPIRE:
- group = nl.XFRMNLGRP_EXPIRE
- default:
- return nil, fmt.Errorf("unsupported group: %x", t)
- }
- groups = append(groups, group)
- }
- return groups, nil
- }
|