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.
13 // BUG(mikio): On JS and NaCl, methods and functions related to
14 // Interface are not implemented.
16 // BUG(mikio): On DragonFly BSD, NetBSD, OpenBSD, Plan 9 and Solaris,
17 // the MulticastAddrs method of Interface is not implemented.
20 errInvalidInterface
= errors
.New("invalid network interface")
21 errInvalidInterfaceIndex
= errors
.New("invalid network interface index")
22 errInvalidInterfaceName
= errors
.New("invalid network interface name")
23 errNoSuchInterface
= errors
.New("no such network interface")
24 errNoSuchMulticastInterface
= errors
.New("no such multicast network interface")
27 // Interface represents a mapping between network interface name
28 // and index. It also represents network interface facility
30 type Interface
struct {
31 Index
int // positive integer that starts at one, zero is never used
32 MTU
int // maximum transmission unit
33 Name
string // e.g., "en0", "lo0", "eth0.100"
34 HardwareAddr HardwareAddr
// IEEE MAC-48, EUI-48 and EUI-64 form
35 Flags Flags
// e.g., FlagUp, FlagLoopback, FlagMulticast
41 FlagUp Flags
= 1 << iota // interface is up
42 FlagBroadcast
// interface supports broadcast access capability
43 FlagLoopback
// interface is a loopback interface
44 FlagPointToPoint
// interface belongs to a point-to-point link
45 FlagMulticast
// interface supports multicast access capability
48 var flagNames
= []string{
56 func (f Flags
) String() string {
58 for i
, name
:= range flagNames
{
59 if f
&(1<<uint(i
)) != 0 {
72 // Addrs returns a list of unicast interface addresses for a specific
74 func (ifi
*Interface
) Addrs() ([]Addr
, error
) {
76 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: errInvalidInterface
}
78 ifat
, err
:= interfaceAddrTable(ifi
)
80 err
= &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
85 // MulticastAddrs returns a list of multicast, joined group addresses
86 // for a specific interface.
87 func (ifi
*Interface
) MulticastAddrs() ([]Addr
, error
) {
89 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: errInvalidInterface
}
91 ifat
, err
:= interfaceMulticastAddrTable(ifi
)
93 err
= &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
98 // Interfaces returns a list of the system's network interfaces.
99 func Interfaces() ([]Interface
, error
) {
100 ift
, err
:= interfaceTable(0)
102 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
105 zoneCache
.update(ift
)
110 // InterfaceAddrs returns a list of the system's unicast interface
113 // The returned list does not identify the associated interface; use
114 // Interfaces and Interface.Addrs for more detail.
115 func InterfaceAddrs() ([]Addr
, error
) {
116 ifat
, err
:= interfaceAddrTable(nil)
118 err
= &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
123 // InterfaceByIndex returns the interface specified by index.
125 // On Solaris, it returns one of the logical network interfaces
126 // sharing the logical data link; for more precision use
128 func InterfaceByIndex(index
int) (*Interface
, error
) {
130 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: errInvalidInterfaceIndex
}
132 ift
, err
:= interfaceTable(index
)
134 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
136 ifi
, err
:= interfaceByIndex(ift
, index
)
138 err
= &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
143 func interfaceByIndex(ift
[]Interface
, index
int) (*Interface
, error
) {
144 for _
, ifi
:= range ift
{
145 if index
== ifi
.Index
{
149 return nil, errNoSuchInterface
152 // InterfaceByName returns the interface specified by name.
153 func InterfaceByName(name
string) (*Interface
, error
) {
155 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: errInvalidInterfaceName
}
157 ift
, err
:= interfaceTable(0)
159 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: err
}
162 zoneCache
.update(ift
)
164 for _
, ifi
:= range ift
{
165 if name
== ifi
.Name
{
169 return nil, &OpError
{Op
: "route", Net
: "ip+net", Source
: nil, Addr
: nil, Err
: errNoSuchInterface
}
172 // An ipv6ZoneCache represents a cache holding partial network
173 // interface information. It is used for reducing the cost of IPv6
174 // addressing scope zone resolution.
176 // Multiple names sharing the index are managed by first-come
177 // first-served basis for consistency.
178 type ipv6ZoneCache
struct {
179 sync
.RWMutex
// guard the following
180 lastFetched time
.Time
// last time routing information was fetched
181 toIndex
map[string]int // interface name to its index
182 toName
map[int]string // interface index to its name
185 var zoneCache
= ipv6ZoneCache
{
186 toIndex
: make(map[string]int),
187 toName
: make(map[int]string),
190 func (zc
*ipv6ZoneCache
) update(ift
[]Interface
) {
194 if zc
.lastFetched
.After(now
.Add(-60 * time
.Second
)) {
200 if ift
, err
= interfaceTable(0); err
!= nil {
204 zc
.toIndex
= make(map[string]int, len(ift
))
205 zc
.toName
= make(map[int]string, len(ift
))
206 for _
, ifi
:= range ift
{
207 zc
.toIndex
[ifi
.Name
] = ifi
.Index
208 if _
, ok
:= zc
.toName
[ifi
.Index
]; !ok
{
209 zc
.toName
[ifi
.Index
] = ifi
.Name
214 func (zc
*ipv6ZoneCache
) name(index
int) string {
218 zoneCache
.update(nil)
220 defer zoneCache
.RUnlock()
221 name
, ok
:= zoneCache
.toName
[index
]
223 name
= uitoa(uint(index
))
228 func (zc
*ipv6ZoneCache
) index(name
string) int {
232 zoneCache
.update(nil)
234 defer zoneCache
.RUnlock()
235 index
, ok
:= zoneCache
.toIndex
[name
]
237 index
, _
, _
= dtoi(name
)