Golang - 获取网络接口的混杂模式状态

我使用以下 Go 代码来获取有关网络接口的一些信息。关于如何获得每个界面的混杂模式状态的任何建议?


type Iface struct {

  Name      string `json:"name"`

  Status    string `json:"status"`

  Multicast bool   `json:"multicast"`

  Broadcast bool   `json:"broadcast"`

}


func (c *InterfacesController) GetInterfaces() {

  interfaces, err := net.Interfaces()


  if err != nil {

    fmt.Println(err)

    return

  }


  var ifaceset []Iface

  var ifc Iface


  for _, i := range interfaces {

    ifc.Name = i.Name

    if strings.Contains(i.Flags.String(), "up") {

        ifc.Status = "UP"

    } else {

        ifc.Status = "DOWN"

    }

    if strings.Contains(i.Flags.String(), "multicast") {

        ifc.Multicast = true

    } else {

        ifc.Multicast = false

    }

    if strings.Contains(i.Flags.String(), "broadcast") {

        ifc.Broadcast = true

    } else {

        ifc.Broadcast = false

    }

    ifaceset = append(ifaceset, ifc)

  }

}



白衣染霜花
浏览 433回答 2
2回答

拉风的咖菲猫

Go 似乎没有跨平台的方式来检查 PROMISC 标志(我什至无法确定 Windows 是否存在这样的标志。)这是在 linux 上获取它的一种方法,我正在猜你在:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "net"&nbsp; &nbsp; "os"&nbsp; &nbsp; "syscall"&nbsp; &nbsp; "unsafe")func GetPromiscuous(i net.Interface) (bool, error) {&nbsp; &nbsp; tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return false, os.NewSyscallError("netlinkrib", err)&nbsp; &nbsp; }&nbsp; &nbsp; msgs, err := syscall.ParseNetlinkMessage(tab)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return false, os.NewSyscallError("parsenetlinkmessage", err)&nbsp; &nbsp; }loop:&nbsp; &nbsp; for _, m := range msgs {&nbsp; &nbsp; &nbsp; &nbsp; switch m.Header.Type {&nbsp; &nbsp; &nbsp; &nbsp; case syscall.NLMSG_DONE:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break loop&nbsp; &nbsp; &nbsp; &nbsp; case syscall.RTM_NEWLINK:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ifim.Index == int32(i.Index) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (ifim.Flags & syscall.IFF_PROMISC) != 0, nil&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return false, os.ErrNotExist}func main() {&nbsp; &nbsp; ints, err := net.Interfaces()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; for _, i := range ints {&nbsp; &nbsp; &nbsp; &nbsp; p, err := GetPromiscuous(i)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(i.Name, p)&nbsp; &nbsp; }}这是基于interfaceTable标准库中的函数。它用于rtnetlink获取接口的标志。除非您想推出自己的syscall.NetlinkRIB功能,否则此代码将始终为每个网络设备提取信息并过滤掉请求的设备。获得所需标志的一种不太神奇的方法是使用 cgo 和 ioctl:package main/*#include <stdlib.h>#include <stdbool.h>#include <string.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>bool is_promisc(char *name) {&nbsp; &nbsp; int s = socket(AF_INET, SOCK_STREAM, 0);&nbsp; &nbsp; struct ifreq *i = malloc(sizeof *i);&nbsp; &nbsp; strncpy((char *)&(i->ifr_name), name, IFNAMSIZ);&nbsp; &nbsp; ioctl(s, SIOCGIFFLAGS, i);&nbsp; &nbsp; bool p = (i->ifr_flags & IFF_PROMISC) != 0;&nbsp; &nbsp; free(i);&nbsp; &nbsp; return p;}*/import "C"import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "net")func GetPromiscuous(i net.Interface) (bool, error) {&nbsp; &nbsp; set, err := C.is_promisc(C.CString(i.Name))&nbsp; &nbsp; return bool(set), err}func main() {&nbsp; &nbsp; ints, err := net.Interfaces()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; for _, i := range ints {&nbsp; &nbsp; &nbsp; &nbsp; p, err := GetPromiscuous(i)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(i.Name, p)&nbsp; &nbsp; }}最后要注意的是,无论哪种方式都可能无法始终正确地告诉您接口实际上是否处于混杂模式。有关更多详细信息,请参阅此线程。从我阅读的内容来看,使用 netlink 路由应该可以正常工作,但另一篇文章说我们应该检查混杂计数。如果有人知道怎么做,请告诉我,因为我找不到怎么做。关于这个问题的唯一 stackoverflow 问题没有得到解答。我认为只要您不做任何疯狂的网络事情(网桥、vlan 接口、macvtap 等),这些方法中的任何一种都可以工作。如果您使用 iproute2 工具在接口上打开和关闭 promisc,则代码肯定有效。

慕桂英4014372

工作环境是Ubuntu,我用了ifconfig命令,查看了各个界面的详细信息,看是否包含PROMISC. 像这样的东西://// get the interfaces//interfaces, err := net.Interfaces()//// run the ifconfig command//out, err := exec.Command("/bin/sh", "-c", "ifconfig").Output()var ifc Ifacevar ifaceset []Iface//// split the output to handle each interface separately//var ifaceDetails = strings.Split(string(out), "\n\n")//// iterate interfaces//for _, i := range interfaces {&nbsp; &nbsp; ifc.Name = i.Name&nbsp; &nbsp; if strings.Contains(i.Flags.String(), "up") {&nbsp; &nbsp; ifc.Status = "UP"&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; ifc.Status = "DOWN"&nbsp; &nbsp; }&nbsp; &nbsp; if strings.Contains(i.Flags.String(), "multicast") {&nbsp; &nbsp; &nbsp; &nbsp; ifc.Multicast = true&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; ifc.Multicast = false&nbsp; &nbsp; }&nbsp; &nbsp; if strings.Contains(i.Flags.String(), "broadcast") {&nbsp; &nbsp; &nbsp; &nbsp; ifc.Broadcast = true&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; ifc.Broadcast = false&nbsp; &nbsp; }&nbsp; &nbsp; //&nbsp; &nbsp; // try to find the word PROMISC to check if it is UP&nbsp; &nbsp; //&nbsp; &nbsp; for _, ifdetails := range ifaceDetails {&nbsp; &nbsp; &nbsp; &nbsp; if strings.Contains(ifdetails, i.Name) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if strings.Contains(ifdetails, "PROMISC") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ifc.Promisc = true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ifc.Promisc = false&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; ifaceset = append(ifaceset, ifc)}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go