微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用Go语言中的RTNETLINK套接字监视IP地址更改

如何解决如何使用Go语言中的RTNETLINK套接字监视IP地址更改

我发现syscall.go文件包中了。常量变量syscall.RTNLGRP_IPV4_IFADDR=0x5。但是RTMGRP_IPV4_IFADDRrtnetlink.h源代码中定义的C语言中的模拟常量具有不同的值,如下所示:

#define RTMGRP_IPV4_IFADDR 0x10

我通过github.com 提交了问题,希望在以后的版本中可以解决

现在,您可以0x10在插入的代码中使用0x5。它将完美运行。

事实证明这根本不是bug。他们没有RTMGRP_*rtnetlink.h源中重新声明常量变量组,并且由于syscall.go冻结而也不想在功能添加此变量。但是他们建议使用source中RTNLGRP_*也声明的方法。但是,这两组常量变量在以下方面有所不同。组代表位值(即:),并声明为用于用户空间后退功能。组代表位位置而不是位值(即:),可以通过以下方式将其转换为位值rtnetlink.hRTMGRP_*``RTMGRP_IPV4_IFADDR = 0x10``RTLNGRP_*``RTNLGRP_IPV4_IFADDR=0x5``1 << (RTNLGRP_* - 1)

解决方法

我有以下代码,应使用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
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。