mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
net/netstat: document the Windows netstat code a bit more
And defensively bound allocation. Updates tailscale/corp#8878 Change-Id: Iaa07479ea2ea28ee1ac3326ab025046d6d785b00 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
8c20da2568
commit
2fc8de485c
@ -20,6 +20,13 @@
|
||||
// OSMetadata includes any additional OS-specific information that may be
|
||||
// obtained during the retrieval of a given Entry.
|
||||
type OSMetadata interface {
|
||||
// GetModule returns the entry's module name.
|
||||
//
|
||||
// It returns ("", nil) if no entry is found. As of 2023-01-27, any returned
|
||||
// error is silently discarded by its sole caller in portlist_windows.go and
|
||||
// treated equivalently as returning ("", nil), but this may change in the
|
||||
// future. An error should only be returned in casees that are worthy of
|
||||
// being logged at least.
|
||||
GetModule() (string, error)
|
||||
}
|
||||
|
||||
@ -224,7 +231,13 @@ type moduleInfoConstraint interface {
|
||||
_MIB_TCPROW_OWNER_MODULE | _MIB_TCP6ROW_OWNER_MODULE
|
||||
}
|
||||
|
||||
// moduleInfo may return "", nil indicating a successful call but with empty data
|
||||
// moduleInfo implements OSMetadata.GetModule. It calls
|
||||
// getOwnerModuleFromTcpEntry or getOwnerModuleFromTcp6Entry.
|
||||
//
|
||||
// See
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getownermodulefromtcpentry
|
||||
//
|
||||
// It may return "", nil indicating a successful call but with empty data.
|
||||
func moduleInfo[entryType moduleInfoConstraint](entry *entryType, proc *windows.LazyProc) (string, error) {
|
||||
var buf []byte
|
||||
var desiredLen uint32
|
||||
@ -241,28 +254,36 @@ func moduleInfo[entryType moduleInfoConstraint](entry *entryType, proc *windows.
|
||||
if err == windows.ERROR_SUCCESS {
|
||||
break
|
||||
}
|
||||
if err == windows.ERROR_NOT_FOUND {
|
||||
return "", nil
|
||||
}
|
||||
if err != windows.ERROR_INSUFFICIENT_BUFFER {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if desiredLen > 1<<20 {
|
||||
// Sanity check before allocating too much.
|
||||
return "", nil
|
||||
}
|
||||
buf = make([]byte, desiredLen)
|
||||
addr = unsafe.Pointer(&buf[0])
|
||||
}
|
||||
|
||||
basicInfo := (*_TCPIP_OWNER_MODULE_BASIC_INFO)(addr)
|
||||
// GetOwnerModuleFromTcp*Entry is apparently using nil as an empty result
|
||||
// under certain circumstances, so we check all the things.
|
||||
if basicInfo == nil || basicInfo.moduleName == nil {
|
||||
if addr == nil {
|
||||
// GetOwnerModuleFromTcp*Entry can apparently return ERROR_SUCCESS
|
||||
// (NO_ERROR) on the first call without the usual first
|
||||
// ERROR_INSUFFICIENT_BUFFER result. Windows said success, so interpret
|
||||
// that was sucessfully not having data.
|
||||
return "", nil
|
||||
}
|
||||
|
||||
basicInfo := (*_TCPIP_OWNER_MODULE_BASIC_INFO)(addr)
|
||||
return windows.UTF16PtrToString(basicInfo.moduleName), nil
|
||||
}
|
||||
|
||||
// GetModule implements OSMetadata.
|
||||
func (m *_MIB_TCPROW_OWNER_MODULE) GetModule() (string, error) {
|
||||
return moduleInfo(m, getOwnerModuleFromTcpEntry)
|
||||
}
|
||||
|
||||
// GetModule implements OSMetadata.
|
||||
func (m *_MIB_TCP6ROW_OWNER_MODULE) GetModule() (string, error) {
|
||||
return moduleInfo(m, getOwnerModuleFromTcp6Entry)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user