...
Run Format

Source file src/net/interface.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package net
     6	
     7	import (
     8		"errors"
     9		"sync"
    10		"time"
    11	)
    12	
    13	var (
    14		errInvalidInterface         = errors.New("invalid network interface")
    15		errInvalidInterfaceIndex    = errors.New("invalid network interface index")
    16		errInvalidInterfaceName     = errors.New("invalid network interface name")
    17		errNoSuchInterface          = errors.New("no such network interface")
    18		errNoSuchMulticastInterface = errors.New("no such multicast network interface")
    19	)
    20	
    21	// Interface represents a mapping between network interface name
    22	// and index. It also represents network interface facility
    23	// information.
    24	type Interface struct {
    25		Index        int          // positive integer that starts at one, zero is never used
    26		MTU          int          // maximum transmission unit
    27		Name         string       // e.g., "en0", "lo0", "eth0.100"
    28		HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form
    29		Flags        Flags        // e.g., FlagUp, FlagLoopback, FlagMulticast
    30	}
    31	
    32	type Flags uint
    33	
    34	const (
    35		FlagUp           Flags = 1 << iota // interface is up
    36		FlagBroadcast                      // interface supports broadcast access capability
    37		FlagLoopback                       // interface is a loopback interface
    38		FlagPointToPoint                   // interface belongs to a point-to-point link
    39		FlagMulticast                      // interface supports multicast access capability
    40	)
    41	
    42	var flagNames = []string{
    43		"up",
    44		"broadcast",
    45		"loopback",
    46		"pointtopoint",
    47		"multicast",
    48	}
    49	
    50	func (f Flags) String() string {
    51		s := ""
    52		for i, name := range flagNames {
    53			if f&(1<<uint(i)) != 0 {
    54				if s != "" {
    55					s += "|"
    56				}
    57				s += name
    58			}
    59		}
    60		if s == "" {
    61			s = "0"
    62		}
    63		return s
    64	}
    65	
    66	// Addrs returns interface addresses for a specific interface.
    67	func (ifi *Interface) Addrs() ([]Addr, error) {
    68		if ifi == nil {
    69			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
    70		}
    71		ifat, err := interfaceAddrTable(ifi)
    72		if err != nil {
    73			err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
    74		}
    75		return ifat, err
    76	}
    77	
    78	// MulticastAddrs returns multicast, joined group addresses for
    79	// a specific interface.
    80	func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
    81		if ifi == nil {
    82			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
    83		}
    84		ifat, err := interfaceMulticastAddrTable(ifi)
    85		if err != nil {
    86			err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
    87		}
    88		return ifat, err
    89	}
    90	
    91	// Interfaces returns a list of the system's network interfaces.
    92	func Interfaces() ([]Interface, error) {
    93		ift, err := interfaceTable(0)
    94		if err != nil {
    95			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
    96		}
    97		if len(ift) != 0 {
    98			zoneCache.update(ift)
    99		}
   100		return ift, nil
   101	}
   102	
   103	// InterfaceAddrs returns a list of the system's network interface
   104	// addresses.
   105	func InterfaceAddrs() ([]Addr, error) {
   106		ifat, err := interfaceAddrTable(nil)
   107		if err != nil {
   108			err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
   109		}
   110		return ifat, err
   111	}
   112	
   113	// InterfaceByIndex returns the interface specified by index.
   114	func InterfaceByIndex(index int) (*Interface, error) {
   115		if index <= 0 {
   116			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
   117		}
   118		ift, err := interfaceTable(index)
   119		if err != nil {
   120			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
   121		}
   122		ifi, err := interfaceByIndex(ift, index)
   123		if err != nil {
   124			err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
   125		}
   126		return ifi, err
   127	}
   128	
   129	func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
   130		for _, ifi := range ift {
   131			if index == ifi.Index {
   132				return &ifi, nil
   133			}
   134		}
   135		return nil, errNoSuchInterface
   136	}
   137	
   138	// InterfaceByName returns the interface specified by name.
   139	func InterfaceByName(name string) (*Interface, error) {
   140		if name == "" {
   141			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
   142		}
   143		ift, err := interfaceTable(0)
   144		if err != nil {
   145			return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
   146		}
   147		if len(ift) != 0 {
   148			zoneCache.update(ift)
   149		}
   150		for _, ifi := range ift {
   151			if name == ifi.Name {
   152				return &ifi, nil
   153			}
   154		}
   155		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
   156	}
   157	
   158	// An ipv6ZoneCache represents a cache holding partial network
   159	// interface information. It is used for reducing the cost of IPv6
   160	// addressing scope zone resolution.
   161	type ipv6ZoneCache struct {
   162		sync.RWMutex                // guard the following
   163		lastFetched  time.Time      // last time routing information was fetched
   164		toIndex      map[string]int // interface name to its index
   165		toName       map[int]string // interface index to its name
   166	}
   167	
   168	var zoneCache = ipv6ZoneCache{
   169		toIndex: make(map[string]int),
   170		toName:  make(map[int]string),
   171	}
   172	
   173	func (zc *ipv6ZoneCache) update(ift []Interface) {
   174		zc.Lock()
   175		defer zc.Unlock()
   176		now := time.Now()
   177		if zc.lastFetched.After(now.Add(-60 * time.Second)) {
   178			return
   179		}
   180		zc.lastFetched = now
   181		if len(ift) == 0 {
   182			var err error
   183			if ift, err = interfaceTable(0); err != nil {
   184				return
   185			}
   186		}
   187		zc.toIndex = make(map[string]int, len(ift))
   188		zc.toName = make(map[int]string, len(ift))
   189		for _, ifi := range ift {
   190			zc.toIndex[ifi.Name] = ifi.Index
   191			zc.toName[ifi.Index] = ifi.Name
   192		}
   193	}
   194	
   195	func zoneToString(zone int) string {
   196		if zone == 0 {
   197			return ""
   198		}
   199		zoneCache.update(nil)
   200		zoneCache.RLock()
   201		defer zoneCache.RUnlock()
   202		name, ok := zoneCache.toName[zone]
   203		if !ok {
   204			name = uitoa(uint(zone))
   205		}
   206		return name
   207	}
   208	
   209	func zoneToInt(zone string) int {
   210		if zone == "" {
   211			return 0
   212		}
   213		zoneCache.update(nil)
   214		zoneCache.RLock()
   215		defer zoneCache.RUnlock()
   216		index, ok := zoneCache.toIndex[zone]
   217		if !ok {
   218			index, _, _ = dtoi(zone, 0)
   219		}
   220		return index
   221	}
   222	

View as plain text