From a33e511c12d045b294946baba01a699763a346b2 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+dreamacro@users.noreply.github.com> Date: Fri, 15 Jul 2022 17:00:41 +0800 Subject: [PATCH] Fix: macOS udp find process should use unspecified fallback --- component/process/process_darwin.go | 44 ++++++++++++++++------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/component/process/process_darwin.go b/component/process/process_darwin.go index ef8f6e0e2..2728aad05 100644 --- a/component/process/process_darwin.go +++ b/component/process/process_darwin.go @@ -6,8 +6,6 @@ import ( "syscall" "unsafe" - "github.com/Dreamacro/clash/common/nnip" - "golang.org/x/sys/unix" ) @@ -17,11 +15,7 @@ const ( proccallnumpidinfo = 0x2 ) -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { - return 0, 0, ErrPlatformNotSupport -} - -func findProcessName(network string, ip netip.Addr, port int) (int32, string, error) { +func findProcessName(network string, ip netip.Addr, port int) (string, error) { var spath string switch network { case TCP: @@ -29,14 +23,14 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er case UDP: spath = "net.inet.udp.pcblist_n" default: - return -1, "", ErrInvalidNetwork + return "", ErrInvalidNetwork } isIPv4 := ip.Is4() value, err := syscall.Sysctl(spath) if err != nil { - return -1, "", err + return "", err } buf := []byte(value) @@ -50,6 +44,8 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er // rup8(sizeof(xtcpcb_n)) itemSize += 208 } + + var fallbackUDPProcess string // skip the first xinpgen(24 bytes) block for i := 24; i+itemSize <= len(buf); i += itemSize { // offset of xinpcb_n and xsocket_n @@ -63,29 +59,39 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er // xinpcb_n.inp_vflag flag := buf[inp+44] - var srcIP netip.Addr + var ( + srcIP netip.Addr + srcIsIPv4 bool + ) switch { case flag&0x1 > 0 && isIPv4: // ipv4 - srcIP = nnip.IpToAddr(buf[inp+76 : inp+80]) + srcIP, _ = netip.AddrFromSlice(buf[inp+76 : inp+80]) + srcIsIPv4 = true case flag&0x2 > 0 && !isIPv4: // ipv6 - srcIP = nnip.IpToAddr(buf[inp+64 : inp+80]) + srcIP, _ = netip.AddrFromSlice(buf[inp+64 : inp+80]) default: continue } - if ip != srcIP && (network == TCP || !srcIP.IsUnspecified()) { - continue + if ip == srcIP { + // xsocket_n.so_last_pid + pid := readNativeUint32(buf[so+68 : so+72]) + return getExecPathFromPID(pid) } - // xsocket_n.so_last_pid - pid := readNativeUint32(buf[so+68 : so+72]) - pp, err := getExecPathFromPID(pid) - return -1, pp, err + // udp packet connection may be not equal with srcIP + if network == UDP && srcIP.IsUnspecified() && isIPv4 == srcIsIPv4 { + fallbackUDPProcess, _ = getExecPathFromPID(readNativeUint32(buf[so+68 : so+72])) + } } - return -1, "", ErrNotFound + if network == UDP && fallbackUDPProcess != "" { + return fallbackUDPProcess, nil + } + + return "", ErrNotFound } func getExecPathFromPID(pid uint32) (string, error) {