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.
reviewable/pr802/r3
Brad Fitzpatrick 4 years ago
parent b5a3850d29
commit 8051ecff55

@ -177,6 +177,9 @@ type State struct {
// HTTPProxy is the HTTP proxy to use.
HTTPProxy string
// PAC is the URL to the Proxy Autoconfig URL, if applicable.
PAC string
}
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.
//
// 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 {
s.HTTPProxy = u.String()
}
if getPAC != nil {
s.PAC = getPAC()
}
return s, nil
}

@ -6,11 +6,14 @@ package interfaces
import (
"fmt"
"log"
"os/exec"
"syscall"
"unsafe"
"github.com/tailscale/winipcfg-go"
"go4.org/mem"
"golang.org/x/sys/windows"
"inet.af/netaddr"
"tailscale.com/tsconst"
"tailscale.com/util/lineread"
@ -18,6 +21,7 @@ import (
func init() {
likelyHomeRouterIP = likelyHomeRouterIPWindows
getPAC = getPACWindows
}
/*
@ -148,3 +152,32 @@ func DefaultRouteInterface() (string, error) {
}
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
}

Loading…
Cancel
Save