Source file
src/net/interface.go
Documentation: net
1
2
3
4
5 package net
6
7 import (
8 "errors"
9 "internal/itoa"
10 "sync"
11 "time"
12 )
13
14
15
16
17
18
19
20 var (
21 errInvalidInterface = errors.New("invalid network interface")
22 errInvalidInterfaceIndex = errors.New("invalid network interface index")
23 errInvalidInterfaceName = errors.New("invalid network interface name")
24 errNoSuchInterface = errors.New("no such network interface")
25 errNoSuchMulticastInterface = errors.New("no such multicast network interface")
26 )
27
28
29
30
31 type Interface struct {
32 Index int
33 MTU int
34 Name string
35 HardwareAddr HardwareAddr
36 Flags Flags
37 }
38
39 type Flags uint
40
41 const (
42 FlagUp Flags = 1 << iota
43 FlagBroadcast
44 FlagLoopback
45 FlagPointToPoint
46 FlagMulticast
47 FlagRunning
48 )
49
50 var flagNames = []string{
51 "up",
52 "broadcast",
53 "loopback",
54 "pointtopoint",
55 "multicast",
56 "running",
57 }
58
59 func (f Flags) String() string {
60 s := ""
61 for i, name := range flagNames {
62 if f&(1<<uint(i)) != 0 {
63 if s != "" {
64 s += "|"
65 }
66 s += name
67 }
68 }
69 if s == "" {
70 s = "0"
71 }
72 return s
73 }
74
75
76
77 func (ifi *Interface) Addrs() ([]Addr, error) {
78 if ifi == nil {
79 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
80 }
81 ifat, err := interfaceAddrTable(ifi)
82 if err != nil {
83 err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
84 }
85 return ifat, err
86 }
87
88
89
90 func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
91 if ifi == nil {
92 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
93 }
94 ifat, err := interfaceMulticastAddrTable(ifi)
95 if err != nil {
96 err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
97 }
98 return ifat, err
99 }
100
101
102 func Interfaces() ([]Interface, error) {
103 ift, err := interfaceTable(0)
104 if err != nil {
105 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
106 }
107 if len(ift) != 0 {
108 zoneCache.update(ift, false)
109 }
110 return ift, nil
111 }
112
113
114
115
116
117
118 func InterfaceAddrs() ([]Addr, error) {
119 ifat, err := interfaceAddrTable(nil)
120 if err != nil {
121 err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
122 }
123 return ifat, err
124 }
125
126
127
128
129
130
131 func InterfaceByIndex(index int) (*Interface, error) {
132 if index <= 0 {
133 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
134 }
135 ift, err := interfaceTable(index)
136 if err != nil {
137 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
138 }
139 ifi, err := interfaceByIndex(ift, index)
140 if err != nil {
141 err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
142 }
143 return ifi, err
144 }
145
146 func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
147 for _, ifi := range ift {
148 if index == ifi.Index {
149 return &ifi, nil
150 }
151 }
152 return nil, errNoSuchInterface
153 }
154
155
156 func InterfaceByName(name string) (*Interface, error) {
157 if name == "" {
158 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
159 }
160 ift, err := interfaceTable(0)
161 if err != nil {
162 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
163 }
164 if len(ift) != 0 {
165 zoneCache.update(ift, false)
166 }
167 for _, ifi := range ift {
168 if name == ifi.Name {
169 return &ifi, nil
170 }
171 }
172 return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
173 }
174
175
176
177
178
179
180
181 type ipv6ZoneCache struct {
182 sync.RWMutex
183 lastFetched time.Time
184 toIndex map[string]int
185 toName map[int]string
186 }
187
188 var zoneCache = ipv6ZoneCache{
189 toIndex: make(map[string]int),
190 toName: make(map[int]string),
191 }
192
193
194
195
196 func (zc *ipv6ZoneCache) update(ift []Interface, force bool) (updated bool) {
197 zc.Lock()
198 defer zc.Unlock()
199 now := time.Now()
200 if !force && zc.lastFetched.After(now.Add(-60*time.Second)) {
201 return false
202 }
203 zc.lastFetched = now
204 if len(ift) == 0 {
205 var err error
206 if ift, err = interfaceTable(0); err != nil {
207 return false
208 }
209 }
210 zc.toIndex = make(map[string]int, len(ift))
211 zc.toName = make(map[int]string, len(ift))
212 for _, ifi := range ift {
213 zc.toIndex[ifi.Name] = ifi.Index
214 if _, ok := zc.toName[ifi.Index]; !ok {
215 zc.toName[ifi.Index] = ifi.Name
216 }
217 }
218 return true
219 }
220
221 func (zc *ipv6ZoneCache) name(index int) string {
222 if index == 0 {
223 return ""
224 }
225 updated := zoneCache.update(nil, false)
226 zoneCache.RLock()
227 name, ok := zoneCache.toName[index]
228 zoneCache.RUnlock()
229 if !ok && !updated {
230 zoneCache.update(nil, true)
231 zoneCache.RLock()
232 name, ok = zoneCache.toName[index]
233 zoneCache.RUnlock()
234 }
235 if !ok {
236 name = itoa.Uitoa(uint(index))
237 }
238 return name
239 }
240
241 func (zc *ipv6ZoneCache) index(name string) int {
242 if name == "" {
243 return 0
244 }
245 updated := zoneCache.update(nil, false)
246 zoneCache.RLock()
247 index, ok := zoneCache.toIndex[name]
248 zoneCache.RUnlock()
249 if !ok && !updated {
250 zoneCache.update(nil, true)
251 zoneCache.RLock()
252 index, ok = zoneCache.toIndex[name]
253 zoneCache.RUnlock()
254 }
255 if !ok {
256 index, _, _ = dtoi(name)
257 }
258 return index
259 }
260
View as plain text