我有以下代码,应该使用 RTNETLINK 套接字监视网络变化。但是,当我为接口(interface)设置新 IP 地址时,“New Addr”或“Del Addr”没有显示。可能是什么问题。
package main
import (
"fmt"
"syscall"
)
func main() {
l, _ := ListenNetlink()
for {
msgs, err := l.ReadMsgs()
if err != nil {
fmt.Println("Could not read netlink: %s", err)
}
for _, m := range msgs {
if IsNewAddr(&m) {
fmt.Println("New Addr")
}
if IsDelAddr(&m) {
fmt.Println("Del Addr")
}
}
}
}
type NetlinkListener struct {
fd int
sa *syscall.SockaddrNetlink
}
func ListenNetlink() (*NetlinkListener, error) {
groups := syscall.RTNLGRP_LINK |
syscall.RTNLGRP_IPV4_IFADDR |
syscall.RTNLGRP_IPV6_IFADDR
s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM,
syscall.NETLINK_ROUTE)
if err != nil {
return nil, fmt.Errorf("socket: %s", err)
}
saddr := &syscall.SockaddrNetlink{
Family: syscall.AF_NETLINK,
Pid: uint32(0),
Groups: uint32(groups),
}
err = syscall.Bind(s, saddr)
if err != nil {
return nil, fmt.Errorf("bind: %s", err)
}
return &NetlinkListener{fd: s, sa: saddr}, nil
}
func (l *NetlinkListener) ReadMsgs() ([]syscall.NetlinkMessage, error) {
defer func() {
recover()
}()
pkt := make([]byte, 2048)
n, err := syscall.Read(l.fd, pkt)
if err != nil {
return nil, fmt.Errorf("read: %s", err)
}
msgs, err := syscall.ParseNetlinkMessage(pkt[:n])
if err != nil {
return nil, fmt.Errorf("parse: %s", err)
}
return msgs, nil
}
func IsNewAddr(msg *syscall.NetlinkMessage) bool {
if msg.Header.Type == syscall.RTM_NEWADDR {
return true
}
return false
}
func IsDelAddr(msg *syscall.NetlinkMessage) bool {
if msg.Header.Type == syscall.RTM_DELADDR {
return true
}
return false
}
func IsRelevant(msg *syscall.IfAddrmsg) bool {
if msg.Scope == syscall.RT_SCOPE_UNIVERSE ||
msg.Scope == syscall.RT_SCOPE_SITE {
return true
}
return false
}
最佳答案
我在 syscall.go
找到了包文件。常数变量 syscall.RTNLGRP_IPV4_IFADDR=0x5
.然而模拟RTMGRP_IPV4_IFADDR
rtnetlink.h
source中定义的C语言常量具有以下不同的值:
#define RTMGRP_IPV4_IFADDR 0x10
我提交了 issue通过 github.com,我希望它会在即将发布的版本中得到修复。
现在你可以使用0x10
在你的代码中安装了 0x5
.它将完美运行。
事实证明它根本不是错误。他们没有重新申报RTMGRP_*
来自 rtnetlink.h
source 的常量变量组自syscall.go
以来也不想在功能中添加此功能被卡住。但是他们建议使用 RTNLGRP_*
这也在 rtnetlink.h
source 中声明.然而,这两组常量变量在以下方面有所不同。 RTMGRP_*
group 表示位值(即:RTMGRP_IPV4_IFADDR = 0x10
)并为用户空间向后功能声明。 RTLNGRP_*
group 表示位位置而不是位值(即: RTNLGRP_IPV4_IFADDR=0x5
),可以通过以下方式将其转换为位值 1 << (RTNLGRP_* - 1)
关于go - go语言中如何使用RTNETLINK socket监控ip地址变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36347807/