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