| package netdump | 
 |  | 
 | import ( | 
 | 	"errors" | 
 | 	"fmt" | 
 | 	"net" | 
 | 	"runtime" | 
 | 	"unsafe" | 
 |  | 
 | 	"golang.org/x/sys/unix" | 
 | ) | 
 |  | 
 | // @linux//include/uapi/linux:if.h | 
 | type ifreq struct { | 
 | 	ifname [16]byte | 
 | 	data   uintptr | 
 | } | 
 |  | 
 | // @linux//include/uapi/linux:ethtool.h ethtool_perm_addr | 
 | type ethtoolPermAddr struct { | 
 | 	Cmd  uint32 | 
 | 	Size uint32 | 
 | 	// Make this an array for memory layout reasons (see | 
 | 	// comment on the kernel struct) | 
 | 	Data [32]byte | 
 | } | 
 |  | 
 | var errNoPermenentHWAddr = errors.New("no permanent hardware address available") | 
 |  | 
 | func isAllZeroes(data []byte) bool { | 
 | 	for _, b := range data { | 
 | 		if b != 0 { | 
 | 			return false | 
 | 		} | 
 | 	} | 
 | 	return true | 
 | } | 
 |  | 
 | // Get permanent hardware address on Linux kernels older than 5.6. On newer | 
 | // kernels this is available via normal netlink. Returns errNoPermanentHWAddr | 
 | // in case no such address is available. | 
 | func getPermanentHWAddrLegacy(ifName string) (net.HardwareAddr, error) { | 
 | 	fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) | 
 | 	if err != nil { | 
 | 		fd, err = unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_GENERIC) | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 	} | 
 | 	defer unix.Close(fd) | 
 | 	var data ethtoolPermAddr | 
 | 	data.Cmd = unix.ETHTOOL_GPERMADDR | 
 | 	data.Size = uint32(len(data.Data)) | 
 | 	var req ifreq | 
 | 	copy(req.ifname[:], ifName) | 
 | 	// See //metropolis/pkg/nvme:cmd_linux.go RawCommand notice on the safety | 
 | 	// of this. | 
 | 	req.data = uintptr(unsafe.Pointer(&data)) | 
 | 	for { | 
 | 		_, _, err := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), unix.SIOCETHTOOL, uintptr(unsafe.Pointer(&req))) | 
 | 		if err == unix.EINTR { | 
 | 			continue | 
 | 		} | 
 | 		if err != 0 { | 
 | 			return nil, fmt.Errorf("ioctl(SIOETHTOOL) failed: %w", err) | 
 | 		} | 
 | 		break | 
 | 	} | 
 | 	runtime.KeepAlive(req) | 
 | 	runtime.KeepAlive(data) | 
 | 	// This kernel API is rather old and can indicate the absence of a permanent | 
 | 	// hardware MAC in two ways: a size of zero (in case the driver does not | 
 | 	// implement a permanent hardware address at all) or an all-zero value in | 
 | 	// case the driver has support for returning one but hasn't populated it. | 
 | 	if data.Size == 0 || isAllZeroes(data.Data[:data.Size]) { | 
 | 		return nil, errNoPermenentHWAddr | 
 | 	} | 
 | 	return net.HardwareAddr(data.Data[:data.Size]), nil | 
 | } |