2024-06-14 21:26:46 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrInvalidPCIFormat = errors.New("Invalid PCI address format")
|
|
|
|
ErrInvalidUSBFormat = errors.New("Invalid USB address format")
|
2024-06-24 19:58:15 +00:00
|
|
|
ErrParseMac = errors.New("Failed to parse MAC address")
|
2024-06-14 21:26:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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 */
|
|
|
|
)
|
|
|
|
|
2024-06-25 12:44:53 +00:00
|
|
|
type IfNameType int
|
|
|
|
type IfNameList map[IfNameType]string
|
|
|
|
|
2024-06-14 21:26:46 +00:00
|
|
|
const (
|
2024-06-25 12:44:53 +00:00
|
|
|
IfNameKern IfNameType = iota
|
|
|
|
IfNameMAC
|
|
|
|
IfNameLoc
|
2024-06-14 21:26:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type iface struct {
|
2024-06-25 12:44:53 +00:00
|
|
|
pfx string
|
|
|
|
netpath string
|
|
|
|
names IfNameList
|
2024-06-14 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(ifname string) (i iface, err error) {
|
2024-06-25 12:44:53 +00:00
|
|
|
if strings.HasPrefix(ifname, "eth") {
|
|
|
|
i.pfx = "en"
|
|
|
|
} else {
|
|
|
|
// Fall back to first 2 characters
|
|
|
|
i.pfx = ifname[0:2]
|
2024-06-14 21:26:46 +00:00
|
|
|
}
|
2024-06-25 12:44:53 +00:00
|
|
|
|
|
|
|
i.names = make(IfNameList)
|
|
|
|
i.names[IfNameKern] = ifname
|
|
|
|
i.netpath = strings.Join([]string{SYSFS, "class/net", i.names[IfNameKern]}, "/")
|
2024-06-14 21:26:46 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i iface) shouldRun() (should bool, err error) {
|
2024-06-24 19:58:15 +00:00
|
|
|
ifname_assign_type := strings.Join([]string{i.netpath, "name_assign_type"}, "/")
|
2024-06-14 21:26:46 +00:00
|
|
|
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)
|
2024-06-24 19:58:15 +00:00
|
|
|
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
|
2024-06-14 21:26:46 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-25 12:44:53 +00:00
|
|
|
func (i iface) Process() (err error) {
|
|
|
|
if lerr := i.ProcLoc(); lerr != nil {
|
|
|
|
err = lerr
|
|
|
|
}
|
|
|
|
if lerr := i.ProcMAC(); lerr != nil {
|
|
|
|
err = lerr
|
2024-06-14 21:26:46 +00:00
|
|
|
}
|
2024-06-24 19:58:15 +00:00
|
|
|
|
2024-06-14 21:26:46 +00:00
|
|
|
// It can error but as long as we get a identifier along the path it's okay
|
2024-06-25 12:44:53 +00:00
|
|
|
if i.names[IfNameLoc] == "" && i.names[IfNameMAC] == "" {
|
2024-06-24 19:58:15 +00:00
|
|
|
return
|
2024-06-14 21:26:46 +00:00
|
|
|
}
|
2024-06-25 12:44:53 +00:00
|
|
|
err = nil
|
2024-06-14 21:26:46 +00:00
|
|
|
return
|
|
|
|
}
|