2016-04-01 10 views
0

RTNETLINKソケットを使用してネットワークの変更を監視する必要がある次のコードがあります。しかし、私はインターフェイス "新しいAddr"または "Del Addr"のための新しいIPアドレスを設定しているときに表示されません。可能性のある問題は何か。RTNETLINKソケットをgo言語で使用して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 
} 

答えて

0

ファイルがsyscall.goに見つかりました。定数変数syscall.RTNLGRP_IPV4_IFADDR=0x5。ただし、次のようrtnetlink.h sourceに定義されているC言語でRTMGRP_IPV4_IFADDR定数が異なる値を持つアナログ:

#define RTMGRP_IPV4_IFADDR 0x10 

私はgithub.comを通じてissueを提出し、私はそれが今後のリリースで修正されたことを願っています。

今のところ0x5というコードのinstfで0x10を使用できます。それは完全に動作します。

バグではないことが分かります。彼らはからRTMGRP_*定数変数グループを宣言しておらず、syscall.goがフリーズしているので、この機能にも追加したくありません。しかし、rtnetlink.h sourceでも宣言されているRTNLGRP_*を使用することをお勧めします。しかし、この2つの定数変数群は、以下のように異なる。 RTMGRP_*グループは、ビット値(すなわち:RTMGRP_IPV4_IFADDR = 0x10)とユーザ空間下位機能の宣言を表します。 RTLNGRP_*基は方法1 << (RTNLGRP_* - 1)

に従って、ビット値に変換することができるビット位置ではなく、ビット値(すなわち: RTNLGRP_IPV4_IFADDR=0x5)を表します
関連する問題