Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

17
vendor/golang.zx2c4.com/wintun/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
vendor/golang.zx2c4.com/wintun/README.md generated vendored Normal file
View File

@@ -0,0 +1,9 @@
## wintun-go
This contains bindings to use [Wintun](https://www.wintun.net) from Go.
```go
import "golang.zx2c4.com/wintun"
```
- [Documentation](https://pkg.go.dev/golang.zx2c4.com/wintun)

130
vendor/golang.zx2c4.com/wintun/dll.go generated vendored Normal file
View File

@@ -0,0 +1,130 @@
//go:build windows
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
*/
package wintun
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
)
func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
return &lazyDLL{Name: name, onLoad: onLoad}
}
func (d *lazyDLL) NewProc(name string) *lazyProc {
return &lazyProc{dll: d, Name: name}
}
type lazyProc struct {
Name string
mu sync.Mutex
dll *lazyDLL
addr uintptr
}
func (p *lazyProc) Find() error {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
if p.addr != 0 {
return nil
}
err := p.dll.Load()
if err != nil {
return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err)
}
addr, err := p.nameToAddr()
if err != nil {
return fmt.Errorf("Error getting %v address: %w", p.Name, err)
}
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
return nil
}
func (p *lazyProc) Addr() uintptr {
err := p.Find()
if err != nil {
panic(err)
}
return p.addr
}
type lazyDLL struct {
Name string
mu sync.Mutex
module windows.Handle
onLoad func(d *lazyDLL)
}
func (d *lazyDLL) Load() error {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
return nil
}
d.mu.Lock()
defer d.mu.Unlock()
if d.module != 0 {
return nil
}
const (
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
)
module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
if err != nil {
return fmt.Errorf("Unable to load library: %w", err)
}
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
if d.onLoad != nil {
d.onLoad(d)
}
return nil
}
func (p *lazyProc) nameToAddr() (uintptr, error) {
return windows.GetProcAddress(p.dll.module, p.Name)
}
// Version returns the version of the Wintun DLL.
func Version() string {
if modwintun.Load() != nil {
return "unknown"
}
resInfo, err := windows.FindResource(modwintun.module, windows.ResourceID(1), windows.RT_VERSION)
if err != nil {
return "unknown"
}
data, err := windows.LoadResourceData(modwintun.module, resInfo)
if err != nil {
return "unknown"
}
var fixedInfo *windows.VS_FIXEDFILEINFO
fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
if err != nil {
return "unknown"
}
version := fmt.Sprintf("%d.%d", (fixedInfo.FileVersionMS>>16)&0xff, (fixedInfo.FileVersionMS>>0)&0xff)
if nextNibble := (fixedInfo.FileVersionLS >> 16) & 0xff; nextNibble != 0 {
version += fmt.Sprintf(".%d", nextNibble)
}
if nextNibble := (fixedInfo.FileVersionLS >> 0) & 0xff; nextNibble != 0 {
version += fmt.Sprintf(".%d", nextNibble)
}
return version
}

92
vendor/golang.zx2c4.com/wintun/session.go generated vendored Normal file
View File

@@ -0,0 +1,92 @@
//go:build windows
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
*/
package wintun
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type Session struct {
handle uintptr
}
const (
PacketSizeMax = 0xffff // Maximum packet size
RingCapacityMin = 0x20000 // Minimum ring capacity (128 kiB)
RingCapacityMax = 0x4000000 // Maximum ring capacity (64 MiB)
)
// Packet with data
type Packet struct {
Next *Packet // Pointer to next packet in queue
Size uint32 // Size of packet (max WINTUN_MAX_IP_PACKET_SIZE)
Data *[PacketSizeMax]byte // Pointer to layer 3 IPv4 or IPv6 packet
}
var (
procWintunAllocateSendPacket = modwintun.NewProc("WintunAllocateSendPacket")
procWintunEndSession = modwintun.NewProc("WintunEndSession")
procWintunGetReadWaitEvent = modwintun.NewProc("WintunGetReadWaitEvent")
procWintunReceivePacket = modwintun.NewProc("WintunReceivePacket")
procWintunReleaseReceivePacket = modwintun.NewProc("WintunReleaseReceivePacket")
procWintunSendPacket = modwintun.NewProc("WintunSendPacket")
procWintunStartSession = modwintun.NewProc("WintunStartSession")
)
func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error) {
r0, _, e1 := syscall.Syscall(procWintunStartSession.Addr(), 2, uintptr(wintun.handle), uintptr(capacity), 0)
if r0 == 0 {
err = e1
} else {
session = Session{r0}
}
return
}
func (session Session) End() {
syscall.Syscall(procWintunEndSession.Addr(), 1, session.handle, 0, 0)
session.handle = 0
}
func (session Session) ReadWaitEvent() (handle windows.Handle) {
r0, _, _ := syscall.Syscall(procWintunGetReadWaitEvent.Addr(), 1, session.handle, 0, 0)
handle = windows.Handle(r0)
return
}
func (session Session) ReceivePacket() (packet []byte, err error) {
var packetSize uint32
r0, _, e1 := syscall.Syscall(procWintunReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packetSize)), 0)
if r0 == 0 {
err = e1
return
}
packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
return
}
func (session Session) ReleaseReceivePacket(packet []byte) {
syscall.Syscall(procWintunReleaseReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
}
func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err error) {
r0, _, e1 := syscall.Syscall(procWintunAllocateSendPacket.Addr(), 2, session.handle, uintptr(packetSize), 0)
if r0 == 0 {
err = e1
return
}
packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize)
return
}
func (session Session) SendPacket(packet []byte) {
syscall.Syscall(procWintunSendPacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0)
}

167
vendor/golang.zx2c4.com/wintun/wintun.go generated vendored Normal file
View File

@@ -0,0 +1,167 @@
//go:build windows
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
*/
package wintun
import (
"log"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type loggerLevel int
const (
logInfo loggerLevel = iota
logWarn
logErr
)
const AdapterNameMax = 128
type Adapter struct {
handle uintptr
}
var (
modwintun = newLazyDLL("wintun.dll", setupLogger)
procWintunCreateAdapter = modwintun.NewProc("WintunCreateAdapter")
procWintunOpenAdapter = modwintun.NewProc("WintunOpenAdapter")
procWintunCloseAdapter = modwintun.NewProc("WintunCloseAdapter")
procWintunDeleteDriver = modwintun.NewProc("WintunDeleteDriver")
procWintunGetAdapterLUID = modwintun.NewProc("WintunGetAdapterLUID")
procWintunGetRunningDriverVersion = modwintun.NewProc("WintunGetRunningDriverVersion")
)
type TimestampedWriter interface {
WriteWithTimestamp(p []byte, ts int64) (n int, err error)
}
func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int {
if tw, ok := log.Default().Writer().(TimestampedWriter); ok {
tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100)
} else {
log.Println(windows.UTF16PtrToString(msg))
}
return 0
}
func setupLogger(dll *lazyDLL) {
var callback uintptr
if runtime.GOARCH == "386" {
callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "arm" {
callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
callback = windows.NewCallback(logMessage)
}
syscall.Syscall(dll.NewProc("WintunSetLogger").Addr(), 1, callback, 0, 0)
}
func closeAdapter(wintun *Adapter) {
syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0)
}
// CreateAdapter creates a Wintun adapter. name is the cosmetic name of the adapter.
// tunnelType represents the type of adapter and should be "Wintun". requestedGUID is
// the GUID of the created network adapter, which then influences NLA generation
// deterministically. If it is set to nil, the GUID is chosen by the system at random,
// and hence a new NLA entry is created for each new adapter.
func CreateAdapter(name string, tunnelType string, requestedGUID *windows.GUID) (wintun *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
var tunnelType16 *uint16
tunnelType16, err = windows.UTF16PtrFromString(tunnelType)
if err != nil {
return
}
if err := procWintunCreateAdapter.Find(); err != nil {
return nil, err
}
r0, _, e1 := syscall.Syscall(procWintunCreateAdapter.Addr(), 3, uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID)))
if r0 == 0 {
err = e1
return
}
wintun = &Adapter{handle: r0}
runtime.SetFinalizer(wintun, closeAdapter)
return
}
// OpenAdapter opens an existing Wintun adapter by name.
func OpenAdapter(name string) (wintun *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
if err := procWintunOpenAdapter.Find(); err != nil {
return nil, err
}
r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 1, uintptr(unsafe.Pointer(name16)), 0, 0)
if r0 == 0 {
err = e1
return
}
wintun = &Adapter{handle: r0}
runtime.SetFinalizer(wintun, closeAdapter)
return
}
// Close closes a Wintun adapter.
func (wintun *Adapter) Close() (err error) {
if err := procWintunCloseAdapter.Find(); err != nil {
return err
}
runtime.SetFinalizer(wintun, nil)
r1, _, e1 := syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0)
if r1 == 0 {
err = e1
}
return
}
// Uninstall removes the driver from the system if no drivers are currently in use.
func Uninstall() (err error) {
if err := procWintunDeleteDriver.Find(); err != nil {
return err
}
r1, _, e1 := syscall.Syscall(procWintunDeleteDriver.Addr(), 0, 0, 0, 0)
if r1 == 0 {
err = e1
}
return
}
// RunningVersion returns the version of the loaded driver.
func RunningVersion() (version uint32, err error) {
if err := procWintunGetRunningDriverVersion.Find(); err != nil {
return 0, err
}
r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0)
version = uint32(r0)
if version == 0 {
err = e1
}
return
}
// LUID returns the LUID of the adapter.
func (wintun *Adapter) LUID() (luid uint64) {
syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0)
return
}

19
vendor/golang.zx2c4.com/wireguard/windows/COPYING generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,88 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"sync"
"golang.org/x/sys/windows"
)
// InterfaceChangeCallback structure allows interface change callback handling.
type InterfaceChangeCallback struct {
cb func(notificationType MibNotificationType, iface *MibIPInterfaceRow)
wait sync.WaitGroup
}
var (
interfaceChangeAddRemoveMutex = sync.Mutex{}
interfaceChangeMutex = sync.Mutex{}
interfaceChangeCallbacks = make(map[*InterfaceChangeCallback]bool)
interfaceChangeHandle = windows.Handle(0)
)
// RegisterInterfaceChangeCallback registers a new InterfaceChangeCallback. If this particular callback is already
// registered, the function will silently return. Returned InterfaceChangeCallback.Unregister method should be used
// to unregister.
func RegisterInterfaceChangeCallback(callback func(notificationType MibNotificationType, iface *MibIPInterfaceRow)) (*InterfaceChangeCallback, error) {
s := &InterfaceChangeCallback{cb: callback}
interfaceChangeAddRemoveMutex.Lock()
defer interfaceChangeAddRemoveMutex.Unlock()
interfaceChangeMutex.Lock()
defer interfaceChangeMutex.Unlock()
interfaceChangeCallbacks[s] = true
if interfaceChangeHandle == 0 {
err := notifyIPInterfaceChange(windows.AF_UNSPEC, windows.NewCallback(interfaceChanged), 0, false, &interfaceChangeHandle)
if err != nil {
delete(interfaceChangeCallbacks, s)
interfaceChangeHandle = 0
return nil, err
}
}
return s, nil
}
// Unregister unregisters the callback.
func (callback *InterfaceChangeCallback) Unregister() error {
interfaceChangeAddRemoveMutex.Lock()
defer interfaceChangeAddRemoveMutex.Unlock()
interfaceChangeMutex.Lock()
delete(interfaceChangeCallbacks, callback)
removeIt := len(interfaceChangeCallbacks) == 0 && interfaceChangeHandle != 0
interfaceChangeMutex.Unlock()
callback.wait.Wait()
if removeIt {
err := cancelMibChangeNotify2(interfaceChangeHandle)
if err != nil {
return err
}
interfaceChangeHandle = 0
}
return nil
}
func interfaceChanged(callerContext uintptr, row *MibIPInterfaceRow, notificationType MibNotificationType) uintptr {
rowCopy := *row
interfaceChangeMutex.Lock()
for cb := range interfaceChangeCallbacks {
cb.wait.Add(1)
go func(cb *InterfaceChangeCallback) {
cb.cb(notificationType, &rowCopy)
cb.wait.Done()
}(cb)
}
interfaceChangeMutex.Unlock()
return 0
}

View File

@@ -0,0 +1,387 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"errors"
"net/netip"
"strings"
"golang.org/x/sys/windows"
)
// LUID represents a network interface.
type LUID uint64
// IPInterface method retrieves IP information for the specified interface on the local computer.
func (luid LUID) IPInterface(family AddressFamily) (*MibIPInterfaceRow, error) {
row := &MibIPInterfaceRow{}
row.Init()
row.InterfaceLUID = luid
row.Family = family
err := row.get()
if err != nil {
return nil, err
}
return row, nil
}
// Interface method retrieves information for the specified adapter on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getifentry2
func (luid LUID) Interface() (*MibIfRow2, error) {
row := &MibIfRow2{}
row.InterfaceLUID = luid
err := row.get()
if err != nil {
return nil, err
}
return row, nil
}
// GUID method converts a locally unique identifier (LUID) for a network interface to a globally unique identifier (GUID) for the interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceluidtoguid
func (luid LUID) GUID() (*windows.GUID, error) {
guid := &windows.GUID{}
err := convertInterfaceLUIDToGUID(&luid, guid)
if err != nil {
return nil, err
}
return guid, nil
}
// LUIDFromGUID function converts a globally unique identifier (GUID) for a network interface to the locally unique identifier (LUID) for the interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceguidtoluid
func LUIDFromGUID(guid *windows.GUID) (LUID, error) {
var luid LUID
err := convertInterfaceGUIDToLUID(guid, &luid)
if err != nil {
return 0, err
}
return luid, nil
}
// LUIDFromIndex function converts a local index for a network interface to the locally unique identifier (LUID) for the interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-convertinterfaceindextoluid
func LUIDFromIndex(index uint32) (LUID, error) {
var luid LUID
err := convertInterfaceIndexToLUID(index, &luid)
if err != nil {
return 0, err
}
return luid, nil
}
// IPAddress method returns MibUnicastIPAddressRow struct that matches to provided 'ip' argument. Corresponds to GetUnicastIpAddressEntry
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry)
func (luid LUID) IPAddress(addr netip.Addr) (*MibUnicastIPAddressRow, error) {
row := &MibUnicastIPAddressRow{InterfaceLUID: luid}
err := row.Address.SetAddr(addr)
if err != nil {
return nil, err
}
err = row.get()
if err != nil {
return nil, err
}
return row, nil
}
// AddIPAddress method adds new unicast IP address to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
func (luid LUID) AddIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
row.DadState = DadStatePreferred
row.ValidLifetime = 0xffffffff
row.PreferredLifetime = 0xffffffff
err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
row.OnLinkPrefixLength = uint8(address.Bits())
return row.Create()
}
// AddIPAddresses method adds multiple new unicast IP addresses to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
func (luid LUID) AddIPAddresses(addresses []netip.Prefix) error {
for i := range addresses {
err := luid.AddIPAddress(addresses[i])
if err != nil {
return err
}
}
return nil
}
// SetIPAddresses method sets new unicast IP addresses to the interface.
func (luid LUID) SetIPAddresses(addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(windows.AF_UNSPEC)
if err != nil {
return err
}
return luid.AddIPAddresses(addresses)
}
// SetIPAddressesForFamily method sets new unicast IP addresses for a specific family to the interface.
func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(family)
if err != nil {
return err
}
for i := range addresses {
if !addresses[i].Addr().Is4() && family == windows.AF_INET {
continue
} else if !addresses[i].Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddIPAddress(addresses[i])
if err != nil {
return err
}
}
return nil
}
// DeleteIPAddress method deletes interface's unicast IP address. Corresponds to DeleteUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry).
func (luid LUID) DeleteIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
// Note: OnLinkPrefixLength member is ignored by DeleteUnicastIpAddressEntry().
row.OnLinkPrefixLength = uint8(address.Bits())
return row.Delete()
}
// FlushIPAddresses method deletes all interface's unicast IP addresses.
func (luid LUID) FlushIPAddresses(family AddressFamily) error {
var tab *mibUnicastIPAddressTable
err := getUnicastIPAddressTable(family, &tab)
if err != nil {
return err
}
t := tab.get()
for i := range t {
if t[i].InterfaceLUID == luid {
t[i].Delete()
}
}
tab.free()
return nil
}
// Route method returns route determined with the input arguments. Corresponds to GetIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2).
// NOTE: If the corresponding route isn't found, the method will return error.
func (luid LUID) Route(destination netip.Prefix, nextHop netip.Addr) (*MibIPforwardRow2, error) {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
row.ValidLifetime = 0xffffffff
row.PreferredLifetime = 0xffffffff
err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return nil, err
}
err = row.NextHop.SetAddr(nextHop)
if err != nil {
return nil, err
}
err = row.get()
if err != nil {
return nil, err
}
return row, nil
}
// AddRoute method adds a route to the interface. Corresponds to CreateIpForwardEntry2 function, with added splitDefault feature.
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2)
func (luid LUID) AddRoute(destination netip.Prefix, nextHop netip.Addr, metric uint32) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
row.Metric = metric
return row.Create()
}
// AddRoutes method adds multiple routes to the interface.
func (luid LUID) AddRoutes(routesData []*RouteData) error {
for _, rd := range routesData {
err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric)
if err != nil {
return err
}
}
return nil
}
// SetRoutes method sets (flush than add) multiple routes to the interface.
func (luid LUID) SetRoutes(routesData []*RouteData) error {
err := luid.FlushRoutes(windows.AF_UNSPEC)
if err != nil {
return err
}
return luid.AddRoutes(routesData)
}
// SetRoutesForFamily method sets (flush than add) multiple routes for a specific family to the interface.
func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteData) error {
err := luid.FlushRoutes(family)
if err != nil {
return err
}
for _, rd := range routesData {
if !rd.Destination.Addr().Is4() && family == windows.AF_INET {
continue
} else if !rd.Destination.Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric)
if err != nil {
return err
}
}
return nil
}
// DeleteRoute method deletes a route that matches the criteria. Corresponds to DeleteIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2).
func (luid LUID) DeleteRoute(destination netip.Prefix, nextHop netip.Addr) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
err = row.get()
if err != nil {
return err
}
return row.Delete()
}
// FlushRoutes method deletes all interface's routes.
// It continues on failures, and returns the last error afterwards.
func (luid LUID) FlushRoutes(family AddressFamily) error {
var tab *mibIPforwardTable2
err := getIPForwardTable2(family, &tab)
if err != nil {
return err
}
t := tab.get()
for i := range t {
if t[i].InterfaceLUID == luid {
err2 := t[i].Delete()
if err2 != nil {
err = err2
}
}
}
tab.free()
return err
}
// DNS method returns all DNS server addresses associated with the adapter.
func (luid LUID) DNS() ([]netip.Addr, error) {
addresses, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault)
if err != nil {
return nil, err
}
r := make([]netip.Addr, 0, len(addresses))
for _, addr := range addresses {
if addr.LUID == luid {
for dns := addr.FirstDNSServerAddress; dns != nil; dns = dns.Next {
if ip := dns.Address.IP(); ip != nil {
if a, ok := netip.AddrFromSlice(ip); ok {
r = append(r, a)
}
} else {
return nil, windows.ERROR_INVALID_PARAMETER
}
}
}
}
return r, nil
}
// SetDNS method clears previous and associates new DNS servers and search domains with the adapter for a specific family.
func (luid LUID) SetDNS(family AddressFamily, servers []netip.Addr, domains []string) error {
if family != windows.AF_INET && family != windows.AF_INET6 {
return windows.ERROR_PROTOCOL_UNREACHABLE
}
var filteredServers []string
for _, server := range servers {
if (server.Is4() && family == windows.AF_INET) || (server.Is6() && family == windows.AF_INET6) {
filteredServers = append(filteredServers, server.String())
}
}
servers16, err := windows.UTF16PtrFromString(strings.Join(filteredServers, ","))
if err != nil {
return err
}
domains16, err := windows.UTF16PtrFromString(strings.Join(domains, ","))
if err != nil {
return err
}
guid, err := luid.GUID()
if err != nil {
return err
}
dnsInterfaceSettings := &DnsInterfaceSettings{
Version: DnsInterfaceSettingsVersion1,
Flags: DnsInterfaceSettingsFlagNameserver | DnsInterfaceSettingsFlagSearchList,
NameServer: servers16,
SearchList: domains16,
}
if family == windows.AF_INET6 {
dnsInterfaceSettings.Flags |= DnsInterfaceSettingsFlagIPv6
}
// For >= Windows 10 1809
err = SetInterfaceDnsSettings(*guid, dnsInterfaceSettings)
if err == nil || !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
return err
}
// For < Windows 10 1809
err = luid.fallbackSetDNSForFamily(family, servers)
if err != nil {
return err
}
if len(domains) > 0 {
return luid.fallbackSetDNSDomain(domains[0])
} else {
return luid.fallbackSetDNSDomain("")
}
}
// FlushDNS method clears all DNS servers associated with the adapter.
func (luid LUID) FlushDNS(family AddressFamily) error {
return luid.SetDNS(family, nil, nil)
}

View File

@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zwinipcfg_windows.go winipcfg.go

View File

@@ -0,0 +1,108 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"bytes"
"errors"
"fmt"
"io"
"net/netip"
"os/exec"
"path/filepath"
"strings"
"syscall"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
func runNetsh(cmds []string) error {
system32, err := windows.GetSystemDirectory()
if err != nil {
return err
}
cmd := exec.Command(filepath.Join(system32, "netsh.exe"))
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
stdin, err := cmd.StdinPipe()
if err != nil {
return fmt.Errorf("runNetsh stdin pipe - %w", err)
}
go func() {
defer stdin.Close()
io.WriteString(stdin, strings.Join(append(cmds, "exit\r\n"), "\r\n"))
}()
output, err := cmd.CombinedOutput()
// Horrible kludges, sorry.
cleaned := bytes.ReplaceAll(output, []byte{'\r', '\n'}, []byte{'\n'})
cleaned = bytes.ReplaceAll(cleaned, []byte("netsh>"), []byte{})
cleaned = bytes.ReplaceAll(cleaned, []byte("There are no Domain Name Servers (DNS) configured on this computer."), []byte{})
cleaned = bytes.TrimSpace(cleaned)
if len(cleaned) != 0 && err == nil {
return fmt.Errorf("netsh: %#q", string(cleaned))
} else if err != nil {
return fmt.Errorf("netsh: %v: %#q", err, string(cleaned))
}
return nil
}
const (
netshCmdTemplateFlush4 = "interface ipv4 set dnsservers name=%d source=static address=none validate=no register=both"
netshCmdTemplateFlush6 = "interface ipv6 set dnsservers name=%d source=static address=none validate=no register=both"
netshCmdTemplateAdd4 = "interface ipv4 add dnsservers name=%d address=%s validate=no"
netshCmdTemplateAdd6 = "interface ipv6 add dnsservers name=%d address=%s validate=no"
)
func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error {
var templateFlush string
if family == windows.AF_INET {
templateFlush = netshCmdTemplateFlush4
} else if family == windows.AF_INET6 {
templateFlush = netshCmdTemplateFlush6
}
cmds := make([]string, 0, 1+len(dnses))
ipif, err := luid.IPInterface(family)
if err != nil {
return err
}
cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex))
for i := 0; i < len(dnses); i++ {
if dnses[i].Is4() && family == windows.AF_INET {
cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String()))
} else if dnses[i].Is6() && family == windows.AF_INET6 {
cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, dnses[i].String()))
}
}
return runNetsh(cmds)
}
func (luid LUID) fallbackSetDNSDomain(domain string) error {
guid, err := luid.GUID()
if err != nil {
return fmt.Errorf("Error converting luid to guid: %w", err)
}
key, err := registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%v", guid), registry.QUERY_VALUE)
if err != nil {
return fmt.Errorf("Error opening adapter-specific TCP/IP network registry key: %w", err)
}
paths, _, err := key.GetStringsValue("IpConfig")
key.Close()
if err != nil {
return fmt.Errorf("Error reading IpConfig registry key: %w", err)
}
if len(paths) == 0 {
return errors.New("No TCP/IP interfaces found on adapter")
}
key, err = registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), registry.SET_VALUE)
if err != nil {
return fmt.Errorf("Unable to open TCP/IP network registry key: %w", err)
}
err = key.SetStringValue("Domain", domain)
key.Close()
return err
}

View File

@@ -0,0 +1,88 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"sync"
"golang.org/x/sys/windows"
)
// RouteChangeCallback structure allows route change callback handling.
type RouteChangeCallback struct {
cb func(notificationType MibNotificationType, route *MibIPforwardRow2)
wait sync.WaitGroup
}
var (
routeChangeAddRemoveMutex = sync.Mutex{}
routeChangeMutex = sync.Mutex{}
routeChangeCallbacks = make(map[*RouteChangeCallback]bool)
routeChangeHandle = windows.Handle(0)
)
// RegisterRouteChangeCallback registers a new RouteChangeCallback. If this particular callback is already
// registered, the function will silently return. Returned RouteChangeCallback.Unregister method should be used
// to unregister.
func RegisterRouteChangeCallback(callback func(notificationType MibNotificationType, route *MibIPforwardRow2)) (*RouteChangeCallback, error) {
s := &RouteChangeCallback{cb: callback}
routeChangeAddRemoveMutex.Lock()
defer routeChangeAddRemoveMutex.Unlock()
routeChangeMutex.Lock()
defer routeChangeMutex.Unlock()
routeChangeCallbacks[s] = true
if routeChangeHandle == 0 {
err := notifyRouteChange2(windows.AF_UNSPEC, windows.NewCallback(routeChanged), 0, false, &routeChangeHandle)
if err != nil {
delete(routeChangeCallbacks, s)
routeChangeHandle = 0
return nil, err
}
}
return s, nil
}
// Unregister unregisters the callback.
func (callback *RouteChangeCallback) Unregister() error {
routeChangeAddRemoveMutex.Lock()
defer routeChangeAddRemoveMutex.Unlock()
routeChangeMutex.Lock()
delete(routeChangeCallbacks, callback)
removeIt := len(routeChangeCallbacks) == 0 && routeChangeHandle != 0
routeChangeMutex.Unlock()
callback.wait.Wait()
if removeIt {
err := cancelMibChangeNotify2(routeChangeHandle)
if err != nil {
return err
}
routeChangeHandle = 0
}
return nil
}
func routeChanged(callerContext uintptr, row *MibIPforwardRow2, notificationType MibNotificationType) uintptr {
rowCopy := *row
routeChangeMutex.Lock()
for cb := range routeChangeCallbacks {
cb.wait.Add(1)
go func(cb *RouteChangeCallback) {
cb.cb(notificationType, &rowCopy)
cb.wait.Done()
}(cb)
}
routeChangeMutex.Unlock()
return 0
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,232 @@
//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"golang.org/x/sys/windows"
)
// IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh
type IPAdapterWINSServerAddress struct {
Length uint32
_ uint32
Next *IPAdapterWINSServerAddress
Address windows.SocketAddress
_ [4]byte
}
// IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh
type IPAdapterGatewayAddress struct {
Length uint32
_ uint32
Next *IPAdapterGatewayAddress
Address windows.SocketAddress
_ [4]byte
}
// IPAdapterAddresses structure is the header node for a linked list of addresses for a particular adapter. This structure can simultaneously be used as part of a linked list of IP_ADAPTER_ADDRESSES structures.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh
// This is a modified and extended version of windows.IpAdapterAddresses.
type IPAdapterAddresses struct {
Length uint32
IfIndex uint32
Next *IPAdapterAddresses
adapterName *byte
FirstUnicastAddress *windows.IpAdapterUnicastAddress
FirstAnycastAddress *windows.IpAdapterAnycastAddress
FirstMulticastAddress *windows.IpAdapterMulticastAddress
FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter
dnsSuffix *uint16
description *uint16
friendlyName *uint16
physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte
physicalAddressLength uint32
Flags IPAAFlags
MTU uint32
IfType IfType
OperStatus IfOperStatus
IPv6IfIndex uint32
ZoneIndices [16]uint32
FirstPrefix *windows.IpAdapterPrefix
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
FirstWINSServerAddress *IPAdapterWINSServerAddress
FirstGatewayAddress *IPAdapterGatewayAddress
Ipv4Metric uint32
Ipv6Metric uint32
LUID LUID
DHCPv4Server windows.SocketAddress
CompartmentID uint32
NetworkGUID windows.GUID
ConnectionType NetIfConnectionType
TunnelType TunnelType
DHCPv6Server windows.SocketAddress
dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte
dhcpv6ClientDUIDLength uint32
DHCPv6IAID uint32
FirstDNSSuffix *IPAdapterDNSSuffix
_ [4]byte
}
// MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row
type MibIPInterfaceRow struct {
Family AddressFamily
_ [4]byte
InterfaceLUID LUID
InterfaceIndex uint32
MaxReassemblySize uint32
InterfaceIdentifier uint64
MinRouterAdvertisementInterval uint32
MaxRouterAdvertisementInterval uint32
AdvertisingEnabled bool
ForwardingEnabled bool
WeakHostSend bool
WeakHostReceive bool
UseAutomaticMetric bool
UseNeighborUnreachabilityDetection bool
ManagedAddressConfigurationSupported bool
OtherStatefulConfigurationSupported bool
AdvertiseDefaultRoute bool
RouterDiscoveryBehavior RouterDiscoveryBehavior
DadTransmits uint32
BaseReachableTime uint32
RetransmitTime uint32
PathMTUDiscoveryTimeout uint32
LinkLocalAddressBehavior LinkLocalAddressBehavior
LinkLocalAddressTimeout uint32
ZoneIndices [ScopeLevelCount]uint32
SitePrefixLength uint32
Metric uint32
NLMTU uint32
Connected bool
SupportsWakeUpPatterns bool
SupportsNeighborDiscovery bool
SupportsRouterDiscovery bool
ReachableTime uint32
TransmitOffload OffloadRod
ReceiveOffload OffloadRod
DisableDefaultRoutes bool
}
// mibIPInterfaceTable structure contains a table of IP interface entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table
type mibIPInterfaceTable struct {
numEntries uint32
_ [4]byte
table [anySize]MibIPInterfaceRow
}
// MibIfRow2 structure stores information about a particular interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2
type MibIfRow2 struct {
InterfaceLUID LUID
InterfaceIndex uint32
InterfaceGUID windows.GUID
alias [ifMaxStringSize + 1]uint16
description [ifMaxStringSize + 1]uint16
physicalAddressLength uint32
physicalAddress [ifMaxPhysAddressLength]byte
permanentPhysicalAddress [ifMaxPhysAddressLength]byte
MTU uint32
Type IfType
TunnelType TunnelType
MediaType NdisMedium
PhysicalMediumType NdisPhysicalMedium
AccessType NetIfAccessType
DirectionType NetIfDirectionType
InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags
OperStatus IfOperStatus
AdminStatus NetIfAdminStatus
MediaConnectState NetIfMediaConnectState
NetworkGUID windows.GUID
ConnectionType NetIfConnectionType
_ [4]byte
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
InOctets uint64
InUcastPkts uint64
InNUcastPkts uint64
InDiscards uint64
InErrors uint64
InUnknownProtos uint64
InUcastOctets uint64
InMulticastOctets uint64
InBroadcastOctets uint64
OutOctets uint64
OutUcastPkts uint64
OutNUcastPkts uint64
OutDiscards uint64
OutErrors uint64
OutUcastOctets uint64
OutMulticastOctets uint64
OutBroadcastOctets uint64
OutQLen uint64
}
// mibIfTable2 structure contains a table of logical and physical interface entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2
type mibIfTable2 struct {
numEntries uint32
_ [4]byte
table [anySize]MibIfRow2
}
// MibUnicastIPAddressRow structure stores information about a unicast IP address.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row
type MibUnicastIPAddressRow struct {
Address RawSockaddrInet
_ [4]byte
InterfaceLUID LUID
InterfaceIndex uint32
PrefixOrigin PrefixOrigin
SuffixOrigin SuffixOrigin
ValidLifetime uint32
PreferredLifetime uint32
OnLinkPrefixLength uint8
SkipAsSource bool
DadState DadState
ScopeID uint32
CreationTimeStamp int64
}
// mibUnicastIPAddressTable structure contains a table of unicast IP address entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table
type mibUnicastIPAddressTable struct {
numEntries uint32
_ [4]byte
table [anySize]MibUnicastIPAddressRow
}
// MibAnycastIPAddressRow structure stores information about an anycast IP address.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row
type MibAnycastIPAddressRow struct {
Address RawSockaddrInet
_ [4]byte
InterfaceLUID LUID
InterfaceIndex uint32
ScopeID uint32
}
// mibAnycastIPAddressTable structure contains a table of anycast IP address entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table
type mibAnycastIPAddressTable struct {
numEntries uint32
_ [4]byte
table [anySize]MibAnycastIPAddressRow
}
// mibIPforwardTable2 structure contains a table of IP route entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2
type mibIPforwardTable2 struct {
numEntries uint32
_ [4]byte
table [anySize]MibIPforwardRow2
}

View File

@@ -0,0 +1,220 @@
//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"golang.org/x/sys/windows"
)
// IPAdapterWINSServerAddress structure stores a single Windows Internet Name Service (WINS) server address in a linked list of WINS server addresses for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_wins_server_address_lh
type IPAdapterWINSServerAddress struct {
Length uint32
_ uint32
Next *IPAdapterWINSServerAddress
Address windows.SocketAddress
}
// IPAdapterGatewayAddress structure stores a single gateway address in a linked list of gateway addresses for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_gateway_address_lh
type IPAdapterGatewayAddress struct {
Length uint32
_ uint32
Next *IPAdapterGatewayAddress
Address windows.SocketAddress
}
// IPAdapterAddresses structure is the header node for a linked list of addresses for a particular adapter. This structure can simultaneously be used as part of a linked list of IP_ADAPTER_ADDRESSES structures.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_addresses_lh
// This is a modified and extended version of windows.IpAdapterAddresses.
type IPAdapterAddresses struct {
Length uint32
IfIndex uint32
Next *IPAdapterAddresses
adapterName *byte
FirstUnicastAddress *windows.IpAdapterUnicastAddress
FirstAnycastAddress *windows.IpAdapterAnycastAddress
FirstMulticastAddress *windows.IpAdapterMulticastAddress
FirstDNSServerAddress *windows.IpAdapterDnsServerAdapter
dnsSuffix *uint16
description *uint16
friendlyName *uint16
physicalAddress [windows.MAX_ADAPTER_ADDRESS_LENGTH]byte
physicalAddressLength uint32
Flags IPAAFlags
MTU uint32
IfType IfType
OperStatus IfOperStatus
IPv6IfIndex uint32
ZoneIndices [16]uint32
FirstPrefix *windows.IpAdapterPrefix
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
FirstWINSServerAddress *IPAdapterWINSServerAddress
FirstGatewayAddress *IPAdapterGatewayAddress
Ipv4Metric uint32
Ipv6Metric uint32
LUID LUID
DHCPv4Server windows.SocketAddress
CompartmentID uint32
NetworkGUID windows.GUID
ConnectionType NetIfConnectionType
TunnelType TunnelType
DHCPv6Server windows.SocketAddress
dhcpv6ClientDUID [maxDHCPv6DUIDLength]byte
dhcpv6ClientDUIDLength uint32
DHCPv6IAID uint32
FirstDNSSuffix *IPAdapterDNSSuffix
}
// MibIPInterfaceRow structure stores interface management information for a particular IP address family on a network interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_row
type MibIPInterfaceRow struct {
Family AddressFamily
InterfaceLUID LUID
InterfaceIndex uint32
MaxReassemblySize uint32
InterfaceIdentifier uint64
MinRouterAdvertisementInterval uint32
MaxRouterAdvertisementInterval uint32
AdvertisingEnabled bool
ForwardingEnabled bool
WeakHostSend bool
WeakHostReceive bool
UseAutomaticMetric bool
UseNeighborUnreachabilityDetection bool
ManagedAddressConfigurationSupported bool
OtherStatefulConfigurationSupported bool
AdvertiseDefaultRoute bool
RouterDiscoveryBehavior RouterDiscoveryBehavior
DadTransmits uint32
BaseReachableTime uint32
RetransmitTime uint32
PathMTUDiscoveryTimeout uint32
LinkLocalAddressBehavior LinkLocalAddressBehavior
LinkLocalAddressTimeout uint32
ZoneIndices [ScopeLevelCount]uint32
SitePrefixLength uint32
Metric uint32
NLMTU uint32
Connected bool
SupportsWakeUpPatterns bool
SupportsNeighborDiscovery bool
SupportsRouterDiscovery bool
ReachableTime uint32
TransmitOffload OffloadRod
ReceiveOffload OffloadRod
DisableDefaultRoutes bool
}
// mibIPInterfaceTable structure contains a table of IP interface entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipinterface_table
type mibIPInterfaceTable struct {
numEntries uint32
table [anySize]MibIPInterfaceRow
}
// MibIfRow2 structure stores information about a particular interface.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_row2
type MibIfRow2 struct {
InterfaceLUID LUID
InterfaceIndex uint32
InterfaceGUID windows.GUID
alias [ifMaxStringSize + 1]uint16
description [ifMaxStringSize + 1]uint16
physicalAddressLength uint32
physicalAddress [ifMaxPhysAddressLength]byte
permanentPhysicalAddress [ifMaxPhysAddressLength]byte
MTU uint32
Type IfType
TunnelType TunnelType
MediaType NdisMedium
PhysicalMediumType NdisPhysicalMedium
AccessType NetIfAccessType
DirectionType NetIfDirectionType
InterfaceAndOperStatusFlags InterfaceAndOperStatusFlags
OperStatus IfOperStatus
AdminStatus NetIfAdminStatus
MediaConnectState NetIfMediaConnectState
NetworkGUID windows.GUID
ConnectionType NetIfConnectionType
TransmitLinkSpeed uint64
ReceiveLinkSpeed uint64
InOctets uint64
InUcastPkts uint64
InNUcastPkts uint64
InDiscards uint64
InErrors uint64
InUnknownProtos uint64
InUcastOctets uint64
InMulticastOctets uint64
InBroadcastOctets uint64
OutOctets uint64
OutUcastPkts uint64
OutNUcastPkts uint64
OutDiscards uint64
OutErrors uint64
OutUcastOctets uint64
OutMulticastOctets uint64
OutBroadcastOctets uint64
OutQLen uint64
}
// mibIfTable2 structure contains a table of logical and physical interface entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_if_table2
type mibIfTable2 struct {
numEntries uint32
table [anySize]MibIfRow2
}
// MibUnicastIPAddressRow structure stores information about a unicast IP address.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row
type MibUnicastIPAddressRow struct {
Address RawSockaddrInet
InterfaceLUID LUID
InterfaceIndex uint32
PrefixOrigin PrefixOrigin
SuffixOrigin SuffixOrigin
ValidLifetime uint32
PreferredLifetime uint32
OnLinkPrefixLength uint8
SkipAsSource bool
DadState DadState
ScopeID uint32
CreationTimeStamp int64
}
// mibUnicastIPAddressTable structure contains a table of unicast IP address entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_table
type mibUnicastIPAddressTable struct {
numEntries uint32
table [anySize]MibUnicastIPAddressRow
}
// MibAnycastIPAddressRow structure stores information about an anycast IP address.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_anycastipaddress_row
type MibAnycastIPAddressRow struct {
Address RawSockaddrInet
InterfaceLUID LUID
InterfaceIndex uint32
ScopeID uint32
}
// mibAnycastIPAddressTable structure contains a table of anycast IP address entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-mib_anycastipaddress_table
type mibAnycastIPAddressTable struct {
numEntries uint32
table [anySize]MibAnycastIPAddressRow
}
// mibIPforwardTable2 structure contains a table of IP route entries.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_ipforward_table2
type mibIPforwardTable2 struct {
numEntries uint32
table [anySize]MibIPforwardRow2
}

View File

@@ -0,0 +1,59 @@
//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
const (
ipAdapterWINSServerAddressSize = 24
ipAdapterWINSServerAddressNextOffset = 8
ipAdapterWINSServerAddressAddressOffset = 12
ipAdapterGatewayAddressSize = 24
ipAdapterGatewayAddressNextOffset = 8
ipAdapterGatewayAddressAddressOffset = 12
ipAdapterDNSSuffixSize = 516
ipAdapterDNSSuffixStringOffset = 4
ipAdapterAddressesSize = 376
ipAdapterAddressesIfIndexOffset = 4
ipAdapterAddressesNextOffset = 8
ipAdapterAddressesAdapterNameOffset = 12
ipAdapterAddressesFirstUnicastAddressOffset = 16
ipAdapterAddressesFirstAnycastAddressOffset = 20
ipAdapterAddressesFirstMulticastAddressOffset = 24
ipAdapterAddressesFirstDNSServerAddressOffset = 28
ipAdapterAddressesDNSSuffixOffset = 32
ipAdapterAddressesDescriptionOffset = 36
ipAdapterAddressesFriendlyNameOffset = 40
ipAdapterAddressesPhysicalAddressOffset = 44
ipAdapterAddressesPhysicalAddressLengthOffset = 52
ipAdapterAddressesFlagsOffset = 56
ipAdapterAddressesMTUOffset = 60
ipAdapterAddressesIfTypeOffset = 64
ipAdapterAddressesOperStatusOffset = 68
ipAdapterAddressesIPv6IfIndexOffset = 72
ipAdapterAddressesZoneIndicesOffset = 76
ipAdapterAddressesFirstPrefixOffset = 140
ipAdapterAddressesTransmitLinkSpeedOffset = 144
ipAdapterAddressesReceiveLinkSpeedOffset = 152
ipAdapterAddressesFirstWINSServerAddressOffset = 160
ipAdapterAddressesFirstGatewayAddressOffset = 164
ipAdapterAddressesIPv4MetricOffset = 168
ipAdapterAddressesIPv6MetricOffset = 172
ipAdapterAddressesLUIDOffset = 176
ipAdapterAddressesDHCPv4ServerOffset = 184
ipAdapterAddressesCompartmentIDOffset = 192
ipAdapterAddressesNetworkGUIDOffset = 196
ipAdapterAddressesConnectionTypeOffset = 212
ipAdapterAddressesTunnelTypeOffset = 216
ipAdapterAddressesDHCPv6ServerOffset = 220
ipAdapterAddressesDHCPv6ClientDUIDOffset = 228
ipAdapterAddressesDHCPv6ClientDUIDLengthOffset = 360
ipAdapterAddressesDHCPv6IAIDOffset = 364
ipAdapterAddressesFirstDNSSuffixOffset = 368
)

View File

@@ -0,0 +1,59 @@
//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
const (
ipAdapterWINSServerAddressSize = 32
ipAdapterWINSServerAddressNextOffset = 8
ipAdapterWINSServerAddressAddressOffset = 16
ipAdapterGatewayAddressSize = 32
ipAdapterGatewayAddressNextOffset = 8
ipAdapterGatewayAddressAddressOffset = 16
ipAdapterDNSSuffixSize = 520
ipAdapterDNSSuffixStringOffset = 8
ipAdapterAddressesSize = 448
ipAdapterAddressesIfIndexOffset = 4
ipAdapterAddressesNextOffset = 8
ipAdapterAddressesAdapterNameOffset = 16
ipAdapterAddressesFirstUnicastAddressOffset = 24
ipAdapterAddressesFirstAnycastAddressOffset = 32
ipAdapterAddressesFirstMulticastAddressOffset = 40
ipAdapterAddressesFirstDNSServerAddressOffset = 48
ipAdapterAddressesDNSSuffixOffset = 56
ipAdapterAddressesDescriptionOffset = 64
ipAdapterAddressesFriendlyNameOffset = 72
ipAdapterAddressesPhysicalAddressOffset = 80
ipAdapterAddressesPhysicalAddressLengthOffset = 88
ipAdapterAddressesFlagsOffset = 92
ipAdapterAddressesMTUOffset = 96
ipAdapterAddressesIfTypeOffset = 100
ipAdapterAddressesOperStatusOffset = 104
ipAdapterAddressesIPv6IfIndexOffset = 108
ipAdapterAddressesZoneIndicesOffset = 112
ipAdapterAddressesFirstPrefixOffset = 176
ipAdapterAddressesTransmitLinkSpeedOffset = 184
ipAdapterAddressesReceiveLinkSpeedOffset = 192
ipAdapterAddressesFirstWINSServerAddressOffset = 200
ipAdapterAddressesFirstGatewayAddressOffset = 208
ipAdapterAddressesIPv4MetricOffset = 216
ipAdapterAddressesIPv6MetricOffset = 220
ipAdapterAddressesLUIDOffset = 224
ipAdapterAddressesDHCPv4ServerOffset = 232
ipAdapterAddressesCompartmentIDOffset = 248
ipAdapterAddressesNetworkGUIDOffset = 252
ipAdapterAddressesConnectionTypeOffset = 268
ipAdapterAddressesTunnelTypeOffset = 272
ipAdapterAddressesDHCPv6ServerOffset = 280
ipAdapterAddressesDHCPv6ClientDUIDOffset = 296
ipAdapterAddressesDHCPv6ClientDUIDLengthOffset = 428
ipAdapterAddressesDHCPv6IAIDOffset = 432
ipAdapterAddressesFirstDNSSuffixOffset = 440
)

View File

@@ -0,0 +1,88 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"sync"
"golang.org/x/sys/windows"
)
// UnicastAddressChangeCallback structure allows unicast address change callback handling.
type UnicastAddressChangeCallback struct {
cb func(notificationType MibNotificationType, unicastAddress *MibUnicastIPAddressRow)
wait sync.WaitGroup
}
var (
unicastAddressChangeAddRemoveMutex = sync.Mutex{}
unicastAddressChangeMutex = sync.Mutex{}
unicastAddressChangeCallbacks = make(map[*UnicastAddressChangeCallback]bool)
unicastAddressChangeHandle = windows.Handle(0)
)
// RegisterUnicastAddressChangeCallback registers a new UnicastAddressChangeCallback. If this particular callback is already
// registered, the function will silently return. Returned UnicastAddressChangeCallback.Unregister method should be used
// to unregister.
func RegisterUnicastAddressChangeCallback(callback func(notificationType MibNotificationType, unicastAddress *MibUnicastIPAddressRow)) (*UnicastAddressChangeCallback, error) {
s := &UnicastAddressChangeCallback{cb: callback}
unicastAddressChangeAddRemoveMutex.Lock()
defer unicastAddressChangeAddRemoveMutex.Unlock()
unicastAddressChangeMutex.Lock()
defer unicastAddressChangeMutex.Unlock()
unicastAddressChangeCallbacks[s] = true
if unicastAddressChangeHandle == 0 {
err := notifyUnicastIPAddressChange(windows.AF_UNSPEC, windows.NewCallback(unicastAddressChanged), 0, false, &unicastAddressChangeHandle)
if err != nil {
delete(unicastAddressChangeCallbacks, s)
unicastAddressChangeHandle = 0
return nil, err
}
}
return s, nil
}
// Unregister unregisters the callback.
func (callback *UnicastAddressChangeCallback) Unregister() error {
unicastAddressChangeAddRemoveMutex.Lock()
defer unicastAddressChangeAddRemoveMutex.Unlock()
unicastAddressChangeMutex.Lock()
delete(unicastAddressChangeCallbacks, callback)
removeIt := len(unicastAddressChangeCallbacks) == 0 && unicastAddressChangeHandle != 0
unicastAddressChangeMutex.Unlock()
callback.wait.Wait()
if removeIt {
err := cancelMibChangeNotify2(unicastAddressChangeHandle)
if err != nil {
return err
}
unicastAddressChangeHandle = 0
}
return nil
}
func unicastAddressChanged(callerContext uintptr, row *MibUnicastIPAddressRow, notificationType MibNotificationType) uintptr {
rowCopy := *row
unicastAddressChangeMutex.Lock()
for cb := range unicastAddressChangeCallbacks {
cb.wait.Add(1)
go func(cb *UnicastAddressChangeCallback) {
cb.cb(notificationType, &rowCopy)
cb.wait.Done()
}(cb)
}
unicastAddressChangeMutex.Unlock()
return 0
}

View File

@@ -0,0 +1,196 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"runtime"
"unsafe"
"golang.org/x/sys/windows"
)
//
// Common functions
//
//sys freeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
//
// Interface-related functions
//
//sys initializeIPInterfaceEntry(row *MibIPInterfaceRow) = iphlpapi.InitializeIpInterfaceEntry
//sys getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) = iphlpapi.GetIpInterfaceTable
//sys getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.GetIpInterfaceEntry
//sys setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) = iphlpapi.SetIpInterfaceEntry
//sys getIfEntry2(row *MibIfRow2) (ret error) = iphlpapi.GetIfEntry2
//sys getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) = iphlpapi.GetIfTable2Ex
//sys convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) = iphlpapi.ConvertInterfaceLuidToGuid
//sys convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceGuidToLuid
//sys convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) = iphlpapi.ConvertInterfaceIndexToLuid
// GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses
func GetAdaptersAddresses(family AddressFamily, flags GAAFlags) ([]*IPAdapterAddresses, error) {
var b []byte
size := uint32(15000)
for {
b = make([]byte, size)
err := windows.GetAdaptersAddresses(uint32(family), uint32(flags), 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &size)
if err == nil {
break
}
if err != windows.ERROR_BUFFER_OVERFLOW || size <= uint32(len(b)) {
return nil, err
}
}
result := make([]*IPAdapterAddresses, 0, uintptr(size)/unsafe.Sizeof(IPAdapterAddresses{}))
for wtiaa := (*IPAdapterAddresses)(unsafe.Pointer(&b[0])); wtiaa != nil; wtiaa = wtiaa.Next {
result = append(result, wtiaa)
}
return result, nil
}
// GetIPInterfaceTable function retrieves the IP interface entries on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipinterfacetable
func GetIPInterfaceTable(family AddressFamily) ([]MibIPInterfaceRow, error) {
var tab *mibIPInterfaceTable
err := getIPInterfaceTable(family, &tab)
if err != nil {
return nil, err
}
t := append(make([]MibIPInterfaceRow, 0, tab.numEntries), tab.get()...)
tab.free()
return t, nil
}
// GetIfTable2Ex function retrieves the MIB-II interface table.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getiftable2ex
func GetIfTable2Ex(level MibIfEntryLevel) ([]MibIfRow2, error) {
var tab *mibIfTable2
err := getIfTable2Ex(level, &tab)
if err != nil {
return nil, err
}
t := append(make([]MibIfRow2, 0, tab.numEntries), tab.get()...)
tab.free()
return t, nil
}
//
// Unicast IP address-related functions
//
//sys getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) = iphlpapi.GetUnicastIpAddressTable
//sys initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) = iphlpapi.InitializeUnicastIpAddressEntry
//sys getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.GetUnicastIpAddressEntry
//sys setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.SetUnicastIpAddressEntry
//sys createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.CreateUnicastIpAddressEntry
//sys deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) = iphlpapi.DeleteUnicastIpAddressEntry
// GetUnicastIPAddressTable function retrieves the unicast IP address table on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddresstable
func GetUnicastIPAddressTable(family AddressFamily) ([]MibUnicastIPAddressRow, error) {
var tab *mibUnicastIPAddressTable
err := getUnicastIPAddressTable(family, &tab)
if err != nil {
return nil, err
}
t := append(make([]MibUnicastIPAddressRow, 0, tab.numEntries), tab.get()...)
tab.free()
return t, nil
}
//
// Anycast IP address-related functions
//
//sys getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) = iphlpapi.GetAnycastIpAddressTable
//sys getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.GetAnycastIpAddressEntry
//sys createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.CreateAnycastIpAddressEntry
//sys deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) = iphlpapi.DeleteAnycastIpAddressEntry
// GetAnycastIPAddressTable function retrieves the anycast IP address table on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getanycastipaddresstable
func GetAnycastIPAddressTable(family AddressFamily) ([]MibAnycastIPAddressRow, error) {
var tab *mibAnycastIPAddressTable
err := getAnycastIPAddressTable(family, &tab)
if err != nil {
return nil, err
}
t := append(make([]MibAnycastIPAddressRow, 0, tab.numEntries), tab.get()...)
tab.free()
return t, nil
}
//
// Routing-related functions
//
//sys getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) = iphlpapi.GetIpForwardTable2
//sys initializeIPForwardEntry(route *MibIPforwardRow2) = iphlpapi.InitializeIpForwardEntry
//sys getIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.GetIpForwardEntry2
//sys setIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.SetIpForwardEntry2
//sys createIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.CreateIpForwardEntry2
//sys deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) = iphlpapi.DeleteIpForwardEntry2
// GetIPForwardTable2 function retrieves the IP route entries on the local computer.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardtable2
func GetIPForwardTable2(family AddressFamily) ([]MibIPforwardRow2, error) {
var tab *mibIPforwardTable2
err := getIPForwardTable2(family, &tab)
if err != nil {
return nil, err
}
t := append(make([]MibIPforwardRow2, 0, tab.numEntries), tab.get()...)
tab.free()
return t, nil
}
//
// Notifications-related functions
//
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyipinterfacechange
//sys notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyIpInterfaceChange
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyunicastipaddresschange
//sys notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyUnicastIpAddressChange
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-notifyroutechange2
//sys notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) = iphlpapi.NotifyRouteChange2
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-cancelmibchangenotify2
//sys cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) = iphlpapi.CancelMibChangeNotify2
//
// DNS-related functions
//
//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
// The GUID is passed by value, not by reference, which means different
// things on different calling conventions. On amd64, this means it's
// passed by reference anyway, while on arm, arm64, and 386, it's split
// into words.
func SetInterfaceDnsSettings(guid windows.GUID, settings *DnsInterfaceSettings) error {
words := (*[4]uintptr)(unsafe.Pointer(&guid))
switch runtime.GOARCH {
case "amd64":
return setInterfaceDnsSettingsByPtr(&guid, settings)
case "arm64":
return setInterfaceDnsSettingsByQwords(words[0], words[1], settings)
case "arm", "386":
return setInterfaceDnsSettingsByDwords(words[0], words[1], words[2], words[3], settings)
default:
panic("unknown calling convention")
}
}

View File

@@ -0,0 +1,350 @@
// Code generated by 'go generate'; DO NOT EDIT.
package winipcfg
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
procConvertInterfaceGuidToLuid = modiphlpapi.NewProc("ConvertInterfaceGuidToLuid")
procConvertInterfaceIndexToLuid = modiphlpapi.NewProc("ConvertInterfaceIndexToLuid")
procConvertInterfaceLuidToGuid = modiphlpapi.NewProc("ConvertInterfaceLuidToGuid")
procCreateAnycastIpAddressEntry = modiphlpapi.NewProc("CreateAnycastIpAddressEntry")
procCreateIpForwardEntry2 = modiphlpapi.NewProc("CreateIpForwardEntry2")
procCreateUnicastIpAddressEntry = modiphlpapi.NewProc("CreateUnicastIpAddressEntry")
procDeleteAnycastIpAddressEntry = modiphlpapi.NewProc("DeleteAnycastIpAddressEntry")
procDeleteIpForwardEntry2 = modiphlpapi.NewProc("DeleteIpForwardEntry2")
procDeleteUnicastIpAddressEntry = modiphlpapi.NewProc("DeleteUnicastIpAddressEntry")
procFreeMibTable = modiphlpapi.NewProc("FreeMibTable")
procGetAnycastIpAddressEntry = modiphlpapi.NewProc("GetAnycastIpAddressEntry")
procGetAnycastIpAddressTable = modiphlpapi.NewProc("GetAnycastIpAddressTable")
procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2")
procGetIfTable2Ex = modiphlpapi.NewProc("GetIfTable2Ex")
procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2")
procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2")
procGetIpInterfaceEntry = modiphlpapi.NewProc("GetIpInterfaceEntry")
procGetIpInterfaceTable = modiphlpapi.NewProc("GetIpInterfaceTable")
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
procGetUnicastIpAddressTable = modiphlpapi.NewProc("GetUnicastIpAddressTable")
procInitializeIpForwardEntry = modiphlpapi.NewProc("InitializeIpForwardEntry")
procInitializeIpInterfaceEntry = modiphlpapi.NewProc("InitializeIpInterfaceEntry")
procInitializeUnicastIpAddressEntry = modiphlpapi.NewProc("InitializeUnicastIpAddressEntry")
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2")
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
procSetInterfaceDnsSettings = modiphlpapi.NewProc("SetInterfaceDnsSettings")
procSetIpForwardEntry2 = modiphlpapi.NewProc("SetIpForwardEntry2")
procSetIpInterfaceEntry = modiphlpapi.NewProc("SetIpInterfaceEntry")
procSetUnicastIpAddressEntry = modiphlpapi.NewProc("SetUnicastIpAddressEntry")
)
func cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) {
r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func convertInterfaceGUIDToLUID(interfaceGUID *windows.GUID, interfaceLUID *LUID) (ret error) {
r0, _, _ := syscall.Syscall(procConvertInterfaceGuidToLuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceGUID)), uintptr(unsafe.Pointer(interfaceLUID)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func convertInterfaceIndexToLUID(interfaceIndex uint32, interfaceLUID *LUID) (ret error) {
r0, _, _ := syscall.Syscall(procConvertInterfaceIndexToLuid.Addr(), 2, uintptr(interfaceIndex), uintptr(unsafe.Pointer(interfaceLUID)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func convertInterfaceLUIDToGUID(interfaceLUID *LUID, interfaceGUID *windows.GUID) (ret error) {
r0, _, _ := syscall.Syscall(procConvertInterfaceLuidToGuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceLUID)), uintptr(unsafe.Pointer(interfaceGUID)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func createAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procCreateAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func createIPForwardEntry2(route *MibIPforwardRow2) (ret error) {
r0, _, _ := syscall.Syscall(procCreateIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func createUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procCreateUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func deleteAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procDeleteAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func deleteIPForwardEntry2(route *MibIPforwardRow2) (ret error) {
r0, _, _ := syscall.Syscall(procDeleteIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func deleteUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procDeleteUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func freeMibTable(memory unsafe.Pointer) {
syscall.Syscall(procFreeMibTable.Addr(), 1, uintptr(memory), 0, 0)
return
}
func getAnycastIPAddressEntry(row *MibAnycastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procGetAnycastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getAnycastIPAddressTable(family AddressFamily, table **mibAnycastIPAddressTable) (ret error) {
r0, _, _ := syscall.Syscall(procGetAnycastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIfEntry2(row *MibIfRow2) (ret error) {
r0, _, _ := syscall.Syscall(procGetIfEntry2.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIfTable2Ex(level MibIfEntryLevel, table **mibIfTable2) (ret error) {
r0, _, _ := syscall.Syscall(procGetIfTable2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(table)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIPForwardEntry2(route *MibIPforwardRow2) (ret error) {
r0, _, _ := syscall.Syscall(procGetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIPForwardTable2(family AddressFamily, table **mibIPforwardTable2) (ret error) {
r0, _, _ := syscall.Syscall(procGetIpForwardTable2.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) {
r0, _, _ := syscall.Syscall(procGetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getIPInterfaceTable(family AddressFamily, table **mibIPInterfaceTable) (ret error) {
r0, _, _ := syscall.Syscall(procGetIpInterfaceTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func getUnicastIPAddressTable(family AddressFamily, table **mibUnicastIPAddressTable) (ret error) {
r0, _, _ := syscall.Syscall(procGetUnicastIpAddressTable.Addr(), 2, uintptr(family), uintptr(unsafe.Pointer(table)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func initializeIPForwardEntry(route *MibIPforwardRow2) {
syscall.Syscall(procInitializeIpForwardEntry.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0)
return
}
func initializeIPInterfaceEntry(row *MibIPInterfaceRow) {
syscall.Syscall(procInitializeIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
return
}
func initializeUnicastIPAddressEntry(row *MibUnicastIPAddressRow) {
syscall.Syscall(procInitializeUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
return
}
func notifyIPInterfaceChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) {
var _p0 uint32
if initialNotification {
_p0 = 1
}
r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func notifyRouteChange2(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) {
var _p0 uint32
if initialNotification {
_p0 = 1
}
r0, _, _ := syscall.Syscall6(procNotifyRouteChange2.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *windows.Handle) (ret error) {
var _p0 uint32
if initialNotification {
_p0 = 1
}
r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
r0, _, _ := syscall.Syscall6(procSetInterfaceDnsSettings.Addr(), 5, uintptr(guid1), uintptr(guid2), uintptr(guid3), uintptr(guid4), uintptr(unsafe.Pointer(settings)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings)))
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setIPForwardEntry2(route *MibIPforwardRow2) (ret error) {
r0, _, _ := syscall.Syscall(procSetIpForwardEntry2.Addr(), 1, uintptr(unsafe.Pointer(route)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setIPInterfaceEntry(row *MibIPInterfaceRow) (ret error) {
r0, _, _ := syscall.Syscall(procSetIpInterfaceEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func setUnicastIPAddressEntry(row *MibUnicastIPAddressRow) (ret error) {
r0, _, _ := syscall.Syscall(procSetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}