Skip to content

Commit

Permalink
packetbeat/route: make use of newly added GetBestInterfaceEx in x/sys…
Browse files Browse the repository at this point in the history
…/windows (#32180)

Also use windows.GetAdaptersAddresses and windows.IpAdapterAddresses
(now complete).
  • Loading branch information
efd6 committed Jul 6, 2022
1 parent 5dd823f commit e4a929d
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 135 deletions.
4 changes: 2 additions & 2 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17431,11 +17431,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

--------------------------------------------------------------------------------
Dependency : golang.org/x/sys
Version: v0.0.0-20220520151302-bc2c85ada10a
Version: v0.0.0-20220702020025-31831981b65f
Licence type (autodetected): BSD-3-Clause
--------------------------------------------------------------------------------

Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20220520151302-bc2c85ada10a/LICENSE:
Contents of probable licence file $GOMODCACHE/golang.org/x/sys@v0.0.0-20220702020025-31831981b65f/LICENSE:

Copyright (c) 2009 The Go Authors. All rights reserved.

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ require (
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
golang.org/x/sys v0.0.0-20220702020025-31831981b65f
golang.org/x/text v0.3.7
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
golang.org/x/tools v0.1.9
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2103,8 +2103,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220702020025-31831981b65f h1:xdsejrW/0Wf2diT5CPp3XmKUNbr7Xvw8kYilQ+6qjRY=
golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
155 changes: 24 additions & 131 deletions packetbeat/route/route_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,184 +15,77 @@
// specific language governing permissions and limitations
// under the License.

//nolint:unused,structcheck // How many ways to check for unused? (╯°□°)╯︵ ┻━┻ Fields kept for documentation.
package route

import (
"errors"
"runtime"
"syscall"
"unsafe"

"golang.org/x/sys/windows"
)

var (
// For details of the APIs used, see:
// https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getbestinterfaceex
// https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses
libiphlpapi = windows.NewLazySystemDLL("Iphlpapi.dll")
getBestInterfaceEx = libiphlpapi.NewProc("GetBestInterfaceEx")
getAdaptersAddresses = libiphlpapi.NewProc("GetAdaptersAddresses")
)

// Default returns the interface and netstat device index of the network interface
// used for the first identified default route for the specified address family.
// Valid values for af are syscall.AF_INET and syscall.AF_INET6. The iface name
// returned will include only the GUID of the device.
func Default(af int) (name string, index int, err error) {
var family windows.Sockaddr
switch af {
case windows.AF_INET, windows.AF_INET6:
case windows.AF_INET:
family = &windows.SockaddrInet4{}
case windows.AF_INET6:
family = &windows.SockaddrInet6{}
default:
return "", -1, errors.New("invalid family")
}

type sockaddr struct {
Family uint16
_ [26]byte
}

var idx uint32
family := &sockaddr{Family: uint16(af)}
ret, _, err := getBestInterfaceEx.Call(uintptr(unsafe.Pointer(family)), uintptr(unsafe.Pointer(&idx)))
err = windows.GetBestInterfaceEx(family, &idx)
runtime.KeepAlive(family)
if ret != windows.NO_ERROR {
if syscall.Errno(ret) == windows.ERROR_NOT_FOUND {
err = ErrNotFound
}
switch err { //nolint:errorlint // These are errno errors.
case nil, windows.ERROR_SUCCESS:
case windows.ERROR_NOT_FOUND:
return "", -1, ErrNotFound
default:
return "", -1, err
}

var addresses *windows.IpAdapterAddresses
const (
workingBufferSize = 15000
maxTries = 3
)
var buf []byte
outBufLen := workingBufferSize
outBufLen := uint32(workingBufferSize)
loop:
for i := 0; i < maxTries; i++ {
buf = make([]byte, outBufLen)
ret, _, err = getAdaptersAddresses.Call(uintptr(af), 0, 0, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&outBufLen)))
buf := make([]byte, outBufLen)
addresses = (*windows.IpAdapterAddresses)(unsafe.Pointer(&buf[0]))
err = windows.GetAdaptersAddresses(uint32(af), 0, 0, addresses, &outBufLen)
runtime.KeepAlive(outBufLen)
switch syscall.Errno(ret) {
switch err { //nolint:errorlint // These are errno errors.
case nil, windows.ERROR_SUCCESS:
break loop
case windows.ERROR_BUFFER_OVERFLOW:
continue
case windows.NO_ERROR:
break loop
case windows.ERROR_NO_DATA:
return "", -1, ErrNotFound
default:
return "", -1, err
}
}

addresses := (*ipAdapterAddressesLH)(unsafe.Pointer(&buf[0]))
for ; addresses != nil; addresses = addresses.next {
for ; addresses != nil; addresses = addresses.Next {
switch af {
case windows.AF_INET:
if addresses.ifIndex != 0 && addresses.ifIndex == idx {
return windows.BytePtrToString(addresses.adapterName), int(idx), nil
if addresses.IfIndex != 0 && addresses.IfIndex == idx {
return windows.BytePtrToString(addresses.AdapterName), int(idx), nil
}
case windows.AF_INET6:
if addresses.ipv6IfIndex != 0 && addresses.ipv6IfIndex == idx {
return windows.BytePtrToString(addresses.adapterName), int(idx), nil
if addresses.Ipv6IfIndex != 0 && addresses.Ipv6IfIndex == idx {
return windows.BytePtrToString(addresses.AdapterName), int(idx), nil
}
}
}
return "", -1, ErrNotFound
}

// https://docs.microsoft.com/en-us/windows/win32/api/ipexport/ns-ipexport-ip_interface_info
type ipInterfaceInfo struct {
numAdapters int32
adapter ipAdapterIndexMap
}

// https://docs.microsoft.com/en-us/windows/win32/api/ipexport/ns-ipexport-ip_adapter_index_map
type ipAdapterIndexMap struct {
index uint32
name [maxAdapterName]uint16
}

// https://doxygen.reactos.org/d3/d8d/ipexport_8h_source.html#l00143
const maxAdapterName = 128

// https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh
type ipAdapterAddressesLH struct {
length uint32
ifIndex uint32
next *ipAdapterAddressesLH
adapterName *byte
firstUnicastAddress *windows.IpAdapterUnicastAddress
firstAnycastAddress *windows.IpAdapterAnycastAddress
firstMulticastAddress *windows.IpAdapterMulticastAddress
firstDnsServerAddress *windows.IpAdapterDnsServerAdapter
dnsSuffix *uint16
description *uint16
friendlyName *uint16
physicalAddress [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
physicalAddressLength uint32
flags uint32
mtu uint32
ifType uint32
operStatus uint32
ipv6IfIndex uint32
zoneIndices [16]uint32
firstPrefix *windows.IpAdapterPrefix
transmitLinkSpeed uint64
receiveLinkSpeed uint64
firstWinsServerAddress *ipAdapterWinsServerAddressLH
firstGatewayAddress *ipAdapterGatewayAddressLH
ipv4Metric uint32
ipv6Metric uint32
luid uint64
dhcpv4Server socketAddress
compartmentId uint32
networkGuid guid
connectionType uint32
tunnelType uint32
dhcpv6Server socketAddress
dhcpv6ClientDuid [maxDHCPv6DUIDLength]byte
dhcpv6ClientDuidLength uint32
dhcpv6Iaid uint32
firstDnsSuffix *ipAdapterDNSSuffix
}

// https://doxygen.reactos.org/d2/d14/iptypes_8h_source.html#l00176
type ipAdapterWinsServerAddressLH struct {
alignment uint64
next *ipAdapterWinsServerAddressLH
address socketAddress
}

// https://doxygen.reactos.org/d2/d14/iptypes_8h_source.html#l00190
type ipAdapterGatewayAddressLH struct {
alignment uint64
next *ipAdapterGatewayAddressLH
address socketAddress
}

// https://doxygen.reactos.org/d8/d15/scsiwmi_8h_source.html#l00050
type guid struct {
data1 uint32
data2 uint16
data3 uint16
data4 [8]byte
}

// https://doxygen.reactos.org/d1/db0/ws2def_8h_source.html#l00374
type socketAddress struct {
lpSockaddr int32
iSockaddrLength int32
}

// https://doxygen.reactos.org/d2/d14/iptypes_8h_source.html#l00204
type ipAdapterDNSSuffix struct {
next *ipAdapterDNSSuffix
string [maxDNSSuffixStringLength]uint16
}

const (
maxDHCPv6DUIDLength = 130 // https://doxygen.reactos.org/d2/d14/iptypes_8h_source.html#l00033
maxDNSSuffixStringLength = 256 // https://doxygen.reactos.org/d2/d14/iptypes_8h_source.html#l00034
)

0 comments on commit e4a929d

Please sign in to comment.