github.com/haraldrudell/parl@v0.4.176/pnet/ifindex.go (about) 1 /* 2 © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pnet 7 8 import ( 9 "errors" 10 "math" 11 "net" 12 "net/netip" 13 "strconv" 14 15 "github.com/haraldrudell/parl/perrors" 16 ) 17 18 // IfIndex is a dynamic reference to a network interface on Linux systems 19 type IfIndex uint32 20 21 func NewIfIndex(index uint32) (ifIndex IfIndex) { 22 return IfIndex(index) 23 } 24 25 func NewIfIndexInt(value int) (ifIndex IfIndex, err error) { 26 if value < 0 || value > math.MaxUint32 { 27 err = perrors.ErrorfPF("Value not uint32: %d", value) 28 return 29 } 30 ifIndex = IfIndex(value) 31 return 32 } 33 34 // IsValid determines if interface index value is set, ie. > 0 35 func (ifIndex IfIndex) IsValid() (isValid bool) { 36 return ifIndex > 0 37 } 38 39 // Interface gets net.Interface for ifIndex 40 // - netInterface.Name is interface name "eth0" 41 // - netInterface.Addr() returns assigned IP addresses 42 func (ifIndex IfIndex) Interface() (netInterface *net.Interface, isErrNoSuchInterface bool, err error) { 43 if netInterface, err = net.InterfaceByIndex(int(ifIndex)); err != nil { 44 isErrNoSuchInterface = errors.Is(err, ErrNoSuchInterface) 45 err = perrors.ErrorfPF("net.InterfaceByIndex %d %w", ifIndex, err) 46 } 47 return 48 } 49 50 // InterfaceAddrs gets Addresses for interface 51 // - netInterface.Name is interface name "eth0" 52 // - netInterface.Addr() returns assigned IP addresses 53 func (ifIndex IfIndex) InterfaceAddrs(useNameCache ...NameCacher) (name string, i4, i6 []netip.Prefix, err error) { 54 var doCache = NoCache 55 if len(useNameCache) > 0 { 56 doCache = useNameCache[0] 57 } 58 59 var netInterface *net.Interface 60 var isErrNoSuchInterface bool 61 if netInterface, isErrNoSuchInterface, err = ifIndex.Interface(); err != nil { 62 if isErrNoSuchInterface && doCache != NoCache { 63 name, err = networkInterfaceNameCache.CachedName(ifIndex, doCache) 64 } 65 return // error or from cache 66 } 67 68 name = netInterface.Name 69 i4, i6, err = InterfaceAddrs(netInterface) 70 return 71 } 72 73 // Interface gets net.Interface for ifIndex 74 // - InterfaceIndex is unique for promting methods 75 func (ifIndex IfIndex) InterfaceIndex() (interfaceIndex int) { 76 return int(ifIndex) 77 } 78 79 // Zone gets net.IPAddr.Zone string for ifIndex 80 // - if an interfa ce name can be ontained, that is the zone 81 // - otherwise a numeric zone is used 82 // - if ifIndex is invalid, empty string 83 func (ifIndex IfIndex) Zone() (zone string, isNumeric bool, err error) { 84 if ifIndex.IsValid() { 85 var iface *net.Interface 86 if iface, _, err = ifIndex.Interface(); err == nil { // may fail if interface already deleted 87 zone = iface.Name 88 } else { 89 zone = strconv.Itoa(int(ifIndex)) 90 isNumeric = true 91 } 92 } 93 return 94 } 95 96 // "#13" 97 func (ifIndex IfIndex) String() (s string) { 98 return "#" + strconv.Itoa(int(ifIndex)) 99 }