diff options
Diffstat (limited to 'tunnel/winipcfg/types.go')
-rw-r--r-- | tunnel/winipcfg/types.go | 202 |
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 +) |