mirror of
https://github.com/vishvananda/netlink
synced 2025-05-16 23:19:24 +00:00
AddrSubscribe(): receive updates for changes in link addresses.
This commit is contained in:
parent
5a5eb317d7
commit
afa33d45e9
@ -2,6 +2,7 @@ package netlink
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -140,3 +141,81 @@ func AddrList(link Link, family int) ([]Addr, error) {
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddrUpdate struct {
|
||||||
|
LinkAddress net.IPNet
|
||||||
|
LinkIndex int
|
||||||
|
NewAddr bool // true=added false=deleted
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddrSubscribe takes a chan down which notifications will be sent
|
||||||
|
// when addresses change. Close the 'done' chan to stop subscription.
|
||||||
|
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
|
||||||
|
s, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR)
|
||||||
|
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 {
|
||||||
|
log.Printf("netlink.AddrSubscribe: Receive() error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, m := range msgs {
|
||||||
|
msgType := m.Header.Type
|
||||||
|
if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR {
|
||||||
|
log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := nl.DeserializeIfAddrmsg(m.Data)
|
||||||
|
|
||||||
|
attrs, err := nl.ParseRouteAttr(m.Data[msg.Len():])
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("netlink.AddrSubscribe: nl.ParseRouteAttr() error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var local, dst *net.IPNet
|
||||||
|
var addr Addr
|
||||||
|
for _, attr := range attrs {
|
||||||
|
switch attr.Attr.Type {
|
||||||
|
case syscall.IFA_ADDRESS:
|
||||||
|
dst = &net.IPNet{
|
||||||
|
IP: attr.Value,
|
||||||
|
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
||||||
|
}
|
||||||
|
case syscall.IFA_LOCAL:
|
||||||
|
local = &net.IPNet{
|
||||||
|
IP: attr.Value,
|
||||||
|
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
||||||
|
}
|
||||||
|
case syscall.IFA_LABEL:
|
||||||
|
addr.Label = string(attr.Value[:len(attr.Value)-1])
|
||||||
|
case IFA_FLAGS:
|
||||||
|
addr.Flags = int(native.Uint32(attr.Value[0:4]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
|
||||||
|
if local != nil {
|
||||||
|
addr.IPNet = local
|
||||||
|
} else {
|
||||||
|
addr.IPNet = dst
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: int(msg.Index), NewAddr: msgType == syscall.RTM_NEWADDR}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
4
route.go
4
route.go
@ -59,8 +59,8 @@ type flagString struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var testFlags = []flagString{
|
var testFlags = []flagString{
|
||||||
flagString{f: FLAG_ONLINK, s: "onlink"},
|
{f: FLAG_ONLINK, s: "onlink"},
|
||||||
flagString{f: FLAG_PERVASIVE, s: "pervasive"},
|
{f: FLAG_PERVASIVE, s: "pervasive"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) ListFlags() []string {
|
func (r *Route) ListFlags() []string {
|
||||||
|
Loading…
Reference in New Issue
Block a user