Add winiphlpapi

This commit is contained in:
世界 2025-01-29 19:59:59 +08:00
parent 2b41455f5a
commit ea0ac932ae
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
6 changed files with 780 additions and 4 deletions

View file

@ -1,16 +1,14 @@
//go:build windows
package windnsapi
import (
"runtime"
"testing"
"github.com/stretchr/testify/require"
)
func TestDNSAPI(t *testing.T) {
if runtime.GOOS != "windows" {
t.SkipNow()
}
t.Parallel()
require.NoError(t, FlushResolverCache())
}

View file

@ -0,0 +1,217 @@
//go:build windows
package winiphlpapi
import (
"context"
"encoding/binary"
"net"
"net/netip"
"os"
"time"
"unsafe"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
func LoadEStats() error {
err := modiphlpapi.Load()
if err != nil {
return err
}
err = procGetTcpTable.Find()
if err != nil {
return err
}
err = procGetTcp6Table.Find()
if err != nil {
return err
}
err = procGetPerTcp6ConnectionEStats.Find()
if err != nil {
return err
}
err = procGetPerTcp6ConnectionEStats.Find()
if err != nil {
return err
}
err = procSetPerTcpConnectionEStats.Find()
if err != nil {
return err
}
err = procSetPerTcp6ConnectionEStats.Find()
if err != nil {
return err
}
return nil
}
func LoadExtendedTable() error {
err := modiphlpapi.Load()
if err != nil {
return err
}
err = procGetExtendedTcpTable.Find()
if err != nil {
return err
}
err = procGetExtendedUdpTable.Find()
if err != nil {
return err
}
return nil
}
func FindPid(network string, source netip.AddrPort) (uint32, error) {
switch N.NetworkName(network) {
case N.NetworkTCP:
if source.Addr().Is4() {
tcpTable, err := GetExtendedTcpTable()
if err != nil {
return 0, err
}
for _, row := range tcpTable {
if source == netip.AddrPortFrom(DwordToAddr(row.DwLocalAddr), DwordToPort(row.DwLocalPort)) {
return row.DwOwningPid, nil
}
}
} else {
tcpTable, err := GetExtendedTcp6Table()
if err != nil {
return 0, err
}
for _, row := range tcpTable {
if source == netip.AddrPortFrom(netip.AddrFrom16(row.UcLocalAddr), DwordToPort(row.DwLocalPort)) {
return row.DwOwningPid, nil
}
}
}
case N.NetworkUDP:
if source.Addr().Is4() {
udpTable, err := GetExtendedUdpTable()
if err != nil {
return 0, err
}
for _, row := range udpTable {
if source == netip.AddrPortFrom(DwordToAddr(row.DwLocalAddr), DwordToPort(row.DwLocalPort)) {
return row.DwOwningPid, nil
}
}
} else {
udpTable, err := GetExtendedUdp6Table()
if err != nil {
return 0, err
}
for _, row := range udpTable {
if source == netip.AddrPortFrom(netip.AddrFrom16(row.UcLocalAddr), DwordToPort(row.DwLocalPort)) {
return row.DwOwningPid, nil
}
}
}
}
return 0, E.New("process not found for ", source)
}
func WriteAndWaitAck(ctx context.Context, conn net.Conn, payload []byte) error {
source := M.AddrPortFromNet(conn.LocalAddr())
destination := M.AddrPortFromNet(conn.RemoteAddr())
if source.Addr().Is4() {
tcpTable, err := GetTcpTable()
if err != nil {
return err
}
var tcpRow *MibTcpRow
for _, row := range tcpTable {
if source == netip.AddrPortFrom(DwordToAddr(row.DwLocalAddr), DwordToPort(row.DwLocalPort)) ||
destination == netip.AddrPortFrom(DwordToAddr(row.DwRemoteAddr), DwordToPort(row.DwRemotePort)) {
tcpRow = &row
break
}
}
if tcpRow == nil {
return E.New("row not found for: ", source)
}
err = SetPerTcpConnectionEStatsSendBuffer(tcpRow, &TcpEstatsSendBuffRwV0{
EnableCollection: true,
})
if err != nil {
return os.NewSyscallError("SetPerTcpConnectionEStatsSendBufferV0", err)
}
defer SetPerTcpConnectionEStatsSendBuffer(tcpRow, &TcpEstatsSendBuffRwV0{
EnableCollection: false,
})
_, err = conn.Write(payload)
if err != nil {
return err
}
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
eStstsSendBuffer, err := GetPerTcpConnectionEStatsSendBuffer(tcpRow)
if err != nil {
return err
}
if eStstsSendBuffer.CurRetxQueue == 0 {
return nil
}
time.Sleep(10 * time.Millisecond)
}
} else {
tcpTable, err := GetTcp6Table()
if err != nil {
return err
}
var tcpRow *MibTcp6Row
for _, row := range tcpTable {
if source == netip.AddrPortFrom(netip.AddrFrom16(row.LocalAddr), DwordToPort(row.LocalPort)) ||
destination == netip.AddrPortFrom(netip.AddrFrom16(row.RemoteAddr), DwordToPort(row.RemotePort)) {
tcpRow = &row
break
}
}
if tcpRow == nil {
return E.New("row not found for: ", source)
}
err = SetPerTcp6ConnectionEStatsSendBuffer(tcpRow, &TcpEstatsSendBuffRwV0{
EnableCollection: true,
})
if err != nil {
return os.NewSyscallError("SetPerTcpConnectionEStatsSendBufferV0", err)
}
defer SetPerTcp6ConnectionEStatsSendBuffer(tcpRow, &TcpEstatsSendBuffRwV0{
EnableCollection: false,
})
_, err = conn.Write(payload)
if err != nil {
return err
}
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
eStstsSendBuffer, err := GetPerTcp6ConnectionEStatsSendBuffer(tcpRow)
if err != nil {
return err
}
if eStstsSendBuffer.CurRetxQueue == 0 {
return nil
}
time.Sleep(10 * time.Millisecond)
}
}
}
func DwordToAddr(addr uint32) netip.Addr {
return netip.AddrFrom4(*(*[4]byte)(unsafe.Pointer(&addr)))
}
func DwordToPort(dword uint32) uint16 {
return binary.BigEndian.Uint16((*[4]byte)(unsafe.Pointer(&dword))[:])
}

View file

@ -0,0 +1,313 @@
//go:build windows
package winiphlpapi
import (
"errors"
"os"
"unsafe"
"golang.org/x/sys/windows"
)
const (
TcpTableBasicListener uint32 = iota
TcpTableBasicConnections
TcpTableBasicAll
TcpTableOwnerPidListener
TcpTableOwnerPidConnections
TcpTableOwnerPidAll
TcpTableOwnerModuleListener
TcpTableOwnerModuleConnections
TcpTableOwnerModuleAll
)
const (
UdpTableBasic uint32 = iota
UdpTableOwnerPid
UdpTableOwnerModule
)
const (
TcpConnectionEstatsSynOpts uint32 = iota
TcpConnectionEstatsData
TcpConnectionEstatsSndCong
TcpConnectionEstatsPath
TcpConnectionEstatsSendBuff
TcpConnectionEstatsRec
TcpConnectionEstatsObsRec
TcpConnectionEstatsBandwidth
TcpConnectionEstatsFineRtt
TcpConnectionEstatsMaximum
)
type MibTcpTable struct {
DwNumEntries uint32
Table [1]MibTcpRow
}
type MibTcpRow struct {
DwState uint32
DwLocalAddr uint32
DwLocalPort uint32
DwRemoteAddr uint32
DwRemotePort uint32
}
type MibTcp6Table struct {
DwNumEntries uint32
Table [1]MibTcp6Row
}
type MibTcp6Row struct {
State uint32
LocalAddr [16]byte
LocalScopeId uint32
LocalPort uint32
RemoteAddr [16]byte
RemoteScopeId uint32
RemotePort uint32
}
type MibTcpTableOwnerPid struct {
DwNumEntries uint32
Table [1]MibTcpRowOwnerPid
}
type MibTcpRowOwnerPid struct {
DwState uint32
DwLocalAddr uint32
DwLocalPort uint32
DwRemoteAddr uint32
DwRemotePort uint32
DwOwningPid uint32
}
type MibTcp6TableOwnerPid struct {
DwNumEntries uint32
Table [1]MibTcp6RowOwnerPid
}
type MibTcp6RowOwnerPid struct {
UcLocalAddr [16]byte
DwLocalScopeId uint32
DwLocalPort uint32
UcRemoteAddr [16]byte
DwRemoteScopeId uint32
DwRemotePort uint32
DwState uint32
DwOwningPid uint32
}
type MibUdpTableOwnerPid struct {
DwNumEntries uint32
Table [1]MibUdpRowOwnerPid
}
type MibUdpRowOwnerPid struct {
DwLocalAddr uint32
DwLocalPort uint32
DwOwningPid uint32
}
type MibUdp6TableOwnerPid struct {
DwNumEntries uint32
Table [1]MibUdp6RowOwnerPid
}
type MibUdp6RowOwnerPid struct {
UcLocalAddr [16]byte
DwLocalScopeId uint32
DwLocalPort uint32
DwOwningPid uint32
}
type TcpEstatsSendBufferRodV0 struct {
CurRetxQueue uint64
MaxRetxQueue uint64
CurAppWQueue uint64
MaxAppWQueue uint64
}
type TcpEstatsSendBuffRwV0 struct {
EnableCollection bool
}
const (
offsetOfMibTcpTable = unsafe.Offsetof(MibTcpTable{}.Table)
offsetOfMibTcp6Table = unsafe.Offsetof(MibTcp6Table{}.Table)
offsetOfMibTcpTableOwnerPid = unsafe.Offsetof(MibTcpTableOwnerPid{}.Table)
offsetOfMibTcp6TableOwnerPid = unsafe.Offsetof(MibTcpTableOwnerPid{}.Table)
offsetOfMibUdpTableOwnerPid = unsafe.Offsetof(MibUdpTableOwnerPid{}.Table)
offsetOfMibUdp6TableOwnerPid = unsafe.Offsetof(MibUdp6TableOwnerPid{}.Table)
sizeOfTcpEstatsSendBuffRwV0 = unsafe.Sizeof(TcpEstatsSendBuffRwV0{})
sizeOfTcpEstatsSendBufferRodV0 = unsafe.Sizeof(TcpEstatsSendBufferRodV0{})
)
func GetTcpTable() ([]MibTcpRow, error) {
var size uint32
err := getTcpTable(nil, &size, false)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
for {
table := make([]byte, size)
err = getTcpTable(&table[0], &size, false)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, err
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibTcpRow)(unsafe.Pointer(&table[offsetOfMibTcpTable])), dwNumEntries), nil
}
}
func GetTcp6Table() ([]MibTcp6Row, error) {
var size uint32
err := getTcp6Table(nil, &size, false)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
for {
table := make([]byte, size)
err = getTcp6Table(&table[0], &size, false)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, err
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibTcp6Row)(unsafe.Pointer(&table[offsetOfMibTcp6Table])), dwNumEntries), nil
}
}
func GetExtendedTcpTable() ([]MibTcpRowOwnerPid, error) {
var size uint32
err := getExtendedTcpTable(nil, &size, false, windows.AF_INET, TcpTableOwnerPidConnections, 0)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, os.NewSyscallError("GetExtendedTcpTable", err)
}
for {
table := make([]byte, size)
err = getExtendedTcpTable(&table[0], &size, false, windows.AF_INET, TcpTableOwnerPidConnections, 0)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, os.NewSyscallError("GetExtendedTcpTable", err)
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibTcpRowOwnerPid)(unsafe.Pointer(&table[offsetOfMibTcpTableOwnerPid])), dwNumEntries), nil
}
}
func GetExtendedTcp6Table() ([]MibTcp6RowOwnerPid, error) {
var size uint32
err := getExtendedTcpTable(nil, &size, false, windows.AF_INET6, TcpTableOwnerPidConnections, 0)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, os.NewSyscallError("GetExtendedTcpTable", err)
}
for {
table := make([]byte, size)
err = getExtendedTcpTable(&table[0], &size, false, windows.AF_INET6, TcpTableOwnerPidConnections, 0)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, os.NewSyscallError("GetExtendedTcpTable", err)
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibTcp6RowOwnerPid)(unsafe.Pointer(&table[offsetOfMibTcp6TableOwnerPid])), dwNumEntries), nil
}
}
func GetExtendedUdpTable() ([]MibUdpRowOwnerPid, error) {
var size uint32
err := getExtendedUdpTable(nil, &size, false, windows.AF_INET, UdpTableOwnerPid, 0)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, os.NewSyscallError("GetExtendedUdpTable", err)
}
for {
table := make([]byte, size)
err = getExtendedUdpTable(&table[0], &size, false, windows.AF_INET, UdpTableOwnerPid, 0)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, os.NewSyscallError("GetExtendedUdpTable", err)
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibUdpRowOwnerPid)(unsafe.Pointer(&table[offsetOfMibUdpTableOwnerPid])), dwNumEntries), nil
}
}
func GetExtendedUdp6Table() ([]MibUdp6RowOwnerPid, error) {
var size uint32
err := getExtendedUdpTable(nil, &size, false, windows.AF_INET6, UdpTableOwnerPid, 0)
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, os.NewSyscallError("GetExtendedUdpTable", err)
}
for {
table := make([]byte, size)
err = getExtendedUdpTable(&table[0], &size, false, windows.AF_INET6, UdpTableOwnerPid, 0)
if err != nil {
if errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
continue
}
return nil, os.NewSyscallError("GetExtendedUdpTable", err)
}
dwNumEntries := int(*(*uint32)(unsafe.Pointer(&table[0])))
return unsafe.Slice((*MibUdp6RowOwnerPid)(unsafe.Pointer(&table[offsetOfMibUdp6TableOwnerPid])), dwNumEntries), nil
}
}
func GetPerTcpConnectionEStatsSendBuffer(row *MibTcpRow) (*TcpEstatsSendBufferRodV0, error) {
var rod TcpEstatsSendBufferRodV0
err := getPerTcpConnectionEStats(row,
TcpConnectionEstatsSendBuff,
0,
0,
0,
0,
0,
0,
uintptr(unsafe.Pointer(&rod)),
0,
uint64(sizeOfTcpEstatsSendBufferRodV0),
)
if err != nil {
return nil, err
}
return &rod, nil
}
func GetPerTcp6ConnectionEStatsSendBuffer(row *MibTcp6Row) (*TcpEstatsSendBufferRodV0, error) {
var rod TcpEstatsSendBufferRodV0
err := getPerTcp6ConnectionEStats(row,
TcpConnectionEstatsSendBuff,
0,
0,
0,
0,
0,
0,
uintptr(unsafe.Pointer(&rod)),
0,
uint64(sizeOfTcpEstatsSendBufferRodV0),
)
if err != nil {
return nil, err
}
return &rod, nil
}
func SetPerTcpConnectionEStatsSendBuffer(row *MibTcpRow, rw *TcpEstatsSendBuffRwV0) error {
return setPerTcpConnectionEStats(row, TcpConnectionEstatsSendBuff, uintptr(unsafe.Pointer(&rw)), 0, uint64(sizeOfTcpEstatsSendBuffRwV0), 0)
}
func SetPerTcp6ConnectionEStatsSendBuffer(row *MibTcp6Row, rw *TcpEstatsSendBuffRwV0) error {
return setPerTcp6ConnectionEStats(row, TcpConnectionEstatsSendBuff, uintptr(unsafe.Pointer(&rw)), 0, uint64(sizeOfTcpEstatsSendBuffRwV0), 0)
}

View file

@ -0,0 +1,90 @@
//go:build windows
package winiphlpapi_test
import (
"context"
"net"
"syscall"
"testing"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/winiphlpapi"
"github.com/stretchr/testify/require"
)
func TestFindPidTcp4(t *testing.T) {
t.Parallel()
listener, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
defer listener.Close()
go listener.Accept()
conn, err := net.Dial("tcp", listener.Addr().String())
require.NoError(t, err)
defer conn.Close()
pid, err := winiphlpapi.FindPid(N.NetworkTCP, M.AddrPortFromNet(conn.LocalAddr()))
require.NoError(t, err)
require.Equal(t, uint32(syscall.Getpid()), pid)
}
func TestFindPidTcp6(t *testing.T) {
t.Parallel()
listener, err := net.Listen("tcp", "[::1]:0")
require.NoError(t, err)
defer listener.Close()
go listener.Accept()
conn, err := net.Dial("tcp", listener.Addr().String())
require.NoError(t, err)
defer conn.Close()
pid, err := winiphlpapi.FindPid(N.NetworkTCP, M.AddrPortFromNet(conn.LocalAddr()))
require.NoError(t, err)
require.Equal(t, uint32(syscall.Getpid()), pid)
}
func TestFindPidUdp4(t *testing.T) {
t.Parallel()
conn, err := net.ListenPacket("udp", "127.0.0.1:0")
require.NoError(t, err)
defer conn.Close()
pid, err := winiphlpapi.FindPid(N.NetworkUDP, M.AddrPortFromNet(conn.LocalAddr()))
require.NoError(t, err)
require.Equal(t, uint32(syscall.Getpid()), pid)
}
func TestFindPidUdp6(t *testing.T) {
t.Parallel()
conn, err := net.ListenPacket("udp", "[::1]:0")
require.NoError(t, err)
defer conn.Close()
pid, err := winiphlpapi.FindPid(N.NetworkUDP, M.AddrPortFromNet(conn.LocalAddr()))
require.NoError(t, err)
require.Equal(t, uint32(syscall.Getpid()), pid)
}
func TestWaitAck4(t *testing.T) {
t.Parallel()
listener, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
defer listener.Close()
go listener.Accept()
conn, err := net.Dial("tcp", listener.Addr().String())
require.NoError(t, err)
defer conn.Close()
err = winiphlpapi.WriteAndWaitAck(context.Background(), conn, []byte("hello"))
require.NoError(t, err)
}
func TestWaitAck6(t *testing.T) {
t.Parallel()
listener, err := net.Listen("tcp", "[::1]:0")
require.NoError(t, err)
defer listener.Close()
go listener.Accept()
conn, err := net.Dial("tcp", listener.Addr().String())
require.NoError(t, err)
defer conn.Close()
err = winiphlpapi.WriteAndWaitAck(context.Background(), conn, []byte("hello"))
require.NoError(t, err)
}

View file

@ -0,0 +1,27 @@
package winiphlpapi
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcptable
//sys getTcpTable(tcpTable *byte, sizePointer *uint32, order bool) (errcode error) = iphlpapi.GetTcpTable
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcp6table
//sys getTcp6Table(tcpTable *byte, sizePointer *uint32, order bool) (errcode error) = iphlpapi.GetTcp6Table
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getpertcpconnectionestats
//sys getPerTcpConnectionEStats(row *MibTcpRow, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, ros uintptr, rosVersion uint64, rosSize uint64, rod uintptr, rodVersion uint64, rodSize uint64) (errcode error) = iphlpapi.GetPerTcpConnectionEStats
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getpertcp6connectionestats
//sys getPerTcp6ConnectionEStats(row *MibTcp6Row, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, ros uintptr, rosVersion uint64, rosSize uint64, rod uintptr, rodVersion uint64, rodSize uint64) (errcode error) = iphlpapi.GetPerTcp6ConnectionEStats
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-setpertcpconnectionestats
//sys setPerTcpConnectionEStats(row *MibTcpRow, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, offset uint64) (errcode error) = iphlpapi.SetPerTcpConnectionEStats
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-setpertcp6connectionestats
//sys setPerTcp6ConnectionEStats(row *MibTcp6Row, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, offset uint64) (errcode error) = iphlpapi.SetPerTcp6ConnectionEStats
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getextendedtcptable
//sys getExtendedTcpTable(pTcpTable *byte, pdwSize *uint32, bOrder bool, ulAf uint64, tableClass uint32, reserved uint64) = (errcode error) = iphlpapi.GetExtendedTcpTable
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getextendedudptable
//sys getExtendedUdpTable(pUdpTable *byte, pdwSize *uint32, bOrder bool, ulAf uint64, tableClass uint32, reserved uint64) = (errcode error) = iphlpapi.GetExtendedUdpTable

View file

@ -0,0 +1,131 @@
// Code generated by 'go generate'; DO NOT EDIT.
package winiphlpapi
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procGetExtendedTcpTable = modiphlpapi.NewProc("GetExtendedTcpTable")
procGetExtendedUdpTable = modiphlpapi.NewProc("GetExtendedUdpTable")
procGetPerTcp6ConnectionEStats = modiphlpapi.NewProc("GetPerTcp6ConnectionEStats")
procGetPerTcpConnectionEStats = modiphlpapi.NewProc("GetPerTcpConnectionEStats")
procGetTcp6Table = modiphlpapi.NewProc("GetTcp6Table")
procGetTcpTable = modiphlpapi.NewProc("GetTcpTable")
procSetPerTcp6ConnectionEStats = modiphlpapi.NewProc("SetPerTcp6ConnectionEStats")
procSetPerTcpConnectionEStats = modiphlpapi.NewProc("SetPerTcpConnectionEStats")
)
func getExtendedTcpTable(pTcpTable *byte, pdwSize *uint32, bOrder bool, ulAf uint64, tableClass uint32, reserved uint64) (errcode error) {
var _p0 uint32
if bOrder {
_p0 = 1
}
r0, _, _ := syscall.Syscall6(procGetExtendedTcpTable.Addr(), 6, uintptr(unsafe.Pointer(pTcpTable)), uintptr(unsafe.Pointer(pdwSize)), uintptr(_p0), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func getExtendedUdpTable(pUdpTable *byte, pdwSize *uint32, bOrder bool, ulAf uint64, tableClass uint32, reserved uint64) (errcode error) {
var _p0 uint32
if bOrder {
_p0 = 1
}
r0, _, _ := syscall.Syscall6(procGetExtendedUdpTable.Addr(), 6, uintptr(unsafe.Pointer(pUdpTable)), uintptr(unsafe.Pointer(pdwSize)), uintptr(_p0), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func getPerTcp6ConnectionEStats(row *MibTcp6Row, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, ros uintptr, rosVersion uint64, rosSize uint64, rod uintptr, rodVersion uint64, rodSize uint64) (errcode error) {
r0, _, _ := syscall.Syscall12(procGetPerTcp6ConnectionEStats.Addr(), 11, uintptr(unsafe.Pointer(row)), uintptr(estatsType), uintptr(rw), uintptr(rwVersion), uintptr(rwSize), uintptr(ros), uintptr(rosVersion), uintptr(rosSize), uintptr(rod), uintptr(rodVersion), uintptr(rodSize), 0)
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func getPerTcpConnectionEStats(row *MibTcpRow, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, ros uintptr, rosVersion uint64, rosSize uint64, rod uintptr, rodVersion uint64, rodSize uint64) (errcode error) {
r0, _, _ := syscall.Syscall12(procGetPerTcpConnectionEStats.Addr(), 11, uintptr(unsafe.Pointer(row)), uintptr(estatsType), uintptr(rw), uintptr(rwVersion), uintptr(rwSize), uintptr(ros), uintptr(rosVersion), uintptr(rosSize), uintptr(rod), uintptr(rodVersion), uintptr(rodSize), 0)
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func getTcp6Table(tcpTable *byte, sizePointer *uint32, order bool) (errcode error) {
var _p0 uint32
if order {
_p0 = 1
}
r0, _, _ := syscall.Syscall(procGetTcp6Table.Addr(), 3, uintptr(unsafe.Pointer(tcpTable)), uintptr(unsafe.Pointer(sizePointer)), uintptr(_p0))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func getTcpTable(tcpTable *byte, sizePointer *uint32, order bool) (errcode error) {
var _p0 uint32
if order {
_p0 = 1
}
r0, _, _ := syscall.Syscall(procGetTcpTable.Addr(), 3, uintptr(unsafe.Pointer(tcpTable)), uintptr(unsafe.Pointer(sizePointer)), uintptr(_p0))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func setPerTcp6ConnectionEStats(row *MibTcp6Row, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, offset uint64) (errcode error) {
r0, _, _ := syscall.Syscall6(procSetPerTcp6ConnectionEStats.Addr(), 6, uintptr(unsafe.Pointer(row)), uintptr(estatsType), uintptr(rw), uintptr(rwVersion), uintptr(rwSize), uintptr(offset))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}
func setPerTcpConnectionEStats(row *MibTcpRow, estatsType uint32, rw uintptr, rwVersion uint64, rwSize uint64, offset uint64) (errcode error) {
r0, _, _ := syscall.Syscall6(procSetPerTcpConnectionEStats.Addr(), 6, uintptr(unsafe.Pointer(row)), uintptr(estatsType), uintptr(rw), uintptr(rwVersion), uintptr(rwSize), uintptr(offset))
if r0 != 0 {
errcode = syscall.Errno(r0)
}
return
}