我有以下代码,应使用RTNETLINK套接字监视网络更改。但是,当我为接口“ New Addr”或“ Del Addr”设置新的IP地址时,不会显示。可能是什么问题。
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源代码中定义的C语言中的模拟常量具有不同的值,如下所示:
syscall.go
syscall.RTNLGRP_IPV4_IFADDR=0x5
RTMGRP_IPV4_IFADDR
rtnetlink.h
#define RTMGRP_IPV4_IFADDR 0x10
我通过github.com 提交了问题,希望在以后的版本中可以解决。
现在,您可以0x10在插入的代码中使用0x5。它将完美运行。
0x10
0x5
事实证明这根本不是bug。他们没有RTMGRP_*从rtnetlink.h源中重新声明常量变量组,并且由于syscall.go冻结而也不想在功能中添加此变量。但是他们建议使用source中RTNLGRP_*也声明的方法。但是,这两组常量变量在以下方面有所不同。组代表位值(即:),并声明为用于用户空间后退功能。组代表位位置而不是位值(即:),可以通过以下方式将其转换为位值rtnetlink.hRTMGRP_*``RTMGRP_IPV4_IFADDR = 0x10``RTLNGRP_*``RTNLGRP_IPV4_IFADDR=0x5``1 << (RTNLGRP_* - 1)
RTMGRP_*
RTNLGRP_*
RTMGRP_*``RTMGRP_IPV4_IFADDR = 0x10``RTLNGRP_*``RTNLGRP_IPV4_IFADDR=0x5``1 << (RTNLGRP_* - 1)