package main import ( "errors" "fmt" "io" "os" "strconv" "strings" ) var ( ErrInvalidPCIFormat = errors.New("Invalid PCI address format") ErrInvalidUSBFormat = errors.New("Invalid USB address format") ErrParseMac = errors.New("Failed to parse MAC address") ) var SYSFS = "/sys" // Sourced from include/uapi/linux/netdevice.h // as of v6.8 const ( NET_NAME_UNKNOWN = 0 /* unknown origin (not exposed to userspace) */ NET_NAME_ENUM = 1 /* enumerated by kernel */ NET_NAME_PREDICTABLE = 2 /* predictably named by the kernel */ NET_NAME_USER = 3 /* provided by user-space */ NET_NAME_RENAMED = 4 /* renamed by user-space */ ) type IfNameType int type IfNameList map[IfNameType]string const ( IfNameKern IfNameType = iota IfNameMAC IfNameLoc ) type iface struct { pfx string netpath string names IfNameList } func New(ifname string) (i iface, err error) { if strings.HasPrefix(ifname, "eth") { i.pfx = "en" } else { // Fall back to first 2 characters i.pfx = ifname[0:2] } i.names = make(IfNameList) i.names[IfNameKern] = ifname i.netpath = strings.Join([]string{SYSFS, "class/net", i.names[IfNameKern]}, "/") return } func (i iface) shouldRun() (should bool, err error) { ifname_assign_type := strings.Join([]string{i.netpath, "name_assign_type"}, "/") should = true var ( file *os.File contents []byte ) if file, err = os.Open(ifname_assign_type); err != nil { err = fmt.Errorf("Failed to open interface rename property: %w", err) return } defer file.Close() if contents, err = io.ReadAll(file); err != nil { err = fmt.Errorf("Failed to read interface rename property: %w", err) return } num, _ := strings.CutSuffix(string(contents), "\n") var res int if res, err = strconv.Atoi(num); err != nil { err = fmt.Errorf("Failed to interpret interface rename property as number: %w", err) return } if res != NET_NAME_ENUM { should = false return } return }