tailscale/net/interfaces/interfaces_windows.go

95 lines
2.6 KiB
Go
Raw Normal View History

// 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"
"syscall"
"github.com/tailscale/winipcfg-go"
"go4.org/mem"
"inet.af/netaddr"
"tailscale.com/tsconst"
"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")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
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()
}
// NonTailscaleMTUs returns a map of interface LUID to interface MTU,
// for all interfaces except Tailscale tunnels.
func NonTailscaleMTUs() (map[uint64]uint32, error) {
ifs, err := winipcfg.GetInterfaces()
if err != nil {
return nil, err
}
ret := map[uint64]uint32{}
for _, iface := range ifs {
if iface.Description == tsconst.WintunInterfaceDesc {
continue
}
ret[iface.Luid] = iface.Mtu
}
return ret, nil
}