12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- // Copyright 2012 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
-
- package nettest
-
- import "net"
-
- // IsMulticastCapable reports whether ifi is an IP multicast-capable
- // network interface. Network must be "ip", "ip4" or "ip6".
- func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
- switch network {
- case "ip", "ip4", "ip6":
- default:
- return nil, false
- }
- if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
- return nil, false
- }
- return hasRoutableIP(network, ifi)
- }
-
- // RoutedInterface returns a network interface that can route IP
- // traffic and satisfies flags. It returns nil when an appropriate
- // network interface is not found. Network must be "ip", "ip4" or
- // "ip6".
- func RoutedInterface(network string, flags net.Flags) *net.Interface {
- switch network {
- case "ip", "ip4", "ip6":
- default:
- return nil
- }
- ift, err := net.Interfaces()
- if err != nil {
- return nil
- }
- for _, ifi := range ift {
- if ifi.Flags&flags != flags {
- continue
- }
- if _, ok := hasRoutableIP(network, &ifi); !ok {
- continue
- }
- return &ifi
- }
- return nil
- }
-
- func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
- ifat, err := ifi.Addrs()
- if err != nil {
- return nil, false
- }
- for _, ifa := range ifat {
- switch ifa := ifa.(type) {
- case *net.IPAddr:
- if ip := routableIP(network, ifa.IP); ip != nil {
- return ip, true
- }
- case *net.IPNet:
- if ip := routableIP(network, ifa.IP); ip != nil {
- return ip, true
- }
- }
- }
- return nil, false
- }
-
- func routableIP(network string, ip net.IP) net.IP {
- if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
- return nil
- }
- switch network {
- case "ip4":
- if ip := ip.To4(); ip != nil {
- return ip
- }
- case "ip6":
- if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
- return nil
- }
- if ip := ip.To16(); ip != nil && ip.To4() == nil {
- return ip
- }
- default:
- if ip := ip.To4(); ip != nil {
- return ip
- }
- if ip := ip.To16(); ip != nil {
- return ip
- }
- }
- return nil
- }
|