package net
import (
)
var (
errInvalidInterface = errors.New("invalid network interface")
errInvalidInterfaceIndex = errors.New("invalid network interface index")
errInvalidInterfaceName = errors.New("invalid network interface name")
errNoSuchInterface = errors.New("no such network interface")
errNoSuchMulticastInterface = errors.New("no such multicast network interface")
)
type Interface struct {
Index int
MTU int
Name string
HardwareAddr HardwareAddr
Flags Flags
}
type Flags uint
const (
FlagUp Flags = 1 << iota
FlagBroadcast
FlagLoopback
FlagPointToPoint
FlagMulticast
)
var flagNames = []string{
"up",
"broadcast",
"loopback",
"pointtopoint",
"multicast",
}
func ( Flags) () string {
:= ""
for , := range flagNames {
if &(1<<uint()) != 0 {
if != "" {
+= "|"
}
+=
}
}
if == "" {
= "0"
}
return
}
func ( *Interface) () ([]Addr, error) {
if == nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
}
, := interfaceAddrTable()
if != nil {
= &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
return ,
}
func ( *Interface) () ([]Addr, error) {
if == nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
}
, := interfaceMulticastAddrTable()
if != nil {
= &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
return ,
}
func () ([]Interface, error) {
, := interfaceTable(0)
if != nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
if len() != 0 {
zoneCache.update(, false)
}
return , nil
}
func () ([]Addr, error) {
, := interfaceAddrTable(nil)
if != nil {
= &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
return ,
}
func ( int) (*Interface, error) {
if <= 0 {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
}
, := interfaceTable()
if != nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
, := interfaceByIndex(, )
if != nil {
= &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
return ,
}
func ( []Interface, int) (*Interface, error) {
for , := range {
if == .Index {
return &, nil
}
}
return nil, errNoSuchInterface
}
func ( string) (*Interface, error) {
if == "" {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
}
, := interfaceTable(0)
if != nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: }
}
if len() != 0 {
zoneCache.update(, false)
}
for , := range {
if == .Name {
return &, nil
}
}
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
}
type ipv6ZoneCache struct {
sync.RWMutex
lastFetched time.Time
toIndex map[string]int
toName map[int]string
}
var zoneCache = ipv6ZoneCache{
toIndex: make(map[string]int),
toName: make(map[int]string),
}
func ( *ipv6ZoneCache) ( []Interface, bool) ( bool) {
.Lock()
defer .Unlock()
:= time.Now()
if ! && .lastFetched.After(.Add(-60*time.Second)) {
return false
}
.lastFetched =
if len() == 0 {
var error
if , = interfaceTable(0); != nil {
return false
}
}
.toIndex = make(map[string]int, len())
.toName = make(map[int]string, len())
for , := range {
.toIndex[.Name] = .Index
if , := .toName[.Index]; ! {
.toName[.Index] = .Name
}
}
return true
}
func ( *ipv6ZoneCache) ( int) string {
if == 0 {
return ""
}
:= zoneCache.update(nil, false)
zoneCache.RLock()
, := zoneCache.toName[]
zoneCache.RUnlock()
if ! && ! {
zoneCache.update(nil, true)
zoneCache.RLock()
, = zoneCache.toName[]
zoneCache.RUnlock()
}
if ! {
= uitoa(uint())
}
return
}
func ( *ipv6ZoneCache) ( string) int {
if == "" {
return 0
}
:= zoneCache.update(nil, false)
zoneCache.RLock()
, := zoneCache.toIndex[]
zoneCache.RUnlock()
if ! && ! {
zoneCache.update(nil, true)
zoneCache.RLock()
, = zoneCache.toIndex[]
zoneCache.RUnlock()
}
if ! {
, _, _ = dtoi()
}
return
}