blob: 7af4da9ceefa594b15ec1a01590e8d5d1de032fd [file] [log] [blame]
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07001package internal
2
3import (
4 "fmt"
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -07005
6 "veyron.io/veyron/veyron2/ipc"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07007
Jiri Simsa519c5072014-09-17 21:37:57 -07008 "veyron.io/veyron/veyron/lib/netstate"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07009)
10
11// IPAddressChooser returns the preferred IP address, which is,
12// a public IPv4 address, then any non-loopback IPv4, then a public
13// IPv6 address and finally any non-loopback/link-local IPv6
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070014func IPAddressChooser(network string, addrs []ipc.Address) ([]ipc.Address, error) {
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070015 if !netstate.IsIPProtocol(network) {
16 return nil, fmt.Errorf("can't support network protocol %q", network)
17 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070018 accessible := netstate.AddrList(addrs)
19
20 // Try and find an address on a interface with a default route.
21 predicates := []netstate.AddressPredicate{netstate.IsPublicUnicastIPv4,
22 netstate.IsUnicastIPv4, netstate.IsPublicUnicastIPv6}
23 for _, predicate := range predicates {
24 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
25 onDefaultRoutes := addrs.Filter(netstate.IsOnDefaultRoute)
26 if len(onDefaultRoutes) > 0 {
27 return onDefaultRoutes, nil
28 }
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070029 }
30 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070031
32 // We failed to find any addresses with default routes, try again
33 // but without the default route requirement.
34 for _, predicate := range predicates {
35 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
36 return addrs, nil
37 }
38 }
39
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070040 return nil, fmt.Errorf("failed to find any usable address for %q", network)
41}