blob: c3c53cedf771f4c66eeeb5f13a83a3aa76cde6fa [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 Nicolaou43b95352014-10-14 11:09:52 -07007 "veyron.io/veyron/veyron2/vlog"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07008
Jiri Simsa519c5072014-09-17 21:37:57 -07009 "veyron.io/veyron/veyron/lib/netstate"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070010)
11
12// IPAddressChooser returns the preferred IP address, which is,
13// a public IPv4 address, then any non-loopback IPv4, then a public
14// IPv6 address and finally any non-loopback/link-local IPv6
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070015func IPAddressChooser(network string, addrs []ipc.Address) ([]ipc.Address, error) {
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070016 if !netstate.IsIPProtocol(network) {
17 return nil, fmt.Errorf("can't support network protocol %q", network)
18 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070019 accessible := netstate.AddrList(addrs)
20
21 // Try and find an address on a interface with a default route.
22 predicates := []netstate.AddressPredicate{netstate.IsPublicUnicastIPv4,
23 netstate.IsUnicastIPv4, netstate.IsPublicUnicastIPv6}
24 for _, predicate := range predicates {
25 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
26 onDefaultRoutes := addrs.Filter(netstate.IsOnDefaultRoute)
27 if len(onDefaultRoutes) > 0 {
28 return onDefaultRoutes, nil
29 }
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070030 }
31 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070032
33 // We failed to find any addresses with default routes, try again
34 // but without the default route requirement.
35 for _, predicate := range predicates {
36 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
37 return addrs, nil
38 }
39 }
40
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070041 return nil, fmt.Errorf("failed to find any usable address for %q", network)
42}
Cosmos Nicolaou43b95352014-10-14 11:09:52 -070043
44// HasPublicIP returns true if the host has at least one public IP address.
45func HasPublicIP(log vlog.Logger) bool {
46 state, err := netstate.GetAccessibleIPs()
47 if err != nil {
48 log.Infof("failed to determine network state: %s", err)
49 return false
50 }
51 any := state.Filter(netstate.IsUnicastIP)
52 if len(any) == 0 {
53 log.Infof("failed to find any usable IP addresses at startup")
54 return false
55 }
56 for _, a := range any {
57 if netstate.IsPublicUnicastIPv4(a) {
58 return true
59 }
60 }
61 return false
62}