50 lines
1.0 KiB
Go
50 lines
1.0 KiB
Go
package gokrazy
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
type netlinkListener struct {
|
|
fd int
|
|
buf []byte
|
|
}
|
|
|
|
func listenNetlink() (*netlinkListener, error) {
|
|
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_ROUTE)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE): %v", err)
|
|
}
|
|
|
|
saddr := &syscall.SockaddrNetlink{
|
|
Family: syscall.AF_NETLINK,
|
|
Groups: (1 << (syscall.RTNLGRP_IPV4_IFADDR - 1)) |
|
|
(1 << (syscall.RTNLGRP_IPV6_IFADDR - 1)),
|
|
}
|
|
|
|
if err := syscall.Bind(fd, saddr); err != nil {
|
|
return nil, fmt.Errorf("bind: %v", err)
|
|
}
|
|
|
|
return &netlinkListener{
|
|
fd: fd,
|
|
// use the page size as buffer size, like libnl
|
|
buf: make([]byte, os.Getpagesize()),
|
|
}, nil
|
|
}
|
|
|
|
func (l *netlinkListener) ReadMsgs() ([]syscall.NetlinkMessage, error) {
|
|
n, err := syscall.Read(l.fd, l.buf)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Read: %v", err)
|
|
}
|
|
|
|
msgs, err := syscall.ParseNetlinkMessage(l.buf[:n])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ParseNetlinkMessage: %v", err)
|
|
}
|
|
|
|
return msgs, nil
|
|
}
|