github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/gateway.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package network 5 6 import ( 7 "net" 8 "os/exec" 9 "runtime" 10 "strconv" 11 "strings" 12 ) 13 14 var goos = func() string { 15 return runtime.GOOS 16 } 17 18 var runIPRouteShow = func() (string, error) { 19 output, err := exec.Command("ip", "route", "show").CombinedOutput() 20 if err != nil { 21 return "", err 22 } 23 return string(output), nil 24 } 25 26 func GetDefaultRoute() (net.IP, string, error) { 27 output, err := runIPRouteShow() 28 if err != nil { 29 return nil, "", err 30 } 31 logger.Tracef("ip route show output:\n%s", output) 32 var defaultRouteMetric = ^uint64(0) 33 var defaultRoute string 34 var defaultRouteDevice string 35 for _, line := range strings.Split(output, "\n") { 36 to, values := parseIpRouteShowLine(line) 37 logger.Tracef("parsing ip r s line to %q, values %+v ", to, values) 38 if to == "default" { 39 var metric = uint64(0) 40 if v, ok := values["metric"]; ok { 41 if i, err := strconv.ParseUint(v, 10, 64); err == nil { 42 metric = i 43 } else { 44 return nil, "", err 45 } 46 } 47 if metric < defaultRouteMetric { 48 // We want to replace our current default route if it's valid. 49 via, hasVia := values["via"] 50 dev, hasDev := values["dev"] 51 if hasVia || hasDev { 52 defaultRouteMetric = metric 53 if hasVia { 54 defaultRoute = via 55 } else { 56 defaultRoute = "" 57 } 58 if hasDev { 59 defaultRouteDevice = dev 60 } else { 61 defaultRouteDevice = "" 62 } 63 } 64 } 65 } 66 } 67 return net.ParseIP(defaultRoute), defaultRouteDevice, nil 68 } 69 70 func parseIpRouteShowLine(line string) (string, map[string]string) { 71 values := make(map[string]string) 72 fields := strings.Fields(line) 73 if len(fields) < 2 { 74 return "", values 75 } 76 to, fields := fields[0], fields[1:] 77 for ; len(fields) >= 2; fields = fields[2:] { 78 values[fields[0]] = fields[1] 79 } 80 return to, values 81 }