mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package nameserver
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
|
|
processInfo "github.com/shirou/gopsutil/process"
|
|
|
|
"github.com/safing/portbase/log"
|
|
"github.com/safing/portmaster/service/network/packet"
|
|
"github.com/safing/portmaster/service/network/state"
|
|
)
|
|
|
|
var commonResolverIPs = []net.IP{
|
|
net.IPv4zero,
|
|
net.IPv4(127, 0, 0, 1), // default
|
|
net.IPv4(127, 0, 0, 53), // some resolvers on Linux
|
|
net.IPv6zero,
|
|
net.IPv6loopback,
|
|
}
|
|
|
|
func findConflictingProcess(ip net.IP, port uint16) (conflictingProcess *processInfo.Process) {
|
|
// Evaluate which IPs to check.
|
|
var ipsToCheck []net.IP
|
|
if ip.Equal(net.IPv4zero) || ip.Equal(net.IPv6zero) {
|
|
ipsToCheck = commonResolverIPs
|
|
} else {
|
|
ipsToCheck = []net.IP{ip}
|
|
}
|
|
|
|
// Find the conflicting process.
|
|
var err error
|
|
for _, resolverIP := range ipsToCheck {
|
|
conflictingProcess, err = getListeningProcess(resolverIP, port)
|
|
switch {
|
|
case err != nil:
|
|
// Log the error and let the worker try again.
|
|
log.Warningf("nameserver: failed to find conflicting service: %s", err)
|
|
case conflictingProcess != nil:
|
|
// Conflicting service found.
|
|
return conflictingProcess
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getListeningProcess(resolverIP net.IP, resolverPort uint16) (*processInfo.Process, error) {
|
|
pid, _, err := state.Lookup(&packet.Info{
|
|
Inbound: true,
|
|
Version: 0, // auto-detect
|
|
Protocol: packet.UDP,
|
|
Src: nil, // do not record direction
|
|
SrcPort: 0, // do not record direction
|
|
Dst: resolverIP,
|
|
DstPort: resolverPort,
|
|
}, true)
|
|
if err != nil {
|
|
// there may be nothing listening on :53
|
|
return nil, nil //nolint:nilerr // Treat lookup error as "not found".
|
|
}
|
|
|
|
// Ignore if it's us for some reason.
|
|
if pid == os.Getpid() {
|
|
return nil, nil
|
|
}
|
|
|
|
proc, err := processInfo.NewProcess(int32(pid))
|
|
if err != nil {
|
|
// Process may have disappeared already.
|
|
return nil, err
|
|
}
|
|
|
|
return proc, nil
|
|
}
|