|
|
@@ -0,0 +1,129 @@
|
|
|
+package 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
|
|
|
+}
|