net/interfaces: add State.PAC field, populate it on Windows

Not used for anything yet (except logging), but populate the current
proxy autoconfig PAC URL in Interfaces.State.

A future change will do things based on it.
This commit is contained in:
Brad Fitzpatrick 2020-10-01 15:33:37 -07:00
parent b5a3850d29
commit 8051ecff55
2 changed files with 42 additions and 0 deletions

View File

@ -177,6 +177,9 @@ type State struct {
// HTTPProxy is the HTTP proxy to use. // HTTPProxy is the HTTP proxy to use.
HTTPProxy string HTTPProxy string
// PAC is the URL to the Proxy Autoconfig URL, if applicable.
PAC string
} }
func (s *State) Equal(s2 *State) bool { func (s *State) Equal(s2 *State) bool {
@ -197,6 +200,9 @@ func (s *State) RemoveTailscaleInterfaces() {
} }
} }
// getPAC, if non-nil, returns the current PAC file URL.
var getPAC func() string
// GetState returns the state of all the current machine's network interfaces. // GetState returns the state of all the current machine's network interfaces.
// //
// It does not set the returned State.IsExpensive. The caller can populate that. // It does not set the returned State.IsExpensive. The caller can populate that.
@ -222,6 +228,9 @@ func GetState() (*State, error) {
if u, err := tshttpproxy.ProxyFromEnvironment(req); err == nil && u != nil { if u, err := tshttpproxy.ProxyFromEnvironment(req); err == nil && u != nil {
s.HTTPProxy = u.String() s.HTTPProxy = u.String()
} }
if getPAC != nil {
s.PAC = getPAC()
}
return s, nil return s, nil
} }

View File

@ -6,11 +6,14 @@ package interfaces
import ( import (
"fmt" "fmt"
"log"
"os/exec" "os/exec"
"syscall" "syscall"
"unsafe"
"github.com/tailscale/winipcfg-go" "github.com/tailscale/winipcfg-go"
"go4.org/mem" "go4.org/mem"
"golang.org/x/sys/windows"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/tsconst" "tailscale.com/tsconst"
"tailscale.com/util/lineread" "tailscale.com/util/lineread"
@ -18,6 +21,7 @@ import (
func init() { func init() {
likelyHomeRouterIP = likelyHomeRouterIPWindows likelyHomeRouterIP = likelyHomeRouterIPWindows
getPAC = getPACWindows
} }
/* /*
@ -148,3 +152,32 @@ func DefaultRouteInterface() (string, error) {
} }
return fmt.Sprintf("%s (%s)", iface.FriendlyName, iface.Description), nil return fmt.Sprintf("%s (%s)", iface.FriendlyName, iface.Description), nil
} }
var (
winHTTP = windows.NewLazySystemDLL("winhttp.dll")
detectAutoProxyConfigURL = winHTTP.NewProc("WinHttpDetectAutoProxyConfigUrl")
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
globalFree = kernel32.NewProc("GlobalFree")
)
const (
winHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001
winHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002
)
func getPACWindows() string {
var res *uint16
r, _, err := detectAutoProxyConfigURL.Call(
winHTTP_AUTO_DETECT_TYPE_DHCP|winHTTP_AUTO_DETECT_TYPE_DNS_A,
uintptr(unsafe.Pointer(&res)),
)
var got string
if res != nil {
got = windows.UTF16PtrToString(res)
globalFree.Call(uintptr(unsafe.Pointer(res)))
} else {
log.Printf("getPACWindows: r=%v, err=%#v", r, err)
}
return got
}