For discovering where we might direct NAT-PMP/PCP/UPnP queries at in the future.main
parent
c3c607e78a
commit
32156330a8
@ -0,0 +1,66 @@ |
||||
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interfaces |
||||
|
||||
import ( |
||||
"os/exec" |
||||
|
||||
"go4.org/mem" |
||||
"inet.af/netaddr" |
||||
"tailscale.com/util/lineread" |
||||
) |
||||
|
||||
func init() { |
||||
likelyHomeRouterIP = likelyHomeRouterIPDarwin |
||||
} |
||||
|
||||
/* |
||||
Parse out 10.0.0.1 from: |
||||
|
||||
$ netstat -r -n -f inet |
||||
Routing tables |
||||
|
||||
Internet: |
||||
Destination Gateway Flags Netif Expire |
||||
default 10.0.0.1 UGSc en0 |
||||
default link#14 UCSI utun2 |
||||
10/16 link#4 UCS en0 ! |
||||
10.0.0.1/32 link#4 UCS en0 ! |
||||
... |
||||
|
||||
*/ |
||||
func likelyHomeRouterIPDarwin() (ret netaddr.IP, ok bool) { |
||||
cmd := exec.Command("/usr/sbin/netstat", "-r", "-n", "-f", "inet") |
||||
stdout, err := cmd.StdoutPipe() |
||||
if err != nil { |
||||
return |
||||
} |
||||
if err := cmd.Start(); err != nil { |
||||
return |
||||
} |
||||
defer cmd.Wait() |
||||
|
||||
var f []mem.RO |
||||
lineread.Reader(stdout, func(lineb []byte) error { |
||||
line := mem.B(lineb) |
||||
if !mem.Contains(line, mem.S("default")) { |
||||
return nil |
||||
} |
||||
f = mem.AppendFields(f[:0], line) |
||||
if len(f) < 3 || !f[0].EqualString("default") { |
||||
return nil |
||||
} |
||||
ipm, flagsm := f[1], f[2] |
||||
if !mem.Contains(flagsm, mem.S("G")) { |
||||
return nil |
||||
} |
||||
ip, err := netaddr.ParseIP(string(mem.Append(nil, ipm))) |
||||
if err == nil && isPrivateIP(ip) { |
||||
ret = ip |
||||
} |
||||
return nil |
||||
}) |
||||
return ret, !ret.IsZero() |
||||
} |
||||
@ -0,0 +1,59 @@ |
||||
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interfaces |
||||
|
||||
import ( |
||||
"go4.org/mem" |
||||
"inet.af/netaddr" |
||||
"tailscale.com/util/lineread" |
||||
) |
||||
|
||||
func init() { |
||||
likelyHomeRouterIP = likelyHomeRouterIPLinux |
||||
} |
||||
|
||||
/* |
||||
Parse 10.0.0.1 out of: |
||||
|
||||
$ cat /proc/net/route |
||||
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT |
||||
ens18 00000000 0100000A 0003 0 0 0 00000000 0 0 0 |
||||
ens18 0000000A 00000000 0001 0 0 0 0000FFFF 0 0 0 |
||||
*/ |
||||
func likelyHomeRouterIPLinux() (ret netaddr.IP, ok bool) { |
||||
lineNum := 0 |
||||
var f []mem.RO |
||||
lineread.File("/proc/net/route", func(line []byte) error { |
||||
lineNum++ |
||||
if lineNum == 1 { |
||||
// Skip header line.
|
||||
return nil |
||||
} |
||||
f = mem.AppendFields(f[:0], mem.B(line)) |
||||
if len(f) < 4 { |
||||
return nil |
||||
} |
||||
gwHex, flagsHex := f[2], f[3] |
||||
flags, err := mem.ParseUint(flagsHex, 16, 16) |
||||
if err != nil { |
||||
return nil // ignore error, skip line and keep going
|
||||
} |
||||
const RTF_UP = 0x0001 |
||||
const RTF_GATEWAY = 0x0002 |
||||
if flags&(RTF_UP|RTF_GATEWAY) != RTF_UP|RTF_GATEWAY { |
||||
return nil |
||||
} |
||||
ipu32, err := mem.ParseUint(gwHex, 16, 32) |
||||
if err != nil { |
||||
return nil // ignore error, skip line and keep going
|
||||
} |
||||
ip := netaddr.IPv4(byte(ipu32), byte(ipu32>>8), byte(ipu32>>16), byte(ipu32>>24)) |
||||
if isPrivateIP(ip) { |
||||
ret = ip |
||||
} |
||||
return nil |
||||
}) |
||||
return ret, !ret.IsZero() |
||||
} |
||||
@ -0,0 +1,71 @@ |
||||
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interfaces |
||||
|
||||
import ( |
||||
"os/exec" |
||||
|
||||
"go4.org/mem" |
||||
"inet.af/netaddr" |
||||
"tailscale.com/util/lineread" |
||||
) |
||||
|
||||
func init() { |
||||
likelyHomeRouterIP = likelyHomeRouterIPWindows |
||||
} |
||||
|
||||
/* |
||||
Parse out 10.0.0.1 from: |
||||
|
||||
Z:\>route print -4 |
||||
=========================================================================== |
||||
Interface List |
||||
15...aa 15 48 ff 1c 72 ......Red Hat VirtIO Ethernet Adapter |
||||
5...........................Tailscale Tunnel |
||||
1...........................Software Loopback Interface 1 |
||||
=========================================================================== |
||||
|
||||
IPv4 Route Table |
||||
=========================================================================== |
||||
Active Routes: |
||||
Network Destination Netmask Gateway Interface Metric |
||||
0.0.0.0 0.0.0.0 10.0.0.1 10.0.28.63 5 |
||||
10.0.0.0 255.255.0.0 On-link 10.0.28.63 261 |
||||
10.0.28.63 255.255.255.255 On-link 10.0.28.63 261 |
||||
10.0.42.0 255.255.255.0 100.103.42.106 100.103.42.106 5 |
||||
10.0.255.255 255.255.255.255 On-link 10.0.28.63 261 |
||||
34.193.248.174 255.255.255.255 100.103.42.106 100.103.42.106 5 |
||||
|
||||
*/ |
||||
func likelyHomeRouterIPWindows() (ret netaddr.IP, ok bool) { |
||||
cmd := exec.Command("route", "print", "-4") |
||||
stdout, err := cmd.StdoutPipe() |
||||
if err != nil { |
||||
return |
||||
} |
||||
if err := cmd.Start(); err != nil { |
||||
return |
||||
} |
||||
defer cmd.Wait() |
||||
|
||||
var f []mem.RO |
||||
lineread.Reader(stdout, func(lineb []byte) error { |
||||
line := mem.B(lineb) |
||||
if !mem.Contains(line, mem.S("0.0.0.0")) { |
||||
return nil |
||||
} |
||||
f = mem.AppendFields(f[:0], line) |
||||
if len(f) < 3 || !f[0].EqualString("0.0.0.0") || !f[1].EqualString("0.0.0.0") { |
||||
return nil |
||||
} |
||||
ipm := f[2] |
||||
ip, err := netaddr.ParseIP(string(mem.Append(nil, ipm))) |
||||
if err == nil && isPrivateIP(ip) { |
||||
ret = ip |
||||
} |
||||
return nil |
||||
}) |
||||
return ret, !ret.IsZero() |
||||
} |
||||
Loading…
Reference in new issue