Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // 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 Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 5 | package internal |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
Cosmos Nicolaou | aa87e29 | 2015-04-21 22:15:50 -0700 | [diff] [blame] | 9 | "net" |
Suharsh Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 10 | "os" |
Jungho Ahn | b2657b2 | 2015-02-04 09:10:04 -0800 | [diff] [blame] | 11 | "strings" |
Cosmos Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 12 | |
Matt Rosencrantz | 9d3278a | 2015-03-11 14:58:34 -0700 | [diff] [blame] | 13 | "v.io/x/lib/netstate" |
Cosmos Nicolaou | 0e4e392 | 2015-06-10 16:30:09 -0700 | [diff] [blame] | 14 | |
| 15 | "v.io/v23/logging" |
| 16 | "v.io/v23/verror" |
| 17 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 18 | "v.io/x/ref/lib/exec" |
| 19 | "v.io/x/ref/lib/flags" |
Cosmos Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 20 | ) |
| 21 | |
Suharsh Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 22 | // 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. |
| 26 | func ParseFlags(f *flags.Flags) error { |
| 27 | handle, err := exec.GetChildHandle() |
Mike Burrows | ccca2f4 | 2015-03-27 13:57:29 -0700 | [diff] [blame] | 28 | if err == nil { |
Suharsh Sivakumar | d1cc6e0 | 2015-03-16 13:58:49 -0700 | [diff] [blame] | 29 | // The process has been started through the vanadium exec |
Suharsh Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 30 | // library. |
Mike Burrows | ccca2f4 | 2015-03-27 13:57:29 -0700 | [diff] [blame] | 31 | } 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 Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 35 | 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 Wang | f1550cf | 2015-05-11 10:58:41 -0700 | [diff] [blame] | 43 | return f.Parse(os.Args[1:], config) |
Suharsh Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 44 | } |
| 45 | |
Cosmos Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 46 | // 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 Ring | 318c3fa | 2015-06-17 11:27:23 -0700 | [diff] [blame] | 49 | type IPAddressChooser struct{} |
| 50 | |
| 51 | func (IPAddressChooser) ChooseAddress(network string, addrs []net.Addr) ([]net.Addr, error) { |
Cosmos Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 52 | if !netstate.IsIPProtocol(network) { |
| 53 | return nil, fmt.Errorf("can't support network protocol %q", network) |
| 54 | } |
Cosmos Nicolaou | aa87e29 | 2015-04-21 22:15:50 -0700 | [diff] [blame] | 55 | accessible := netstate.ConvertToAddresses(addrs) |
Cosmos Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 56 | |
| 57 | // Try and find an address on a interface with a default route. |
Jungho Ahn | b2657b2 | 2015-02-04 09:10:04 -0800 | [diff] [blame] | 58 | // 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 Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 66 | 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 Nicolaou | aa87e29 | 2015-04-21 22:15:50 -0700 | [diff] [blame] | 70 | return onDefaultRoutes.AsNetAddrs(), nil |
Cosmos Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 71 | } |
Cosmos Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 72 | } |
| 73 | } |
Cosmos Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 74 | |
| 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 Nicolaou | aa87e29 | 2015-04-21 22:15:50 -0700 | [diff] [blame] | 79 | return addrs.AsNetAddrs(), nil |
Cosmos Nicolaou | 66bc120 | 2014-09-30 20:42:43 -0700 | [diff] [blame] | 80 | } |
| 81 | } |
Cosmos Nicolaou | aa87e29 | 2015-04-21 22:15:50 -0700 | [diff] [blame] | 82 | return []net.Addr{}, nil |
Cosmos Nicolaou | ef323db | 2014-09-07 22:13:28 -0700 | [diff] [blame] | 83 | } |
Cosmos Nicolaou | 43b9535 | 2014-10-14 11:09:52 -0700 | [diff] [blame] | 84 | |
| 85 | // HasPublicIP returns true if the host has at least one public IP address. |
Cosmos Nicolaou | 0e4e392 | 2015-06-10 16:30:09 -0700 | [diff] [blame] | 86 | func HasPublicIP(log logging.Logger) bool { |
Cosmos Nicolaou | 43b9535 | 2014-10-14 11:09:52 -0700 | [diff] [blame] | 87 | 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 | } |