net.Interfaceaddrs () gets the fake MAC address after the network adapter is bound
package main
import (
"encoding/hex"
"fmt"
"net"
"strings"
"syscall"
"unsafe"
)
func main() {
getPermanentMacAddr()
}
// If we use bond or team technology
// to use two or more adapters as a virtual one
// use net.Interface.HardwareAddr will get the same mac address
// The following code thinking was borrowed from ethtool's source code ethtool.c
// this code will get the permanent mac address
func getPermanentMacAddr() error {
var err error
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
if err != nil {
fd, err = syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_GENERIC)
if err != nil {
return err
}
}
defer func() {
_ = syscall.Close(fd)
}()
var adapters []net.Interface
adapters, _ = net.Interfaces()
for _, adapter := range adapters {
var data struct {
cmd uint32
size uint32
data [128]byte
}
data.cmd = 0x20
data.size = 128
// data.data = make([]byte, 128)
var ifr struct {
IfrName [16]byte
IfrData unsafe.Pointer
}
copy(ifr.IfrName[:], adapter.Name)
ifr.IfrData = unsafe.Pointer(&data)
_, _, sysErr := syscall.RawSyscall(syscall.SYS_IOCTL,
uintptr(fd), uintptr(0x8946), uintptr(unsafe.Pointer(&ifr)))
if sysErr != 0 {
fmt.Println("调用ioctl获取网口", adapter.Name, "物理MAC地址错误")
// return errors.New("call ioctl get permanent mac address error")
continue
}
// If mac address is all zero, this is a virtual adapter
// we ignore it
bAllZERO := true
var i uint32 = 0
for i = 0; i < data.size; i++ {
if data.data[i] != 0x00 {
bAllZERO = false
break
}
}
if bAllZERO {
continue
}
if len(hex.EncodeToString(data.data[0:data.size])) > 12 {
continue
}
mac := strings.ToUpper(hex.EncodeToString(data.data[0:data.size]))
for i := 10; i > 0; i = i - 2 {
mac = fmt.Sprintf("%s:%s", mac[:i], mac[i:])
}
fmt.Println(mac)
}
return nil
}
What version of Go are you using (
go version)?Does this issue reproduce with the latest release?
What operating system and processor architecture are you using (
go env)?go envOutputWhat did you expect to see?
net.Interfaceaddrs () gets the real MAC address
What did you see instead?
net.Interfaceaddrs () gets the fake MAC address after the network adapter is bound
What did you do?
Code sample: