diff --git a/Gopkg.lock b/Gopkg.lock index 0b35835a5..ea04733d9 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -620,12 +620,11 @@ version = "v1.0" [[projects]] - digest = "1:c145f317274ab1a430e40f427402ca812219dbd4fa548a60fe1e09820c51d8cd" + digest = "1:8e34e38aafc5f66eb68ba2ece587d5a8267cae283f68591869cb8714eb27a2c0" name = "github.com/jackpal/gateway" packages = ["."] pruneopts = "NUT" - revision = "10816db7ab2f4b71e71dba9420bfa67d5be27b33" - source = "github.com/ndeloof/gateway" + revision = "5ceb358a720efa82a5692470f37874b1f48035ad" [[projects]] digest = "1:fbfb539de947ebc48768d413ee811e3ff34d32636ff0965a517e7786e559f66b" diff --git a/Gopkg.toml b/Gopkg.toml index 0e2112fda..343785de5 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -127,10 +127,8 @@ required = ["github.com/wadey/gocovmerge"] branch = "master" [[constraint]] - # see https://github.com/jackpal/gateway/pull/21 - source = "github.com/ndeloof/gateway" name = "github.com/jackpal/gateway" - revision = "10816db7ab2f4b71e71dba9420bfa67d5be27b33" + revision = "5ceb358a720efa82a5692470f37874b1f48035ad" [[constraint]] name = "github.com/dustin/go-humanize" diff --git a/vendor/github.com/jackpal/gateway/gateway_common.go b/vendor/github.com/jackpal/gateway/gateway_common.go index c6fe816cd..2ee4d9b82 100644 --- a/vendor/github.com/jackpal/gateway/gateway_common.go +++ b/vendor/github.com/jackpal/gateway/gateway_common.go @@ -1,8 +1,12 @@ package gateway import ( + "bufio" + "bytes" + "encoding/binary" "errors" "net" + "strconv" "strings" ) @@ -53,58 +57,43 @@ func parseWindowsRoutePrint(output []byte) (net.IP, error) { return nil, errNoGateway } -func parseLinuxIPRouteShow(output []byte) (net.IP, error) { - // Linux '/usr/bin/ip route show' format looks like this: - // default via 192.168.178.1 dev wlp3s0 metric 303 - // 192.168.178.0/24 dev wlp3s0 proto kernel scope link src 192.168.178.76 metric 303 - lines := strings.Split(string(output), "\n") - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) >= 3 && fields[0] == "default" { - ip := net.ParseIP(fields[2]) - if ip != nil { - return ip, nil - } - } - } - return nil, errNoGateway -} +func parseLinuxProcNetRoute(f []byte) (net.IP, error) { + /* /proc/net/route file: + Iface Destination Gateway Flags RefCnt Use Metric Mask + eno1 00000000 C900A8C0 0003 0 0 100 00000000 0 00 + eno1 0000A8C0 00000000 0001 0 0 100 00FFFFFF 0 00 + */ + const ( + sep = "\t" // field separator + field = 2 // field containing hex gateway address + ) + scanner := bufio.NewScanner(bytes.NewReader(f)) + for scanner.Scan() { + // Skip header line + if !scanner.Scan() { + return nil, errors.New("Invalid linux route file") + } -func parseLinuxIPRouteGet(output []byte) (net.IP, error) { - // Linux '/usr/bin/ip route get 8.8.8.8' format looks like this: - // 8.8.8.8 via 10.0.1.1 dev eth0 src 10.0.1.36 uid 2000 - lines := strings.Split(string(output), "\n") - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) >= 2 && fields[1] == "via" { - ip := net.ParseIP(fields[2]) - if ip != nil { - return ip, nil - } + // get field containing gateway address + tokens := strings.Split(scanner.Text(), sep) + if len(tokens) <= field { + return nil, errors.New("Invalid linux route file") } - } + gatewayHex := "0x" + tokens[field] - return nil, errNoGateway -} + // cast hex address to uint32 + d, _ := strconv.ParseInt(gatewayHex, 0, 64) + d32 := uint32(d) -func parseLinuxRoute(output []byte) (net.IP, error) { - // Linux route out format is always like this: - // Kernel IP routing table - // Destination Gateway Genmask Flags Metric Ref Use Iface - // 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 - lines := strings.Split(string(output), "\n") - for _, line := range lines { - fields := strings.Fields(line) - if len(fields) >= 2 && fields[0] == "0.0.0.0" { - ip := net.ParseIP(fields[1]) - if ip != nil { - return ip, nil - } - } - } + // make net.IP address from uint32 + ipd32 := make(net.IP, 4) + binary.LittleEndian.PutUint32(ipd32, d32) - return nil, errNoGateway + // format net.IP to dotted ipV4 string + return net.IP(ipd32), nil + } + return nil, errors.New("Failed to parse linux route file") } func parseDarwinRouteGet(output []byte) (net.IP, error) { diff --git a/vendor/github.com/jackpal/gateway/gateway_linux.go b/vendor/github.com/jackpal/gateway/gateway_linux.go index aacaa88e7..6ed020c8f 100644 --- a/vendor/github.com/jackpal/gateway/gateway_linux.go +++ b/vendor/github.com/jackpal/gateway/gateway_linux.go @@ -1,47 +1,30 @@ package gateway import ( + "fmt" + "io/ioutil" "net" - "os/exec" + "os" ) -func DiscoverGateway() (ip net.IP, err error) { - ip, err = discoverGatewayUsingRoute() - if err != nil { - ip, err = discoverGatewayUsingIpRouteShow() - } - if err != nil { - ip, err = discoverGatewayUsingIpRouteGet() - } - return -} -func discoverGatewayUsingIpRouteShow() (net.IP, error) { - routeCmd := exec.Command("ip", "route", "show") - output, err := routeCmd.CombinedOutput() +const ( + // See http://man7.org/linux/man-pages/man8/route.8.html + file = "/proc/net/route" +) + +func DiscoverGateway() (ip net.IP, err error) { + f, err := os.Open(file) if err != nil { - return nil, err + return nil, fmt.Errorf("Can't access %s", file) } + defer f.Close() - return parseLinuxIPRouteShow(output) -} - -func discoverGatewayUsingIpRouteGet() (net.IP, error) { - routeCmd := exec.Command("ip", "route", "get", "8.8.8.8") - output, err := routeCmd.CombinedOutput() + bytes, err := ioutil.ReadAll(f) if err != nil { - return nil, err + return nil, fmt.Errorf("Can't read %s", file) } - - return parseLinuxIPRouteGet(output) + return parseLinuxProcNetRoute(bytes) } -func discoverGatewayUsingRoute() (net.IP, error) { - routeCmd := exec.Command("route", "-n") - output, err := routeCmd.CombinedOutput() - if err != nil { - return nil, err - } - return parseLinuxRoute(output) -}