Skip to content

Commit

Permalink
Add winiphlpapi
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Jan 30, 2025
1 parent d9f6eb1 commit 2e4c772
Show file tree
Hide file tree
Showing 6 changed files with 660 additions and 4 deletions.
6 changes: 2 additions & 4 deletions common/windnsapi/dnsapi_test.go
Original file line number Diff line number Diff line change
@@ -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())
}
119 changes: 119 additions & 0 deletions common/winiphlpapi/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//go:build windows

package winiphlpapi

import (
"encoding/binary"
"net/netip"
"unsafe"

E "github.com/sagernet/sing/common/exceptions"
)

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 FindTCPPid(source netip.AddrPort, destination netip.AddrPort) (uint32, error) {
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)) ||
destination == netip.AddrPortFrom(DwordToAddr(row.DwRemoteAddr), DwordToPort(row.DwRemotePort)) {
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)) ||
destination == netip.AddrPortFrom(netip.AddrFrom16(row.UcRemoteAddr), DwordToPort(row.DwRemotePort)) {
return row.DwOwningPid, nil
}
}
}
return 0, E.New("process not found for ", source, "-", destination)
}

func FindUDPPid(source netip.AddrPort) (uint32, error) {
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 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))[2:])
}
Loading

0 comments on commit 2e4c772

Please sign in to comment.