pax_global_header00006660000000000000000000000064127235632660014526gustar00rootroot0000000000000052 comment=3e333950771011fed13be63e62b9f473c5e0d9bf gateway-1.0.4/000077500000000000000000000000001272356326600131715ustar00rootroot00000000000000gateway-1.0.4/.travis.yml000066400000000000000000000002411272356326600152770ustar00rootroot00000000000000language: go go: - 1.6.2 - tip allowed_failures: - go: tip install: - go get -d -v ./... && go install -race -v ./... script: go test -race -v ./... gateway-1.0.4/LICENSE000066400000000000000000000030241272356326600141750ustar00rootroot00000000000000// Copyright (c) 2010 Jack Palevich. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gateway-1.0.4/README.md000066400000000000000000000006051272356326600144510ustar00rootroot00000000000000# gateway A simple library for discovering the IP address of the default gateway. [![Build Status](https://travis-ci.org/jackpal/gateway.svg)](https://travis-ci.org/jackpal/gateway) Provides implementations for: + FreeBSD + Linux + OS X (Darwin) + Solaris + Windows Other platforms use an implementation that always returns an error. Pull requests for other OSs happily considered! gateway-1.0.4/gateway_common.go000066400000000000000000000074651272356326600165450ustar00rootroot00000000000000package gateway import ( "errors" "net" "strings" ) var errNoGateway = errors.New("no gateway found") func parseWindowsRoutePrint(output []byte) (net.IP, error) { // Windows route output format is always like this: // =========================================================================== // Active Routes: // Network Destination Netmask Gateway Interface Metric // 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.100 20 // =========================================================================== // I'm trying to pick the active route, // then jump 2 lines and pick the third IP // Not using regex because output is quite standard from Windows XP to 8 (NEEDS TESTING) lines := strings.Split(string(output), "\n") for idx, line := range lines { if strings.HasPrefix(line, "Active Routes:") { if len(lines) <= idx+2 { return nil, errNoGateway } fields := strings.Fields(lines[idx+2]) if len(fields) < 3 { return nil, errNoGateway } ip := net.ParseIP(fields[2]) if ip != nil { return ip, nil } } } return nil, errNoGateway } func parseLinuxIPRoute(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 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 } } } return nil, errNoGateway } func parseDarwinRouteGet(output []byte) (net.IP, error) { // Darwin route out format is always like this: // route to: default // destination: default // mask: default // gateway: 192.168.1.1 lines := strings.Split(string(output), "\n") for _, line := range lines { fields := strings.Fields(line) if len(fields) >= 2 && fields[0] == "gateway:" { ip := net.ParseIP(fields[1]) if ip != nil { return ip, nil } } } return nil, errNoGateway } func parseBSDSolarisNetstat(output []byte) (net.IP, error) { // netstat -rn produces the following on FreeBSD: // Routing tables // // Internet: // Destination Gateway Flags Netif Expire // default 10.88.88.2 UGS em0 // 10.88.88.0/24 link#1 U em0 // 10.88.88.148 link#1 UHS lo0 // 127.0.0.1 link#2 UH lo0 // // Internet6: // Destination Gateway Flags Netif Expire // ::/96 ::1 UGRS lo0 // ::1 link#2 UH lo0 // ::ffff:0.0.0.0/96 ::1 UGRS lo0 // fe80::/10 ::1 UGRS lo0 // ... outputLines := strings.Split(string(output), "\n") for _, line := range outputLines { fields := strings.Fields(line) if len(fields) >= 2 && fields[0] == "default" { ip := net.ParseIP(fields[1]) if ip != nil { return ip, nil } } } return nil, errNoGateway } gateway-1.0.4/gateway_darwin.go000066400000000000000000000004201272356326600165210ustar00rootroot00000000000000package gateway import ( "net" "os/exec" ) func DiscoverGateway() (net.IP, error) { routeCmd := exec.Command("/sbin/route", "-n", "get", "0.0.0.0") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseDarwinRouteGet(output) } gateway-1.0.4/gateway_freebsd.go000066400000000000000000000004051272356326600166520ustar00rootroot00000000000000package gateway import ( "net" "os/exec" ) func DiscoverGateway() (ip net.IP, err error) { routeCmd := exec.Command("netstat", "-rn") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseBSDSolarisNetstat(output) } gateway-1.0.4/gateway_linux.go000066400000000000000000000012021272356326600163730ustar00rootroot00000000000000package gateway import ( "net" "os/exec" ) func DiscoverGateway() (ip net.IP, err error) { ip, err = discoverGatewayUsingRoute() if err != nil { ip, err = discoverGatewayUsingIp() } return } func discoverGatewayUsingIp() (net.IP, error) { routeCmd := exec.Command("/usr/bin/ip", "route", "show") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseLinuxIPRoute(output) } func discoverGatewayUsingRoute() (net.IP, error) { routeCmd := exec.Command("/usr/bin/route", "-n") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseLinuxRoute(output) } gateway-1.0.4/gateway_solaris.go000066400000000000000000000004051272356326600167140ustar00rootroot00000000000000package gateway import ( "net" "os/exec" ) func DiscoverGateway() (ip net.IP, err error) { routeCmd := exec.Command("netstat", "-rn") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseBSDSolarisNetstat(output) } gateway-1.0.4/gateway_test.go000066400000000000000000000172221272356326600162240ustar00rootroot00000000000000package gateway import ( "net" "testing" ) type testcase struct { output []byte ok bool gateway string } func TestParseWindowsRoutePrint(t *testing.T) { correctData := []byte(` IPv4 Route Table =========================================================================== Active Routes: Network Destination Netmask Gateway Interface Metric 0.0.0.0 0.0.0.0 10.88.88.2 10.88.88.149 10 =========================================================================== Persistent Routes: `) randomData := []byte(` Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation `) noRoute := []byte(` IPv4 Route Table =========================================================================== Active Routes: `) badRoute1 := []byte(` IPv4 Route Table =========================================================================== Active Routes: =========================================================================== Persistent Routes: `) badRoute2 := []byte(` IPv4 Route Table =========================================================================== Active Routes: Network Destination Netmask Gateway Interface Metric 0.0.0.0 0.0.0.0 foo 10.88.88.149 10 =========================================================================== Persistent Routes: `) testcases := []testcase{ {correctData, true, "10.88.88.2"}, {randomData, false, ""}, {noRoute, false, ""}, {badRoute1, false, ""}, {badRoute2, false, ""}, } test(t, testcases, parseWindowsRoutePrint) } func TestParseLinuxIPRoutePrint(t *testing.T) { correctData := []byte(` 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 `) randomData := []byte(` test Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation `) noRoute := []byte(` 192.168.178.0/24 dev wlp3s0 proto kernel scope link src 192.168.178.76 metric 303 `) badRoute := []byte(` default via foo dev wlp3s0 metric 303 192.168.178.0/24 dev wlp3s0 proto kernel scope link src 192.168.178.76 metric 303 `) testcases := []testcase{ {correctData, true, "192.168.178.1"}, {randomData, false, ""}, {noRoute, false, ""}, {badRoute, false, ""}, } test(t, testcases, parseLinuxIPRoute) } func TestParseLinuxRoutePrint(t *testing.T) { correctData := []byte(` 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 `) randomData := []byte(` test Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation `) noRoute := []byte(` Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface `) badRoute := []byte(` Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 foo 0.0.0.0 UG 0 0 0 eth0 `) testcases := []testcase{ {correctData, true, "192.168.1.1"}, {randomData, false, ""}, {noRoute, false, ""}, {badRoute, false, ""}, } test(t, testcases, parseLinuxRoute) } func TestParseDarwinRouteGet(t *testing.T) { correctData := []byte(` route to: 0.0.0.0 destination: default mask: default gateway: 172.16.32.1 interface: en0 flags: recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 0 `) randomData := []byte(` test Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation `) noRoute := []byte(` route to: 0.0.0.0 destination: default mask: default `) badRoute := []byte(` route to: 0.0.0.0 destination: default mask: default gateway: foo interface: en0 flags: recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 0 `) testcases := []testcase{ {correctData, true, "172.16.32.1"}, {randomData, false, ""}, {noRoute, false, ""}, {badRoute, false, ""}, } test(t, testcases, parseDarwinRouteGet) } func TestParseBSDSolarisNetstat(t *testing.T) { correctDataFreeBSD := []byte(` Routing tables Internet: Destination Gateway Flags Netif Expire default 10.88.88.2 UGS em0 10.88.88.0/24 link#1 U em0 10.88.88.148 link#1 UHS lo0 127.0.0.1 link#2 UH lo0 Internet6: Destination Gateway Flags Netif Expire ::/96 ::1 UGRS lo0 ::1 link#2 UH lo0 ::ffff:0.0.0.0/96 ::1 UGRS lo0 fe80::/10 ::1 UGRS lo0 `) correctDataSolaris := []byte(` Routing Table: IPv4 Destination Gateway Flags Ref Use Interface -------------------- -------------------- ----- ----- ---------- --------- default 172.16.32.1 UG 2 76419 net0 127.0.0.1 127.0.0.1 UH 2 36 lo0 172.16.32.0 172.16.32.17 U 4 8100 net0 Routing Table: IPv6 Destination/Mask Gateway Flags Ref Use If --------------------------- --------------------------- ----- --- ------- ----- ::1 ::1 UH 3 75382 lo0 2001:470:deeb:32::/64 2001:470:deeb:32::17 U 3 2744 net0 fe80::/10 fe80::6082:52ff:fedc:7df0 U 3 8430 net0 `) randomData := []byte(` Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation `) noRoute := []byte(` Internet: Destination Gateway Flags Netif Expire 10.88.88.0/24 link#1 U em0 10.88.88.148 link#1 UHS lo0 127.0.0.1 link#2 UH lo0 `) badRoute := []byte(` Internet: Destination Gateway Flags Netif Expire default foo UGS em0 10.88.88.0/24 link#1 U em0 10.88.88.148 link#1 UHS lo0 127.0.0.1 link#2 UH lo0 `) testcases := []testcase{ {correctDataFreeBSD, true, "10.88.88.2"}, {correctDataSolaris, true, "172.16.32.1"}, {randomData, false, ""}, {noRoute, false, ""}, {badRoute, false, ""}, } test(t, testcases, parseBSDSolarisNetstat) } func test(t *testing.T, testcases []testcase, fn func([]byte) (net.IP, error)) { for i, tc := range testcases { net, err := fn(tc.output) if tc.ok { if err != nil { t.Errorf("Unexpected error in test #%d: %v", i, err) } if net.String() != tc.gateway { t.Errorf("Unexpected gateway address %v != %s", net, tc.gateway) } } else if err == nil { t.Errorf("Unexpected nil error in test #%d", i) } } } gateway-1.0.4/gateway_unimplemented.go000066400000000000000000000003621272356326600201100ustar00rootroot00000000000000// +build !darwin,!linux,!windows,!solaris,!freebsd package gateway import ( "fmt" "net" "runtime" ) func DiscoverGateway() (ip net.IP, err error) { err = fmt.Errorf("DiscoverGateway not implemented for OS %s", runtime.GOOS) return } gateway-1.0.4/gateway_windows.go000066400000000000000000000004201272356326600167270ustar00rootroot00000000000000package gateway import ( "net" "os/exec" ) func DiscoverGateway() (ip net.IP, err error) { routeCmd := exec.Command("route", "print", "0.0.0.0") output, err := routeCmd.CombinedOutput() if err != nil { return nil, err } return parseWindowsRoutePrint(output) }