blob: 4df3db40d57460f910568b2e4e9b27b3b7e83104 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium 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
Cosmos Nicolaouef323db2014-09-07 22:13:28 -07005package internal
6
7import (
8 "fmt"
Cosmos Nicolaouaa87e292015-04-21 22:15:50 -07009 "net"
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080010 "os"
Jungho Ahnb2657b22015-02-04 09:10:04 -080011 "strings"
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070012
Matt Rosencrantz9d3278a2015-03-11 14:58:34 -070013 "v.io/x/lib/netstate"
Cosmos Nicolaou0e4e3922015-06-10 16:30:09 -070014
15 "v.io/v23/logging"
16 "v.io/v23/verror"
17
Jiri Simsaffceefa2015-02-28 11:03:34 -080018 "v.io/x/ref/lib/exec"
19 "v.io/x/ref/lib/flags"
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070020)
21
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080022// ParseFlags parses all registered flags taking into account overrides from other
23// configuration and environment variables. It must be called by the profile and
24// flags.RuntimeFlags() must be passed to the runtime initialization function. The
25// profile can use or modify the flags as it pleases.
26func ParseFlags(f *flags.Flags) error {
27 handle, err := exec.GetChildHandle()
Mike Burrowsccca2f42015-03-27 13:57:29 -070028 if err == nil {
Suharsh Sivakumard1cc6e02015-03-16 13:58:49 -070029 // The process has been started through the vanadium exec
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080030 // library.
Mike Burrowsccca2f42015-03-27 13:57:29 -070031 } else if verror.ErrorID(err) == exec.ErrNoVersion.ID {
32 // The process has not been started through the vanadium exec
33 // library. No further action is needed.
34 } else {
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080035 return err
36 }
37
38 // Parse runtime flags.
39 var config map[string]string
40 if handle != nil {
41 config = handle.Config.Dump()
42 }
Todd Wangf1550cf2015-05-11 10:58:41 -070043 return f.Parse(os.Args[1:], config)
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080044}
45
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070046// IPAddressChooser returns the preferred IP address, which is,
47// a public IPv4 address, then any non-loopback IPv4, then a public
48// IPv6 address and finally any non-loopback/link-local IPv6
James Ring318c3fa2015-06-17 11:27:23 -070049type IPAddressChooser struct{}
50
51func (IPAddressChooser) ChooseAddress(network string, addrs []net.Addr) ([]net.Addr, error) {
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070052 if !netstate.IsIPProtocol(network) {
53 return nil, fmt.Errorf("can't support network protocol %q", network)
54 }
Cosmos Nicolaouaa87e292015-04-21 22:15:50 -070055 accessible := netstate.ConvertToAddresses(addrs)
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070056
57 // Try and find an address on a interface with a default route.
Jungho Ahnb2657b22015-02-04 09:10:04 -080058 // We give preference to IPv4 over IPv6 for compatibility for now.
59 var predicates []netstate.AddressPredicate
60 if !strings.HasSuffix(network, "6") {
61 predicates = append(predicates, netstate.IsPublicUnicastIPv4, netstate.IsUnicastIPv4)
62 }
63 if !strings.HasSuffix(network, "4") {
64 predicates = append(predicates, netstate.IsPublicUnicastIPv6, netstate.IsUnicastIPv6)
65 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070066 for _, predicate := range predicates {
67 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
68 onDefaultRoutes := addrs.Filter(netstate.IsOnDefaultRoute)
69 if len(onDefaultRoutes) > 0 {
Cosmos Nicolaouaa87e292015-04-21 22:15:50 -070070 return onDefaultRoutes.AsNetAddrs(), nil
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070071 }
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070072 }
73 }
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070074
75 // We failed to find any addresses with default routes, try again
76 // but without the default route requirement.
77 for _, predicate := range predicates {
78 if addrs := accessible.Filter(predicate); len(addrs) > 0 {
Cosmos Nicolaouaa87e292015-04-21 22:15:50 -070079 return addrs.AsNetAddrs(), nil
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -070080 }
81 }
Cosmos Nicolaouaa87e292015-04-21 22:15:50 -070082 return []net.Addr{}, nil
Cosmos Nicolaouef323db2014-09-07 22:13:28 -070083}
Cosmos Nicolaou43b95352014-10-14 11:09:52 -070084
85// HasPublicIP returns true if the host has at least one public IP address.
Cosmos Nicolaou0e4e3922015-06-10 16:30:09 -070086func HasPublicIP(log logging.Logger) bool {
Cosmos Nicolaou43b95352014-10-14 11:09:52 -070087 state, err := netstate.GetAccessibleIPs()
88 if err != nil {
89 log.Infof("failed to determine network state: %s", err)
90 return false
91 }
92 any := state.Filter(netstate.IsUnicastIP)
93 if len(any) == 0 {
94 log.Infof("failed to find any usable IP addresses at startup")
95 return false
96 }
97 for _, a := range any {
98 if netstate.IsPublicUnicastIPv4(a) {
99 return true
100 }
101 }
102 return false
103}