Fix: macOS udp find process should use unspecified fallback

This commit is contained in:
Dreamacro 2022-07-15 17:00:41 +08:00 committed by MetaCubeX
parent d71a2ce61e
commit a33e511c12

View File

@ -6,8 +6,6 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/Dreamacro/clash/common/nnip"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -17,11 +15,7 @@ const (
proccallnumpidinfo = 0x2 proccallnumpidinfo = 0x2
) )
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { func findProcessName(network string, ip netip.Addr, port int) (string, error) {
return 0, 0, ErrPlatformNotSupport
}
func findProcessName(network string, ip netip.Addr, port int) (int32, string, error) {
var spath string var spath string
switch network { switch network {
case TCP: case TCP:
@ -29,14 +23,14 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er
case UDP: case UDP:
spath = "net.inet.udp.pcblist_n" spath = "net.inet.udp.pcblist_n"
default: default:
return -1, "", ErrInvalidNetwork return "", ErrInvalidNetwork
} }
isIPv4 := ip.Is4() isIPv4 := ip.Is4()
value, err := syscall.Sysctl(spath) value, err := syscall.Sysctl(spath)
if err != nil { if err != nil {
return -1, "", err return "", err
} }
buf := []byte(value) buf := []byte(value)
@ -50,6 +44,8 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er
// rup8(sizeof(xtcpcb_n)) // rup8(sizeof(xtcpcb_n))
itemSize += 208 itemSize += 208
} }
var fallbackUDPProcess string
// skip the first xinpgen(24 bytes) block // skip the first xinpgen(24 bytes) block
for i := 24; i+itemSize <= len(buf); i += itemSize { for i := 24; i+itemSize <= len(buf); i += itemSize {
// offset of xinpcb_n and xsocket_n // 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 // xinpcb_n.inp_vflag
flag := buf[inp+44] flag := buf[inp+44]
var srcIP netip.Addr var (
srcIP netip.Addr
srcIsIPv4 bool
)
switch { switch {
case flag&0x1 > 0 && isIPv4: case flag&0x1 > 0 && isIPv4:
// ipv4 // ipv4
srcIP = nnip.IpToAddr(buf[inp+76 : inp+80]) srcIP, _ = netip.AddrFromSlice(buf[inp+76 : inp+80])
srcIsIPv4 = true
case flag&0x2 > 0 && !isIPv4: case flag&0x2 > 0 && !isIPv4:
// ipv6 // ipv6
srcIP = nnip.IpToAddr(buf[inp+64 : inp+80]) srcIP, _ = netip.AddrFromSlice(buf[inp+64 : inp+80])
default: default:
continue continue
} }
if ip != srcIP && (network == TCP || !srcIP.IsUnspecified()) { if ip == srcIP {
continue
}
// xsocket_n.so_last_pid // xsocket_n.so_last_pid
pid := readNativeUint32(buf[so+68 : so+72]) pid := readNativeUint32(buf[so+68 : so+72])
pp, err := getExecPathFromPID(pid) return getExecPathFromPID(pid)
return -1, pp, err
} }
return -1, "", ErrNotFound // udp packet connection may be not equal with srcIP
if network == UDP && srcIP.IsUnspecified() && isIPv4 == srcIsIPv4 {
fallbackUDPProcess, _ = getExecPathFromPID(readNativeUint32(buf[so+68 : so+72]))
}
}
if network == UDP && fallbackUDPProcess != "" {
return fallbackUDPProcess, nil
}
return "", ErrNotFound
} }
func getExecPathFromPID(pid uint32) (string, error) { func getExecPathFromPID(pid uint32) (string, error) {