OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / internal / nettest / interface.go
1 // Copyright 2012 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 nettest
6
7 import "net"
8
9 // IsMulticastCapable reports whether ifi is an IP multicast-capable
10 // network interface. Network must be "ip", "ip4" or "ip6".
11 func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
12         switch network {
13         case "ip", "ip4", "ip6":
14         default:
15                 return nil, false
16         }
17         if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
18                 return nil, false
19         }
20         return hasRoutableIP(network, ifi)
21 }
22
23 // RoutedInterface returns a network interface that can route IP
24 // traffic and satisfies flags. It returns nil when an appropriate
25 // network interface is not found. Network must be "ip", "ip4" or
26 // "ip6".
27 func RoutedInterface(network string, flags net.Flags) *net.Interface {
28         switch network {
29         case "ip", "ip4", "ip6":
30         default:
31                 return nil
32         }
33         ift, err := net.Interfaces()
34         if err != nil {
35                 return nil
36         }
37         for _, ifi := range ift {
38                 if ifi.Flags&flags != flags {
39                         continue
40                 }
41                 if _, ok := hasRoutableIP(network, &ifi); !ok {
42                         continue
43                 }
44                 return &ifi
45         }
46         return nil
47 }
48
49 func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
50         ifat, err := ifi.Addrs()
51         if err != nil {
52                 return nil, false
53         }
54         for _, ifa := range ifat {
55                 switch ifa := ifa.(type) {
56                 case *net.IPAddr:
57                         if ip := routableIP(network, ifa.IP); ip != nil {
58                                 return ip, true
59                         }
60                 case *net.IPNet:
61                         if ip := routableIP(network, ifa.IP); ip != nil {
62                                 return ip, true
63                         }
64                 }
65         }
66         return nil, false
67 }
68
69 func routableIP(network string, ip net.IP) net.IP {
70         if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
71                 return nil
72         }
73         switch network {
74         case "ip4":
75                 if ip := ip.To4(); ip != nil {
76                         return ip
77                 }
78         case "ip6":
79                 if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
80                         return nil
81                 }
82                 if ip := ip.To16(); ip != nil && ip.To4() == nil {
83                         return ip
84                 }
85         default:
86                 if ip := ip.To4(); ip != nil {
87                         return ip
88                 }
89                 if ip := ip.To16(); ip != nil {
90                         return ip
91                 }
92         }
93         return nil
94 }