Il ne semble pas Go a une façon multiplateforme de vérifier le drapeau PROMISC (je ne peux même pas savoir à coup sûr si un tel indicateur existe pour les fenêtres.) Voici une façon de l'obtenir sur linux, que je devine que vous êtes sur:
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)
}
}
Ceci est basé de la fonction interfaceTable
dans la bibliothèque standard. Il utilise rtnetlink
pour obtenir les drapeaux de l'interface. À moins que vous ne souhaitiez lancer votre propre fonction syscall.NetlinkRIB
, ce code extrait toujours les informations de chaque périphérique réseau et filtre les informations demandées.
Un peu moins de façon magique pour obtenir le drapeau que vous voulez est d'utiliser CGO et 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)
}
}
Une note finale est que de toute façon ne peut pas toujours vous dire correctement si une interface est en fait en mode promiscuous ou pas. Voir this thread pour plus de détails. D'après ce que je lis en utilisant la route netlink devrait fonctionner correctement, mais un autre message dit que nous devrions vérifier le nombre promiscuous. S'il vous plaît laissez-moi savoir si quelqu'un sait comment faire cela, parce que je ne peux pas trouver comment. Le only stackoverflow question sur le sujet a gone unanswered.
Je pense que l'une ou l'autre de ces méthodes fonctionnera tant que vous n'utilisez pas de réseau douteux (bridge, interfaces vlan, macvtap, etc.) Le code fonctionne si vous utilisez les outils iproute2 pour activer et désactiver le Promisc sur une interface.