Update dependencies
This commit is contained in:
35
vendor/tailscale.com/net/netstat/netstat.go
generated
vendored
Normal file
35
vendor/tailscale.com/net/netstat/netstat.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Package netstat returns the local machine's network connection table.
|
||||
package netstat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var ErrNotImplemented = errors.New("not implemented for GOOS=" + runtime.GOOS)
|
||||
|
||||
type Entry struct {
|
||||
Local, Remote netip.AddrPort
|
||||
Pid int
|
||||
State string // TODO: type?
|
||||
OSMetadata OSMetadata
|
||||
}
|
||||
|
||||
// Table contains local machine's TCP connection entries.
|
||||
//
|
||||
// Currently only TCP (IPv4 and IPv6) are included.
|
||||
type Table struct {
|
||||
Entries []Entry
|
||||
}
|
||||
|
||||
// Get returns the connection table.
|
||||
//
|
||||
// It returns ErrNotImplemented if the table is not available for the
|
||||
// current operating system.
|
||||
func Get() (*Table, error) {
|
||||
return get()
|
||||
}
|
||||
14
vendor/tailscale.com/net/netstat/netstat_noimpl.go
generated
vendored
Normal file
14
vendor/tailscale.com/net/netstat/netstat_noimpl.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package netstat
|
||||
|
||||
// OSMetadata includes any additional OS-specific information that may be
|
||||
// obtained during the retrieval of a given Entry.
|
||||
type OSMetadata struct{}
|
||||
|
||||
func get() (*Table, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
287
vendor/tailscale.com/net/netstat/netstat_windows.go
generated
vendored
Normal file
287
vendor/tailscale.com/net/netstat/netstat_windows.go
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package netstat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"net/netip"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/cpu"
|
||||
"golang.org/x/sys/windows"
|
||||
"tailscale.com/net/netaddr"
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// See https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getextendedtcptable
|
||||
|
||||
// TCP_TABLE_OWNER_MODULE_ALL means to include the PID and module. The table type
|
||||
// we get back from Windows depends on AF_INET vs AF_INET6:
|
||||
// MIB_TCPTABLE_OWNER_MODULE for v4 or MIB_TCP6TABLE_OWNER_MODULE for v6.
|
||||
const tcpTableOwnerModuleAll = 8
|
||||
|
||||
// TCPIP_OWNER_MODULE_BASIC_INFO means to request "basic information" about the
|
||||
// owner module.
|
||||
const tcpipOwnerModuleBasicInfo = 0
|
||||
|
||||
var (
|
||||
iphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
|
||||
getTCPTable = iphlpapi.NewProc("GetExtendedTcpTable")
|
||||
getOwnerModuleFromTcpEntry = iphlpapi.NewProc("GetOwnerModuleFromTcpEntry")
|
||||
getOwnerModuleFromTcp6Entry = iphlpapi.NewProc("GetOwnerModuleFromTcp6Entry")
|
||||
// TODO: GetExtendedUdpTable also? if/when needed.
|
||||
)
|
||||
|
||||
// See https://web.archive.org/web/20221219211913/https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow_owner_module
|
||||
type _MIB_TCPROW_OWNER_MODULE struct {
|
||||
state uint32
|
||||
localAddr uint32
|
||||
localPort uint32
|
||||
remoteAddr uint32
|
||||
remotePort uint32
|
||||
pid uint32
|
||||
createTimestamp int64
|
||||
owningModuleInfo [16]uint64
|
||||
}
|
||||
|
||||
func (row *_MIB_TCPROW_OWNER_MODULE) asEntry() Entry {
|
||||
return Entry{
|
||||
Local: ipport4(row.localAddr, port(&row.localPort)),
|
||||
Remote: ipport4(row.remoteAddr, port(&row.remotePort)),
|
||||
Pid: int(row.pid),
|
||||
State: state(row.state),
|
||||
OSMetadata: row,
|
||||
}
|
||||
}
|
||||
|
||||
type _MIB_TCPTABLE_OWNER_MODULE struct {
|
||||
numEntries uint32
|
||||
table _MIB_TCPROW_OWNER_MODULE
|
||||
}
|
||||
|
||||
func (m *_MIB_TCPTABLE_OWNER_MODULE) getRows() []_MIB_TCPROW_OWNER_MODULE {
|
||||
return unsafe.Slice(&m.table, m.numEntries)
|
||||
}
|
||||
|
||||
// See https://web.archive.org/web/20221219212442/https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcp6row_owner_module
|
||||
type _MIB_TCP6ROW_OWNER_MODULE struct {
|
||||
localAddr [16]byte
|
||||
localScope uint32
|
||||
localPort uint32
|
||||
remoteAddr [16]byte
|
||||
remoteScope uint32
|
||||
remotePort uint32
|
||||
state uint32
|
||||
pid uint32
|
||||
createTimestamp int64
|
||||
owningModuleInfo [16]uint64
|
||||
}
|
||||
|
||||
func (row *_MIB_TCP6ROW_OWNER_MODULE) asEntry() Entry {
|
||||
return Entry{
|
||||
Local: ipport6(row.localAddr, row.localScope, port(&row.localPort)),
|
||||
Remote: ipport6(row.remoteAddr, row.remoteScope, port(&row.remotePort)),
|
||||
Pid: int(row.pid),
|
||||
State: state(row.state),
|
||||
OSMetadata: row,
|
||||
}
|
||||
}
|
||||
|
||||
type _MIB_TCP6TABLE_OWNER_MODULE struct {
|
||||
numEntries uint32
|
||||
table _MIB_TCP6ROW_OWNER_MODULE
|
||||
}
|
||||
|
||||
func (m *_MIB_TCP6TABLE_OWNER_MODULE) getRows() []_MIB_TCP6ROW_OWNER_MODULE {
|
||||
return unsafe.Slice(&m.table, m.numEntries)
|
||||
}
|
||||
|
||||
// See https://web.archive.org/web/20221219213143/https://learn.microsoft.com/en-us/windows/win32/api/iprtrmib/ns-iprtrmib-tcpip_owner_module_basic_info
|
||||
type _TCPIP_OWNER_MODULE_BASIC_INFO struct {
|
||||
moduleName *uint16
|
||||
modulePath *uint16
|
||||
}
|
||||
|
||||
func get() (*Table, error) {
|
||||
t := new(Table)
|
||||
if err := t.addEntries(windows.AF_INET); err != nil {
|
||||
return nil, fmt.Errorf("failed to get IPv4 entries: %w", err)
|
||||
}
|
||||
if err := t.addEntries(windows.AF_INET6); err != nil {
|
||||
return nil, fmt.Errorf("failed to get IPv6 entries: %w", err)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (t *Table) addEntries(fam int) error {
|
||||
var size uint32
|
||||
var addr unsafe.Pointer
|
||||
var buf []byte
|
||||
for {
|
||||
err, _, _ := getTCPTable.Call(
|
||||
uintptr(addr),
|
||||
uintptr(unsafe.Pointer(&size)),
|
||||
1, // sorted
|
||||
uintptr(fam),
|
||||
tcpTableOwnerModuleAll,
|
||||
0, // reserved; "must be zero"
|
||||
)
|
||||
if err == 0 {
|
||||
break
|
||||
}
|
||||
if err == uintptr(windows.ERROR_INSUFFICIENT_BUFFER) {
|
||||
const maxSize = 10 << 20
|
||||
if size > maxSize || size < 4 {
|
||||
return fmt.Errorf("unreasonable kernel-reported size %d", size)
|
||||
}
|
||||
buf = make([]byte, size)
|
||||
addr = unsafe.Pointer(&buf[0])
|
||||
continue
|
||||
}
|
||||
return windows.Errno(err)
|
||||
}
|
||||
if len(buf) < int(size) {
|
||||
return errors.New("unexpected size growth from system call")
|
||||
}
|
||||
buf = buf[:size]
|
||||
|
||||
switch fam {
|
||||
case windows.AF_INET:
|
||||
info := (*_MIB_TCPTABLE_OWNER_MODULE)(unsafe.Pointer(&buf[0]))
|
||||
rows := info.getRows()
|
||||
for _, row := range rows {
|
||||
t.Entries = append(t.Entries, row.asEntry())
|
||||
}
|
||||
case windows.AF_INET6:
|
||||
info := (*_MIB_TCP6TABLE_OWNER_MODULE)(unsafe.Pointer(&buf[0]))
|
||||
rows := info.getRows()
|
||||
for _, row := range rows {
|
||||
t.Entries = append(t.Entries, row.asEntry())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var states = []string{
|
||||
"",
|
||||
"CLOSED",
|
||||
"LISTEN",
|
||||
"SYN-SENT",
|
||||
"SYN-RECEIVED",
|
||||
"ESTABLISHED",
|
||||
"FIN-WAIT-1",
|
||||
"FIN-WAIT-2",
|
||||
"CLOSE-WAIT",
|
||||
"CLOSING",
|
||||
"LAST-ACK",
|
||||
"DELETE-TCB",
|
||||
}
|
||||
|
||||
func state(v uint32) string {
|
||||
if v < uint32(len(states)) {
|
||||
return states[v]
|
||||
}
|
||||
return fmt.Sprintf("unknown-state-%d", v)
|
||||
}
|
||||
|
||||
func ipport4(addr uint32, port uint16) netip.AddrPort {
|
||||
if !cpu.IsBigEndian {
|
||||
addr = bits.ReverseBytes32(addr)
|
||||
}
|
||||
return netip.AddrPortFrom(
|
||||
netaddr.IPv4(byte(addr>>24), byte(addr>>16), byte(addr>>8), byte(addr)),
|
||||
port)
|
||||
}
|
||||
|
||||
func ipport6(addr [16]byte, scope uint32, port uint16) netip.AddrPort {
|
||||
ip := netip.AddrFrom16(addr).Unmap()
|
||||
if scope != 0 {
|
||||
// TODO: something better here?
|
||||
ip = ip.WithZone(fmt.Sprint(scope))
|
||||
}
|
||||
return netip.AddrPortFrom(ip, port)
|
||||
}
|
||||
|
||||
func port(v *uint32) uint16 {
|
||||
if !cpu.IsBigEndian {
|
||||
return uint16(bits.ReverseBytes32(*v) >> 16)
|
||||
}
|
||||
return uint16(*v >> 16)
|
||||
}
|
||||
|
||||
type moduleInfoConstraint interface {
|
||||
_MIB_TCPROW_OWNER_MODULE | _MIB_TCP6ROW_OWNER_MODULE
|
||||
}
|
||||
|
||||
// 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
|
||||
var addr unsafe.Pointer
|
||||
|
||||
for {
|
||||
e, _, _ := proc.Call(
|
||||
uintptr(unsafe.Pointer(entry)),
|
||||
uintptr(tcpipOwnerModuleBasicInfo),
|
||||
uintptr(addr),
|
||||
uintptr(unsafe.Pointer(&desiredLen)),
|
||||
)
|
||||
err := windows.Errno(e)
|
||||
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])
|
||||
}
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user