OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / route / route_test.go
1 // Copyright 2016 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 // +build darwin dragonfly freebsd netbsd openbsd
6
7 package route
8
9 import (
10         "fmt"
11         "os/exec"
12         "runtime"
13         "time"
14 )
15
16 func (m *RouteMessage) String() string {
17         return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[12:16])))
18 }
19
20 func (m *InterfaceMessage) String() string {
21         var attrs addrAttrs
22         if runtime.GOOS == "openbsd" {
23                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
24         } else {
25                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
26         }
27         return fmt.Sprintf("%s", attrs)
28 }
29
30 func (m *InterfaceAddrMessage) String() string {
31         var attrs addrAttrs
32         if runtime.GOOS == "openbsd" {
33                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
34         } else {
35                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
36         }
37         return fmt.Sprintf("%s", attrs)
38 }
39
40 func (m *InterfaceMulticastAddrMessage) String() string {
41         return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8])))
42 }
43
44 func (m *InterfaceAnnounceMessage) String() string {
45         what := "<nil>"
46         switch m.What {
47         case 0:
48                 what = "arrival"
49         case 1:
50                 what = "departure"
51         }
52         return fmt.Sprintf("(%d %s %s)", m.Index, m.Name, what)
53 }
54
55 func (m *InterfaceMetrics) String() string {
56         return fmt.Sprintf("(type=%d mtu=%d)", m.Type, m.MTU)
57 }
58
59 func (m *RouteMetrics) String() string {
60         return fmt.Sprintf("(pmtu=%d)", m.PathMTU)
61 }
62
63 type addrAttrs uint
64
65 var addrAttrNames = [...]string{
66         "dst",
67         "gateway",
68         "netmask",
69         "genmask",
70         "ifp",
71         "ifa",
72         "author",
73         "brd",
74         "df:mpls1-n:tag-o:src", // mpls1 for dragonfly, tag for netbsd, src for openbsd
75         "df:mpls2-o:srcmask",   // mpls2 for dragonfly, srcmask for openbsd
76         "df:mpls3-o:label",     // mpls3 for dragonfly, label for openbsd
77         "o:bfd",                // bfd for openbsd
78         "o:dns",                // dns for openbsd
79         "o:static",             // static for openbsd
80         "o:search",             // search for openbsd
81 }
82
83 func (attrs addrAttrs) String() string {
84         var s string
85         for i, name := range addrAttrNames {
86                 if attrs&(1<<uint(i)) != 0 {
87                         if s != "" {
88                                 s += "|"
89                         }
90                         s += name
91                 }
92         }
93         if s == "" {
94                 return "<nil>"
95         }
96         return s
97 }
98
99 type msgs []Message
100
101 func (ms msgs) validate() ([]string, error) {
102         var ss []string
103         for _, m := range ms {
104                 switch m := m.(type) {
105                 case *RouteMessage:
106                         if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[12:16]))); err != nil {
107                                 return nil, err
108                         }
109                         sys := m.Sys()
110                         if sys == nil {
111                                 return nil, fmt.Errorf("no sys for %s", m.String())
112                         }
113                         ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
114                 case *InterfaceMessage:
115                         var attrs addrAttrs
116                         if runtime.GOOS == "openbsd" {
117                                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
118                         } else {
119                                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
120                         }
121                         if err := addrs(m.Addrs).match(attrs); err != nil {
122                                 return nil, err
123                         }
124                         sys := m.Sys()
125                         if sys == nil {
126                                 return nil, fmt.Errorf("no sys for %s", m.String())
127                         }
128                         ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
129                 case *InterfaceAddrMessage:
130                         var attrs addrAttrs
131                         if runtime.GOOS == "openbsd" {
132                                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
133                         } else {
134                                 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
135                         }
136                         if err := addrs(m.Addrs).match(attrs); err != nil {
137                                 return nil, err
138                         }
139                         ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
140                 case *InterfaceMulticastAddrMessage:
141                         if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil {
142                                 return nil, err
143                         }
144                         ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
145                 case *InterfaceAnnounceMessage:
146                         ss = append(ss, m.String())
147                 default:
148                         ss = append(ss, fmt.Sprintf("%+v", m))
149                 }
150         }
151         return ss, nil
152 }
153
154 type syss []Sys
155
156 func (sys syss) String() string {
157         var s string
158         for _, sy := range sys {
159                 switch sy := sy.(type) {
160                 case *InterfaceMetrics:
161                         if len(s) > 0 {
162                                 s += " "
163                         }
164                         s += sy.String()
165                 case *RouteMetrics:
166                         if len(s) > 0 {
167                                 s += " "
168                         }
169                         s += sy.String()
170                 }
171         }
172         return s
173 }
174
175 type addrFamily int
176
177 func (af addrFamily) String() string {
178         switch af {
179         case sysAF_UNSPEC:
180                 return "unspec"
181         case sysAF_LINK:
182                 return "link"
183         case sysAF_INET:
184                 return "inet4"
185         case sysAF_INET6:
186                 return "inet6"
187         default:
188                 return fmt.Sprintf("%d", af)
189         }
190 }
191
192 const hexDigit = "0123456789abcdef"
193
194 type llAddr []byte
195
196 func (a llAddr) String() string {
197         if len(a) == 0 {
198                 return ""
199         }
200         buf := make([]byte, 0, len(a)*3-1)
201         for i, b := range a {
202                 if i > 0 {
203                         buf = append(buf, ':')
204                 }
205                 buf = append(buf, hexDigit[b>>4])
206                 buf = append(buf, hexDigit[b&0xF])
207         }
208         return string(buf)
209 }
210
211 type ipAddr []byte
212
213 func (a ipAddr) String() string {
214         if len(a) == 0 {
215                 return "<nil>"
216         }
217         if len(a) == 4 {
218                 return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
219         }
220         if len(a) == 16 {
221                 return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
222         }
223         s := make([]byte, len(a)*2)
224         for i, tn := range a {
225                 s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
226         }
227         return string(s)
228 }
229
230 func (a *LinkAddr) String() string {
231         name := a.Name
232         if name == "" {
233                 name = "<nil>"
234         }
235         lla := llAddr(a.Addr).String()
236         if lla == "" {
237                 lla = "<nil>"
238         }
239         return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
240 }
241
242 func (a *Inet4Addr) String() string {
243         return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), ipAddr(a.IP[:]))
244 }
245
246 func (a *Inet6Addr) String() string {
247         return fmt.Sprintf("(%v %v %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.ZoneID)
248 }
249
250 func (a *DefaultAddr) String() string {
251         return fmt.Sprintf("(%v %s)", addrFamily(a.Family()), ipAddr(a.Raw[2:]).String())
252 }
253
254 type addrs []Addr
255
256 func (as addrs) String() string {
257         var s string
258         for _, a := range as {
259                 if a == nil {
260                         continue
261                 }
262                 if len(s) > 0 {
263                         s += " "
264                 }
265                 switch a := a.(type) {
266                 case *LinkAddr:
267                         s += a.String()
268                 case *Inet4Addr:
269                         s += a.String()
270                 case *Inet6Addr:
271                         s += a.String()
272                 case *DefaultAddr:
273                         s += a.String()
274                 }
275         }
276         if s == "" {
277                 return "<nil>"
278         }
279         return s
280 }
281
282 func (as addrs) match(attrs addrAttrs) error {
283         var ts addrAttrs
284         af := sysAF_UNSPEC
285         for i := range as {
286                 if as[i] != nil {
287                         ts |= 1 << uint(i)
288                 }
289                 switch as[i].(type) {
290                 case *Inet4Addr:
291                         if af == sysAF_UNSPEC {
292                                 af = sysAF_INET
293                         }
294                         if af != sysAF_INET {
295                                 return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
296                         }
297                 case *Inet6Addr:
298                         if af == sysAF_UNSPEC {
299                                 af = sysAF_INET6
300                         }
301                         if af != sysAF_INET6 {
302                                 return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
303                         }
304                 }
305         }
306         if ts != attrs && ts > attrs {
307                 return fmt.Errorf("%v not included in %v", ts, attrs)
308         }
309         return nil
310 }
311
312 func fetchAndParseRIB(af int, typ RIBType) ([]Message, error) {
313         var err error
314         var b []byte
315         for i := 0; i < 3; i++ {
316                 if b, err = FetchRIB(af, typ, 0); err != nil {
317                         time.Sleep(10 * time.Millisecond)
318                         continue
319                 }
320                 break
321         }
322         if err != nil {
323                 return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
324         }
325         ms, err := ParseRIB(typ, b)
326         if err != nil {
327                 return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
328         }
329         return ms, nil
330 }
331
332 // propVirtual is a proprietary virtual network interface.
333 type propVirtual struct {
334         name         string
335         addr, mask   string
336         setupCmds    []*exec.Cmd
337         teardownCmds []*exec.Cmd
338 }
339
340 func (pv *propVirtual) setup() error {
341         for _, cmd := range pv.setupCmds {
342                 if err := cmd.Run(); err != nil {
343                         pv.teardown()
344                         return err
345                 }
346         }
347         return nil
348 }
349
350 func (pv *propVirtual) teardown() error {
351         for _, cmd := range pv.teardownCmds {
352                 if err := cmd.Run(); err != nil {
353                         return err
354                 }
355         }
356         return nil
357 }
358
359 func (pv *propVirtual) configure(suffix int) error {
360         if runtime.GOOS == "openbsd" {
361                 pv.name = fmt.Sprintf("vether%d", suffix)
362         } else {
363                 pv.name = fmt.Sprintf("vlan%d", suffix)
364         }
365         xname, err := exec.LookPath("ifconfig")
366         if err != nil {
367                 return err
368         }
369         pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
370                 Path: xname,
371                 Args: []string{"ifconfig", pv.name, "create"},
372         })
373         if runtime.GOOS == "netbsd" {
374                 // NetBSD requires an underlying dot1Q-capable network
375                 // interface.
376                 pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
377                         Path: xname,
378                         Args: []string{"ifconfig", pv.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"},
379                 })
380         }
381         pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
382                 Path: xname,
383                 Args: []string{"ifconfig", pv.name, "inet", pv.addr, "netmask", pv.mask},
384         })
385         pv.teardownCmds = append(pv.teardownCmds, &exec.Cmd{
386                 Path: xname,
387                 Args: []string{"ifconfig", pv.name, "destroy"},
388         })
389         return nil
390 }