github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/internal/nettest/interface.go (about) 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 }