aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tunnel/winipcfg/types.go
diff options
context:
space:
mode:
Diffstat (limited to 'tunnel/winipcfg/types.go')
-rw-r--r--tunnel/winipcfg/types.go202
1 files changed, 132 insertions, 70 deletions
diff --git a/tunnel/winipcfg/types.go b/tunnel/winipcfg/types.go
index 81f9335d..8e8f4a59 100644
--- a/tunnel/winipcfg/types.go
+++ b/tunnel/winipcfg/types.go
@@ -1,13 +1,15 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
- "bytes"
- "net"
+ "encoding/binary"
+ "fmt"
+ "net/netip"
+ "strconv"
"unsafe"
"golang.org/x/sys/windows"
@@ -581,19 +583,17 @@ const (
ScopeLevelCount = 16
)
-// Theoretical array index limitations
-const (
- maxIndexCount8 = (1 << 31) - 1
- maxIndexCount16 = (1 << 30) - 1
-)
-
// RouteData structure describes a route to add
type RouteData struct {
- Destination net.IPNet
- NextHop net.IP
+ Destination netip.Prefix
+ NextHop netip.Addr
Metric uint32
}
+func (routeData *RouteData) String() string {
+ return fmt.Sprintf("%+v", *routeData)
+}
+
// IPAdapterDNSSuffix structure stores a DNS suffix in a linked list of DNS suffixes for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_dns_suffix
type IPAdapterDNSSuffix struct {
@@ -609,15 +609,7 @@ func (obj *IPAdapterDNSSuffix) String() string {
// AdapterName method returns the name of the adapter with which these addresses are associated.
// Unlike an adapter's friendly name, the adapter name returned by AdapterName is permanent and cannot be modified by the user.
func (addr *IPAdapterAddresses) AdapterName() string {
- if addr.adapterName == nil {
- return ""
- }
- slice := (*(*[maxIndexCount8]uint8)(unsafe.Pointer(addr.adapterName)))[:]
- null := bytes.IndexByte(slice, 0)
- if null != -1 {
- slice = slice[:null]
- }
- return string(slice)
+ return windows.BytePtrToString(addr.adapterName)
}
// DNSSuffix method returns adapter DNS suffix associated with this adapter.
@@ -625,7 +617,7 @@ func (addr *IPAdapterAddresses) DNSSuffix() string {
if addr.dnsSuffix == nil {
return ""
}
- return windows.UTF16ToString((*(*[maxIndexCount16]uint16)(unsafe.Pointer(addr.dnsSuffix)))[:])
+ return windows.UTF16PtrToString(addr.dnsSuffix)
}
// Description method returns description for the adapter.
@@ -633,7 +625,7 @@ func (addr *IPAdapterAddresses) Description() string {
if addr.description == nil {
return ""
}
- return windows.UTF16ToString((*(*[maxIndexCount16]uint16)(unsafe.Pointer(addr.description)))[:])
+ return windows.UTF16PtrToString(addr.description)
}
// FriendlyName method returns a user-friendly name for the adapter. For example: "Local Area Connection 1."
@@ -642,7 +634,7 @@ func (addr *IPAdapterAddresses) FriendlyName() string {
if addr.friendlyName == nil {
return ""
}
- return windows.UTF16ToString((*(*[maxIndexCount16]uint16)(unsafe.Pointer(addr.friendlyName)))[:])
+ return windows.UTF16PtrToString(addr.friendlyName)
}
// PhysicalAddress method returns the Media Access Control (MAC) address for the adapter.
@@ -693,9 +685,8 @@ func (row *MibIPInterfaceRow) Set() error {
}
// get method returns all table rows as a Go slice.
-func (tab *mibIPInterfaceTable) get() []MibIPInterfaceRow {
- const maxCount = maxIndexCount8 / unsafe.Sizeof(MibIPInterfaceRow{})
- return (*[maxCount]MibIPInterfaceRow)(unsafe.Pointer(&tab.table[0]))[:tab.numEntries]
+func (tab *mibIPInterfaceTable) get() (s []MibIPInterfaceRow) {
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -731,9 +722,8 @@ func (row *MibIfRow2) get() (ret error) {
}
// get method returns all table rows as a Go slice.
-func (tab *mibIfTable2) get() []MibIfRow2 {
- const maxCount = maxIndexCount8 / unsafe.Sizeof(MibIfRow2{})
- return (*[maxCount]MibIfRow2)(unsafe.Pointer(&tab.table[0]))[:tab.numEntries]
+func (tab *mibIfTable2) get() (s []MibIfRow2) {
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -749,45 +739,82 @@ type RawSockaddrInet struct {
data [26]byte
}
-// SetIP method sets family, address, and port to the given IPv4 or IPv6 address and port.
+func ntohs(i uint16) uint16 {
+ return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&i))[:])
+}
+
+func htons(i uint16) uint16 {
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, i)
+ return *(*uint16)(unsafe.Pointer(&b[0]))
+}
+
+// SetAddrPort method sets family, address, and port to the given IPv4 or IPv6 address and port.
// All other members of the structure are set to zero.
-func (addr *RawSockaddrInet) SetIP(ip net.IP, port uint16) error {
- if v4 := ip.To4(); v4 != nil {
+func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error {
+ if addrPort.Addr().Is4() {
addr4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(addr))
addr4.Family = windows.AF_INET
- copy(addr4.Addr[:], v4)
- addr4.Port = port
+ addr4.Addr = addrPort.Addr().As4()
+ addr4.Port = htons(addrPort.Port())
for i := 0; i < 8; i++ {
addr4.Zero[i] = 0
}
return nil
- }
-
- if v6 := ip.To16(); v6 != nil {
+ } else if addrPort.Addr().Is6() {
addr6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
addr6.Family = windows.AF_INET6
- addr6.Port = port
+ addr6.Addr = addrPort.Addr().As16()
+ addr6.Port = htons(addrPort.Port())
addr6.Flowinfo = 0
- copy(addr6.Addr[:], v6)
- addr6.Scope_id = 0
+ scopeId := uint32(0)
+ if z := addrPort.Addr().Zone(); z != "" {
+ if s, err := strconv.ParseUint(z, 10, 32); err == nil {
+ scopeId = uint32(s)
+ }
+ }
+ addr6.Scope_id = scopeId
return nil
}
-
return windows.ERROR_INVALID_PARAMETER
}
-// IP method returns IPv4 or IPv6 address.
-// If the address is neither IPv4 not IPv6 nil is returned.
-func (addr *RawSockaddrInet) IP() net.IP {
+// SetAddr method sets family and address to the given IPv4 or IPv6 address.
+// All other members of the structure are set to zero.
+func (addr *RawSockaddrInet) SetAddr(netAddr netip.Addr) error {
+ return addr.SetAddrPort(netip.AddrPortFrom(netAddr, 0))
+}
+
+// AddrPort returns the IP address and port.
+func (addr *RawSockaddrInet) AddrPort() netip.AddrPort {
+ return netip.AddrPortFrom(addr.Addr(), addr.Port())
+}
+
+// Addr returns IPv4 or IPv6 address, or an invalid address if the address is neither.
+func (addr *RawSockaddrInet) Addr() netip.Addr {
switch addr.Family {
case windows.AF_INET:
- return (*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr[:]
-
+ return netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr)
case windows.AF_INET6:
- return (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Addr[:]
+ raw := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
+ a := netip.AddrFrom16(raw.Addr)
+ if raw.Scope_id != 0 {
+ a = a.WithZone(strconv.FormatUint(uint64(raw.Scope_id), 10))
+ }
+ return a
}
+ return netip.Addr{}
+}
- return nil
+// Port returns the port if the address if IPv4 or IPv6, or 0 if neither.
+func (addr *RawSockaddrInet) Port() uint16 {
+ switch addr.Family {
+ case windows.AF_INET:
+ return ntohs((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Port)
+ case windows.AF_INET6:
+ return ntohs((*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Port)
+ }
+ return 0
}
// Init method initializes a MibUnicastIPAddressRow structure with default values for a unicast IP address entry on the local computer.
@@ -821,9 +848,8 @@ func (row *MibUnicastIPAddressRow) Delete() error {
}
// get method returns all table rows as a Go slice.
-func (tab *mibUnicastIPAddressTable) get() []MibUnicastIPAddressRow {
- const maxCount = maxIndexCount8 / unsafe.Sizeof(MibUnicastIPAddressRow{})
- return (*[maxCount]MibUnicastIPAddressRow)(unsafe.Pointer(&tab.table[0]))[:tab.numEntries]
+func (tab *mibUnicastIPAddressTable) get() (s []MibUnicastIPAddressRow) {
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -851,9 +877,8 @@ func (row *MibAnycastIPAddressRow) Delete() error {
}
// get method returns all table rows as a Go slice.
-func (tab *mibAnycastIPAddressTable) get() []MibAnycastIPAddressRow {
- const maxCount = maxIndexCount8 / unsafe.Sizeof(MibAnycastIPAddressRow{})
- return (*[maxCount]MibAnycastIPAddressRow)(unsafe.Pointer(&tab.table[0]))[:tab.numEntries]
+func (tab *mibAnycastIPAddressTable) get() (s []MibAnycastIPAddressRow) {
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -865,32 +890,30 @@ func (tab *mibAnycastIPAddressTable) free() {
// IPAddressPrefix structure stores an IP address prefix.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_ip_address_prefix
type IPAddressPrefix struct {
- Prefix RawSockaddrInet
+ RawPrefix RawSockaddrInet
PrefixLength uint8
_ [2]byte
}
-// SetIPNet method sets IP address prefix using net.IPNet.
-func (prefix *IPAddressPrefix) SetIPNet(net net.IPNet) error {
- err := prefix.Prefix.SetIP(net.IP, 0)
+// SetPrefix method sets IP address prefix using netip.Prefix.
+func (prefix *IPAddressPrefix) SetPrefix(netPrefix netip.Prefix) error {
+ err := prefix.RawPrefix.SetAddr(netPrefix.Addr())
if err != nil {
return err
}
- ones, _ := net.Mask.Size()
- prefix.PrefixLength = uint8(ones)
+ prefix.PrefixLength = uint8(netPrefix.Bits())
return nil
}
-// IPNet method returns IP address prefix as net.IPNet.
-// If the address is neither IPv4 not IPv6 an empty net.IPNet is returned. The resulting net.IPNet should be checked appropriately.
-func (prefix *IPAddressPrefix) IPNet() net.IPNet {
- switch prefix.Prefix.Family {
+// Prefix returns IP address prefix as netip.Prefix.
+func (prefix *IPAddressPrefix) Prefix() netip.Prefix {
+ switch prefix.RawPrefix.Family {
case windows.AF_INET:
- return net.IPNet{IP: (*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv4len)}
+ return netip.PrefixFrom(netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
case windows.AF_INET6:
- return net.IPNet{IP: (*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv6len)}
+ return netip.PrefixFrom(netip.AddrFrom16((*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
}
- return net.IPNet{}
+ return netip.Prefix{}
}
// MibIPforwardRow2 structure stores information about an IP route entry.
@@ -944,9 +967,8 @@ func (row *MibIPforwardRow2) Delete() error {
}
// get method returns all table rows as a Go slice.
-func (tab *mibIPforwardTable2) get() []MibIPforwardRow2 {
- const maxCount = maxIndexCount8 / unsafe.Sizeof(MibIPforwardRow2{})
- return (*[maxCount]MibIPforwardRow2)(unsafe.Pointer(&tab.table[0]))[:tab.numEntries]
+func (tab *mibIPforwardTable2) get() (s []MibIPforwardRow2) {
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -954,3 +976,43 @@ func (tab *mibIPforwardTable2) get() []MibIPforwardRow2 {
func (tab *mibIPforwardTable2) free() {
freeMibTable(unsafe.Pointer(tab))
}
+
+//
+// DNS API
+//
+
+// DnsInterfaceSettings is meant to be used with SetInterfaceDnsSettings
+type DnsInterfaceSettings struct {
+ Version uint32
+ _ [4]byte
+ Flags uint64
+ Domain *uint16
+ NameServer *uint16
+ SearchList *uint16
+ RegistrationEnabled uint32
+ RegisterAdapterName uint32
+ EnableLLMNR uint32
+ QueryAdapterName uint32
+ ProfileNameServer *uint16
+}
+
+const (
+ DnsInterfaceSettingsVersion1 = 1 // for DnsInterfaceSettings
+ DnsInterfaceSettingsVersion2 = 2 // for DnsInterfaceSettingsEx
+ DnsInterfaceSettingsVersion3 = 3 // for DnsInterfaceSettings3
+
+ DnsInterfaceSettingsFlagIPv6 = 0x0001
+ DnsInterfaceSettingsFlagNameserver = 0x0002
+ DnsInterfaceSettingsFlagSearchList = 0x0004
+ DnsInterfaceSettingsFlagRegistrationEnabled = 0x0008
+ DnsInterfaceSettingsFlagRegisterAdapterName = 0x0010
+ DnsInterfaceSettingsFlagDomain = 0x0020
+ DnsInterfaceSettingsFlagHostname = 0x0040
+ DnsInterfaceSettingsFlagEnableLLMNR = 0x0080
+ DnsInterfaceSettingsFlagQueryAdapterName = 0x0100
+ DnsInterfaceSettingsFlagProfileNameserver = 0x0200
+ DnsInterfaceSettingsFlagDisableUnconstrainedQueries = 0x0400 // v2 only
+ DnsInterfaceSettingsFlagSupplementalSearchList = 0x0800 // v2 only
+ DnsInterfaceSettingsFlagDOH = 0x1000 // v3 only
+ DnsInterfaceSettingsFlagDOHProfile = 0x2000 // v3 only
+)