Refactor: metadata use netip.Addr
This commit is contained in:
@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
@ -15,14 +17,16 @@ var (
|
||||
ErrNotFound = errors.New("DNS option not found")
|
||||
)
|
||||
|
||||
func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]net.IP, error) {
|
||||
func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]netip.Addr, error) {
|
||||
conn, err := ListenDHCPClient(context, ifaceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
defer func() {
|
||||
_ = conn.Close()
|
||||
}()
|
||||
|
||||
result := make(chan []net.IP, 1)
|
||||
result := make(chan []netip.Addr, 1)
|
||||
|
||||
ifaceObj, err := iface.ResolveInterface(ifaceName)
|
||||
if err != nil {
|
||||
@ -52,7 +56,7 @@ func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]net.IP, er
|
||||
}
|
||||
}
|
||||
|
||||
func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- []net.IP) {
|
||||
func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- []netip.Addr) {
|
||||
defer close(result)
|
||||
|
||||
buf := make([]byte, dhcpv4.MaxMessageSize)
|
||||
@ -77,11 +81,17 @@ func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- []
|
||||
}
|
||||
|
||||
dns := pkt.DNS()
|
||||
if len(dns) == 0 {
|
||||
l := len(dns)
|
||||
if l == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
result <- dns
|
||||
dnsAddr := make([]netip.Addr, l)
|
||||
for i := 0; i < l; i++ {
|
||||
dnsAddr[i] = nnip.IpToAddr(dns[i])
|
||||
}
|
||||
|
||||
result <- dnsAddr
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package dialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
@ -19,12 +20,9 @@ func bindControl(ifaceIdx int, chain controlFn) controlFn {
|
||||
}
|
||||
}()
|
||||
|
||||
ipStr, _, err := net.SplitHostPort(address)
|
||||
if err == nil {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip != nil && !ip.IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
addrPort, err := netip.ParseAddrPort(address)
|
||||
if err == nil && !addrPort.Addr().IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
|
||||
var innerErr error
|
||||
@ -45,7 +43,7 @@ func bindControl(ifaceIdx int, chain controlFn) controlFn {
|
||||
}
|
||||
}
|
||||
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ net.IP) error {
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
|
||||
ifaceObj, err := iface.ResolveInterface(ifaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2,6 +2,7 @@ package dialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
@ -17,12 +18,9 @@ func bindControl(ifaceName string, chain controlFn) controlFn {
|
||||
}
|
||||
}()
|
||||
|
||||
ipStr, _, err := net.SplitHostPort(address)
|
||||
if err == nil {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip != nil && !ip.IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
addrPort, err := netip.ParseAddrPort(address)
|
||||
if err == nil && !addrPort.Addr().IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
|
||||
var innerErr error
|
||||
@ -38,7 +36,7 @@ func bindControl(ifaceName string, chain controlFn) controlFn {
|
||||
}
|
||||
}
|
||||
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ net.IP) error {
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
|
||||
dialer.Control = bindControl(ifaceName, dialer.Control)
|
||||
|
||||
return nil
|
||||
|
@ -4,27 +4,28 @@ package dialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
)
|
||||
|
||||
func lookupLocalAddr(ifaceName string, network string, destination net.IP, port int) (net.Addr, error) {
|
||||
func lookupLocalAddr(ifaceName string, network string, destination netip.Addr, port int) (net.Addr, error) {
|
||||
ifaceObj, err := iface.ResolveInterface(ifaceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var addr *net.IPNet
|
||||
var addr *netip.Prefix
|
||||
switch network {
|
||||
case "udp4", "tcp4":
|
||||
addr, err = ifaceObj.PickIPv4Addr(destination)
|
||||
case "tcp6", "udp6":
|
||||
addr, err = ifaceObj.PickIPv6Addr(destination)
|
||||
default:
|
||||
if destination != nil {
|
||||
if destination.To4() != nil {
|
||||
if destination.IsValid() {
|
||||
if destination.Is4() {
|
||||
addr, err = ifaceObj.PickIPv4Addr(destination)
|
||||
} else {
|
||||
addr, err = ifaceObj.PickIPv6Addr(destination)
|
||||
@ -39,12 +40,12 @@ func lookupLocalAddr(ifaceName string, network string, destination net.IP, port
|
||||
|
||||
if strings.HasPrefix(network, "tcp") {
|
||||
return &net.TCPAddr{
|
||||
IP: addr.IP,
|
||||
IP: addr.Addr().AsSlice(),
|
||||
Port: port,
|
||||
}, nil
|
||||
} else if strings.HasPrefix(network, "udp") {
|
||||
return &net.UDPAddr{
|
||||
IP: addr.IP,
|
||||
IP: addr.Addr().AsSlice(),
|
||||
Port: port,
|
||||
}, nil
|
||||
}
|
||||
@ -52,7 +53,7 @@ func lookupLocalAddr(ifaceName string, network string, destination net.IP, port
|
||||
return nil, iface.ErrAddrNotFound
|
||||
}
|
||||
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, destination net.IP) error {
|
||||
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, destination netip.Addr) error {
|
||||
if !destination.IsGlobalUnicast() {
|
||||
return nil
|
||||
}
|
||||
@ -83,7 +84,7 @@ func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, add
|
||||
|
||||
local, _ := strconv.ParseUint(port, 10, 16)
|
||||
|
||||
addr, err := lookupLocalAddr(ifaceName, network, nil, int(local))
|
||||
addr, err := lookupLocalAddr(ifaceName, network, netip.Addr{}, int(local))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
)
|
||||
@ -29,7 +30,7 @@ func DialContext(ctx context.Context, network, address string, options ...Option
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ip net.IP
|
||||
var ip netip.Addr
|
||||
switch network {
|
||||
case "tcp4", "udp4":
|
||||
if !opt.direct {
|
||||
@ -88,7 +89,7 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio
|
||||
return lc.ListenPacket(ctx, network, address)
|
||||
}
|
||||
|
||||
func dialContext(ctx context.Context, network string, destination net.IP, port string, opt *option) (net.Conn, error) {
|
||||
func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt *option) (net.Conn, error) {
|
||||
dialer := &net.Dialer{}
|
||||
if opt.interfaceName != "" {
|
||||
if err := bindIfaceToDialer(opt.interfaceName, dialer, network, destination); err != nil {
|
||||
@ -128,12 +129,12 @@ func dualStackDialContext(ctx context.Context, network, address string, opt *opt
|
||||
case results <- result:
|
||||
case <-returned:
|
||||
if result.Conn != nil {
|
||||
result.Conn.Close()
|
||||
_ = result.Conn.Close()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
var ip net.IP
|
||||
var ip netip.Addr
|
||||
if ipv6 {
|
||||
if !direct {
|
||||
ip, result.error = resolver.ResolveIPv6ProxyServerHost(host)
|
||||
|
@ -4,14 +4,15 @@ package dialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ net.IP) {
|
||||
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ netip.Addr) {
|
||||
dialer.Control = bindMarkToControl(mark, dialer.Control)
|
||||
}
|
||||
|
||||
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, address string) {
|
||||
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, _ string) {
|
||||
lc.Control = bindMarkToControl(mark, lc.Control)
|
||||
}
|
||||
|
||||
@ -23,20 +24,17 @@ func bindMarkToControl(mark int, chain controlFn) controlFn {
|
||||
}
|
||||
}()
|
||||
|
||||
ipStr, _, err := net.SplitHostPort(address)
|
||||
if err == nil {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip != nil && !ip.IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
addrPort, err := netip.ParseAddrPort(address)
|
||||
if err == nil && !addrPort.Addr().IsGlobalUnicast() {
|
||||
return
|
||||
}
|
||||
|
||||
return c.Control(func(fd uintptr) {
|
||||
switch network {
|
||||
case "tcp4", "udp4":
|
||||
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
case "tcp6", "udp6":
|
||||
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package dialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
|
||||
"github.com/Dreamacro/clash/log"
|
||||
@ -17,10 +18,10 @@ func printMarkWarn() {
|
||||
})
|
||||
}
|
||||
|
||||
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ net.IP) {
|
||||
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ netip.Addr) {
|
||||
printMarkWarn()
|
||||
}
|
||||
|
||||
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, address string) {
|
||||
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, _ string) {
|
||||
printMarkWarn()
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package dialer
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -18,9 +19,9 @@ func resolverDialContext(ctx context.Context, network, address string) (net.Conn
|
||||
interfaceName := DefaultInterface.Load()
|
||||
|
||||
if interfaceName != "" {
|
||||
dstIP := net.ParseIP(address)
|
||||
if dstIP != nil {
|
||||
bindIfaceToDialer(interfaceName, d, network, dstIP)
|
||||
dstIP, err := netip.ParseAddr(address)
|
||||
if err == nil {
|
||||
_ = bindIfaceToDialer(interfaceName, d, network, dstIP)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package iface
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/singledo"
|
||||
@ -11,7 +12,7 @@ import (
|
||||
type Interface struct {
|
||||
Index int
|
||||
Name string
|
||||
Addrs []*net.IPNet
|
||||
Addrs []*netip.Prefix
|
||||
HardwareAddr net.HardwareAddr
|
||||
}
|
||||
|
||||
@ -37,14 +38,18 @@ func ResolveInterface(name string) (*Interface, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
ipNets := make([]*net.IPNet, 0, len(addrs))
|
||||
ipNets := make([]*netip.Prefix, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
ipNet := addr.(*net.IPNet)
|
||||
if v4 := ipNet.IP.To4(); v4 != nil {
|
||||
ipNet.IP = v4
|
||||
ip, _ := netip.AddrFromSlice(ipNet.IP)
|
||||
|
||||
ones, bits := ipNet.Mask.Size()
|
||||
if bits == 32 {
|
||||
ip = ip.Unmap()
|
||||
}
|
||||
|
||||
ipNets = append(ipNets, ipNet)
|
||||
pf := netip.PrefixFrom(ip, ones)
|
||||
ipNets = append(ipNets, &pf)
|
||||
}
|
||||
|
||||
r[iface.Name] = &Interface{
|
||||
@ -74,35 +79,35 @@ func FlushCache() {
|
||||
interfaces.Reset()
|
||||
}
|
||||
|
||||
func (iface *Interface) PickIPv4Addr(destination net.IP) (*net.IPNet, error) {
|
||||
return iface.pickIPAddr(destination, func(addr *net.IPNet) bool {
|
||||
return addr.IP.To4() != nil
|
||||
func (iface *Interface) PickIPv4Addr(destination netip.Addr) (*netip.Prefix, error) {
|
||||
return iface.pickIPAddr(destination, func(addr *netip.Prefix) bool {
|
||||
return addr.Addr().Is4()
|
||||
})
|
||||
}
|
||||
|
||||
func (iface *Interface) PickIPv6Addr(destination net.IP) (*net.IPNet, error) {
|
||||
return iface.pickIPAddr(destination, func(addr *net.IPNet) bool {
|
||||
return addr.IP.To4() == nil
|
||||
func (iface *Interface) PickIPv6Addr(destination netip.Addr) (*netip.Prefix, error) {
|
||||
return iface.pickIPAddr(destination, func(addr *netip.Prefix) bool {
|
||||
return addr.Addr().Is6()
|
||||
})
|
||||
}
|
||||
|
||||
func (iface *Interface) pickIPAddr(destination net.IP, accept func(addr *net.IPNet) bool) (*net.IPNet, error) {
|
||||
var fallback *net.IPNet
|
||||
func (iface *Interface) pickIPAddr(destination netip.Addr, accept func(addr *netip.Prefix) bool) (*netip.Prefix, error) {
|
||||
var fallback *netip.Prefix
|
||||
|
||||
for _, addr := range iface.Addrs {
|
||||
if !accept(addr) {
|
||||
continue
|
||||
}
|
||||
|
||||
if fallback == nil && !addr.IP.IsLinkLocalUnicast() {
|
||||
if fallback == nil && !addr.Addr().IsLinkLocalUnicast() {
|
||||
fallback = addr
|
||||
|
||||
if destination == nil {
|
||||
if !destination.IsValid() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if destination != nil && addr.Contains(destination) {
|
||||
if destination.IsValid() && addr.Contains(destination) {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package process
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
@ -19,7 +21,7 @@ const (
|
||||
UDP = "udp"
|
||||
)
|
||||
|
||||
func FindProcessName(network string, srcIP net.IP, srcPort int) (string, error) {
|
||||
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (string, error) {
|
||||
return findProcessName(network, srcIP, srcPort)
|
||||
}
|
||||
|
||||
@ -31,23 +33,23 @@ func ShouldFindProcess(metadata *C.Metadata) bool {
|
||||
return false
|
||||
}
|
||||
for _, ip := range localIPs {
|
||||
if ip.Equal(metadata.SrcIP) {
|
||||
if ip == metadata.SrcIP {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AppendLocalIPs(ip ...net.IP) {
|
||||
func AppendLocalIPs(ip ...netip.Addr) {
|
||||
localIPs = append(ip, localIPs...)
|
||||
}
|
||||
|
||||
func getLocalIPs() []net.IP {
|
||||
ips := []net.IP{net.IPv4zero, net.IPv6zero}
|
||||
func getLocalIPs() []netip.Addr {
|
||||
ips := []netip.Addr{netip.IPv4Unspecified(), netip.IPv6Unspecified()}
|
||||
|
||||
netInterfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
ips = append(ips, net.IPv4(127, 0, 0, 1), net.IPv6loopback)
|
||||
ips = append(ips, netip.AddrFrom4([4]byte{127, 0, 0, 1}), nnip.IpToAddr(net.IPv6loopback))
|
||||
return ips
|
||||
}
|
||||
|
||||
@ -57,7 +59,7 @@ func getLocalIPs() []net.IP {
|
||||
|
||||
for _, address := range adds {
|
||||
if ipNet, ok := address.(*net.IPNet); ok {
|
||||
ips = append(ips, ipNet.IP)
|
||||
ips = append(ips, nnip.IpToAddr(ipNet.IP))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,7 +68,7 @@ func getLocalIPs() []net.IP {
|
||||
return ips
|
||||
}
|
||||
|
||||
var localIPs []net.IP
|
||||
var localIPs []netip.Addr
|
||||
|
||||
func init() {
|
||||
localIPs = getLocalIPs()
|
||||
|
@ -2,10 +2,12 @@ package process
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -15,7 +17,7 @@ const (
|
||||
proccallnumpidinfo = 0x2
|
||||
)
|
||||
|
||||
func findProcessName(network string, ip net.IP, port int) (string, error) {
|
||||
func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||
var spath string
|
||||
switch network {
|
||||
case TCP:
|
||||
@ -26,7 +28,7 @@ func findProcessName(network string, ip net.IP, port int) (string, error) {
|
||||
return "", ErrInvalidNetwork
|
||||
}
|
||||
|
||||
isIPv4 := ip.To4() != nil
|
||||
isIPv4 := ip.Is4()
|
||||
|
||||
value, err := syscall.Sysctl(spath)
|
||||
if err != nil {
|
||||
@ -57,19 +59,19 @@ func findProcessName(network string, ip net.IP, port int) (string, error) {
|
||||
// xinpcb_n.inp_vflag
|
||||
flag := buf[inp+44]
|
||||
|
||||
var srcIP net.IP
|
||||
var srcIP netip.Addr
|
||||
switch {
|
||||
case flag&0x1 > 0 && isIPv4:
|
||||
// ipv4
|
||||
srcIP = net.IP(buf[inp+76 : inp+80])
|
||||
srcIP = nnip.IpToAddr(buf[inp+76 : inp+80])
|
||||
case flag&0x2 > 0 && !isIPv4:
|
||||
// ipv6
|
||||
srcIP = net.IP(buf[inp+64 : inp+80])
|
||||
srcIP = nnip.IpToAddr(buf[inp+64 : inp+80])
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if !ip.Equal(srcIP) && (network == TCP || !srcIP.IsUnspecified()) {
|
||||
if ip != srcIP && (network == TCP || !srcIP.IsUnspecified()) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,14 @@ package process
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
@ -20,7 +21,7 @@ var (
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
||||
once.Do(func() {
|
||||
if err := initSearcher(); err != nil {
|
||||
log.Errorln("Initialize PROCESS-NAME failed: %s", err.Error())
|
||||
@ -102,7 +103,7 @@ type searcher struct {
|
||||
pid int
|
||||
}
|
||||
|
||||
func (s *searcher) Search(buf []byte, ip net.IP, port uint16, isTCP bool) (uint32, error) {
|
||||
func (s *searcher) Search(buf []byte, ip netip.Addr, port uint16, isTCP bool) (uint32, error) {
|
||||
var itemSize int
|
||||
var inpOffset int
|
||||
|
||||
@ -116,7 +117,7 @@ func (s *searcher) Search(buf []byte, ip net.IP, port uint16, isTCP bool) (uint3
|
||||
inpOffset = s.udpInpOffset
|
||||
}
|
||||
|
||||
isIPv4 := ip.To4() != nil
|
||||
isIPv4 := ip.Is4()
|
||||
// skip the first xinpgen block
|
||||
for i := s.headSize; i+itemSize <= len(buf); i += itemSize {
|
||||
inp := i + inpOffset
|
||||
@ -130,19 +131,19 @@ func (s *searcher) Search(buf []byte, ip net.IP, port uint16, isTCP bool) (uint3
|
||||
// xinpcb.inp_vflag
|
||||
flag := buf[inp+s.vflag]
|
||||
|
||||
var srcIP net.IP
|
||||
var srcIP netip.Addr
|
||||
switch {
|
||||
case flag&0x1 > 0 && isIPv4:
|
||||
// ipv4
|
||||
srcIP = net.IP(buf[inp+s.ip : inp+s.ip+4])
|
||||
srcIP = nnip.IpToAddr(buf[inp+s.ip : inp+s.ip+4])
|
||||
case flag&0x2 > 0 && !isIPv4:
|
||||
// ipv6
|
||||
srcIP = net.IP(buf[inp+s.ip-12 : inp+s.ip+4])
|
||||
srcIP = nnip.IpToAddr(buf[inp+s.ip-12 : inp+s.ip+4])
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if !ip.Equal(srcIP) {
|
||||
if ip != srcIP {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
@ -31,7 +32,7 @@ const (
|
||||
pathProc = "/proc"
|
||||
)
|
||||
|
||||
func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
||||
inode, uid, err := resolveSocketByNetlink(network, ip, srcPort)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -40,7 +41,7 @@ func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
return resolveProcessNameByProcSearch(inode, uid)
|
||||
}
|
||||
|
||||
func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int32, error) {
|
||||
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
||||
var family byte
|
||||
var protocol byte
|
||||
|
||||
@ -53,7 +54,7 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int3
|
||||
return 0, 0, ErrInvalidNetwork
|
||||
}
|
||||
|
||||
if ip.To4() != nil {
|
||||
if ip.Is4() {
|
||||
family = syscall.AF_INET
|
||||
} else {
|
||||
family = syscall.AF_INET6
|
||||
@ -65,10 +66,12 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int3
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("dial netlink: %w", err)
|
||||
}
|
||||
defer syscall.Close(socket)
|
||||
defer func() {
|
||||
_ = syscall.Close(socket)
|
||||
}()
|
||||
|
||||
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Usec: 100})
|
||||
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Usec: 100})
|
||||
_ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Usec: 100})
|
||||
_ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Usec: 100})
|
||||
|
||||
if err := syscall.Connect(socket, &syscall.SockaddrNetlink{
|
||||
Family: syscall.AF_NETLINK,
|
||||
@ -84,7 +87,9 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int3
|
||||
}
|
||||
|
||||
rb := pool.Get(pool.RelayBufferSize)
|
||||
defer pool.Put(rb)
|
||||
defer func() {
|
||||
_ = pool.Put(rb)
|
||||
}()
|
||||
|
||||
n, err := syscall.Read(socket, rb)
|
||||
if err != nil {
|
||||
@ -111,14 +116,10 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int3
|
||||
return inode, uid, nil
|
||||
}
|
||||
|
||||
func packSocketDiagRequest(family, protocol byte, source net.IP, sourcePort uint16) []byte {
|
||||
func packSocketDiagRequest(family, protocol byte, source netip.Addr, sourcePort uint16) []byte {
|
||||
s := make([]byte, 16)
|
||||
|
||||
if v4 := source.To4(); v4 != nil {
|
||||
copy(s, v4)
|
||||
} else {
|
||||
copy(s, source)
|
||||
}
|
||||
copy(s, source.AsSlice())
|
||||
|
||||
buf := make([]byte, sizeOfSocketDiagRequest)
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
package process
|
||||
|
||||
import "net"
|
||||
import "net/netip"
|
||||
|
||||
func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
||||
return "", ErrPlatformNotSupport
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ package process
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@ -57,7 +58,7 @@ func initWin32API() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
||||
once.Do(func() {
|
||||
err := initWin32API()
|
||||
if err != nil {
|
||||
@ -67,7 +68,7 @@ func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
}
|
||||
})
|
||||
family := windows.AF_INET
|
||||
if ip.To4() == nil {
|
||||
if ip.Is6() {
|
||||
family = windows.AF_INET6
|
||||
}
|
||||
|
||||
@ -107,7 +108,7 @@ type searcher struct {
|
||||
tcpState int
|
||||
}
|
||||
|
||||
func (s *searcher) Search(b []byte, ip net.IP, port uint16) (uint32, error) {
|
||||
func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error) {
|
||||
n := int(readNativeUint32(b[:4]))
|
||||
itemSize := s.itemSize
|
||||
for i := 0; i < n; i++ {
|
||||
@ -131,9 +132,9 @@ func (s *searcher) Search(b []byte, ip net.IP, port uint16) (uint32, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
srcIP := net.IP(row[s.ip : s.ip+s.ipSize])
|
||||
srcIP := nnip.IpToAddr(row[s.ip : s.ip+s.ipSize])
|
||||
// windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto
|
||||
if !ip.Equal(srcIP) && (!srcIP.IsUnspecified() || s.tcpState != -1) {
|
||||
if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,18 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
import "net/netip"
|
||||
|
||||
var DefaultHostMapper Enhancer
|
||||
|
||||
type Enhancer interface {
|
||||
FakeIPEnabled() bool
|
||||
MappingEnabled() bool
|
||||
IsFakeIP(net.IP) bool
|
||||
IsFakeBroadcastIP(net.IP) bool
|
||||
IsExistFakeIP(net.IP) bool
|
||||
FindHostByIP(net.IP) (string, bool)
|
||||
IsFakeIP(netip.Addr) bool
|
||||
IsFakeBroadcastIP(netip.Addr) bool
|
||||
IsExistFakeIP(netip.Addr) bool
|
||||
FindHostByIP(netip.Addr) (string, bool)
|
||||
FlushFakeIP() error
|
||||
InsertHostByIP(net.IP, string)
|
||||
InsertHostByIP(netip.Addr, string)
|
||||
StoreFakePoolState()
|
||||
}
|
||||
|
||||
@ -34,7 +32,7 @@ func MappingEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsFakeIP(ip net.IP) bool {
|
||||
func IsFakeIP(ip netip.Addr) bool {
|
||||
if mapper := DefaultHostMapper; mapper != nil {
|
||||
return mapper.IsFakeIP(ip)
|
||||
}
|
||||
@ -42,7 +40,7 @@ func IsFakeIP(ip net.IP) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsFakeBroadcastIP(ip net.IP) bool {
|
||||
func IsFakeBroadcastIP(ip netip.Addr) bool {
|
||||
if mapper := DefaultHostMapper; mapper != nil {
|
||||
return mapper.IsFakeBroadcastIP(ip)
|
||||
}
|
||||
@ -50,7 +48,7 @@ func IsFakeBroadcastIP(ip net.IP) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsExistFakeIP(ip net.IP) bool {
|
||||
func IsExistFakeIP(ip netip.Addr) bool {
|
||||
if mapper := DefaultHostMapper; mapper != nil {
|
||||
return mapper.IsExistFakeIP(ip)
|
||||
}
|
||||
@ -58,13 +56,13 @@ func IsExistFakeIP(ip net.IP) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func InsertHostByIP(ip net.IP, host string) {
|
||||
func InsertHostByIP(ip netip.Addr, host string) {
|
||||
if mapper := DefaultHostMapper; mapper != nil {
|
||||
mapper.InsertHostByIP(ip, host)
|
||||
}
|
||||
}
|
||||
|
||||
func FindHostByIP(ip net.IP) (string, bool) {
|
||||
func FindHostByIP(ip netip.Addr) (string, bool) {
|
||||
if mapper := DefaultHostMapper; mapper != nil {
|
||||
return mapper.FindHostByIP(ip)
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
)
|
||||
|
||||
@ -37,29 +37,29 @@ var (
|
||||
)
|
||||
|
||||
type Resolver interface {
|
||||
ResolveIP(host string) (ip net.IP, err error)
|
||||
ResolveIPv4(host string) (ip net.IP, err error)
|
||||
ResolveIPv6(host string) (ip net.IP, err error)
|
||||
ResolveIP(host string) (ip netip.Addr, err error)
|
||||
ResolveIPv4(host string) (ip netip.Addr, err error)
|
||||
ResolveIPv6(host string) (ip netip.Addr, err error)
|
||||
}
|
||||
|
||||
// ResolveIPv4 with a host, return ipv4
|
||||
func ResolveIPv4(host string) (net.IP, error) {
|
||||
func ResolveIPv4(host string) (netip.Addr, error) {
|
||||
return ResolveIPv4WithResolver(host, DefaultResolver)
|
||||
}
|
||||
|
||||
func ResolveIPv4WithResolver(host string, r Resolver) (net.IP, error) {
|
||||
func ResolveIPv4WithResolver(host string, r Resolver) (netip.Addr, error) {
|
||||
if node := DefaultHosts.Search(host); node != nil {
|
||||
if ip := node.Data; ip.Is4() {
|
||||
return ip.AsSlice(), nil
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
if ip != nil {
|
||||
if !strings.Contains(host, ":") {
|
||||
ip, err := netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
if ip.Is4() {
|
||||
return ip, nil
|
||||
}
|
||||
return nil, ErrIPVersion
|
||||
return netip.Addr{}, ErrIPVersion
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
@ -71,39 +71,44 @@ func ResolveIPv4WithResolver(host string, r Resolver) (net.IP, error) {
|
||||
defer cancel()
|
||||
ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip4", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return netip.Addr{}, err
|
||||
} else if len(ipAddrs) == 0 {
|
||||
return nil, ErrIPNotFound
|
||||
return netip.Addr{}, ErrIPNotFound
|
||||
}
|
||||
|
||||
return ipAddrs[rand.Intn(len(ipAddrs))], nil
|
||||
ip := ipAddrs[rand.Intn(len(ipAddrs))].To4()
|
||||
if ip == nil {
|
||||
return netip.Addr{}, ErrIPVersion
|
||||
}
|
||||
|
||||
return netip.AddrFrom4(*(*[4]byte)(ip)), nil
|
||||
}
|
||||
|
||||
return nil, ErrIPNotFound
|
||||
return netip.Addr{}, ErrIPNotFound
|
||||
}
|
||||
|
||||
// ResolveIPv6 with a host, return ipv6
|
||||
func ResolveIPv6(host string) (net.IP, error) {
|
||||
func ResolveIPv6(host string) (netip.Addr, error) {
|
||||
return ResolveIPv6WithResolver(host, DefaultResolver)
|
||||
}
|
||||
|
||||
func ResolveIPv6WithResolver(host string, r Resolver) (net.IP, error) {
|
||||
func ResolveIPv6WithResolver(host string, r Resolver) (netip.Addr, error) {
|
||||
if DisableIPv6 {
|
||||
return nil, ErrIPv6Disabled
|
||||
return netip.Addr{}, ErrIPv6Disabled
|
||||
}
|
||||
|
||||
if node := DefaultHosts.Search(host); node != nil {
|
||||
if ip := node.Data; ip.Is6() {
|
||||
return ip.AsSlice(), nil
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
if ip != nil {
|
||||
if strings.Contains(host, ":") {
|
||||
ip, err := netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
if ip.Is6() {
|
||||
return ip, nil
|
||||
}
|
||||
return nil, ErrIPVersion
|
||||
return netip.Addr{}, ErrIPVersion
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
@ -115,22 +120,21 @@ func ResolveIPv6WithResolver(host string, r Resolver) (net.IP, error) {
|
||||
defer cancel()
|
||||
ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return netip.Addr{}, err
|
||||
} else if len(ipAddrs) == 0 {
|
||||
return nil, ErrIPNotFound
|
||||
return netip.Addr{}, ErrIPNotFound
|
||||
}
|
||||
|
||||
return ipAddrs[rand.Intn(len(ipAddrs))], nil
|
||||
return netip.AddrFrom16(*(*[16]byte)(ipAddrs[rand.Intn(len(ipAddrs))])), nil
|
||||
}
|
||||
|
||||
return nil, ErrIPNotFound
|
||||
return netip.Addr{}, ErrIPNotFound
|
||||
}
|
||||
|
||||
// ResolveIPWithResolver same as ResolveIP, but with a resolver
|
||||
func ResolveIPWithResolver(host string, r Resolver) (net.IP, error) {
|
||||
func ResolveIPWithResolver(host string, r Resolver) (netip.Addr, error) {
|
||||
if node := DefaultHosts.Search(host); node != nil {
|
||||
ip := node.Data
|
||||
return ip.Unmap().AsSlice(), nil
|
||||
return node.Data, nil
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
@ -142,30 +146,30 @@ func ResolveIPWithResolver(host string, r Resolver) (net.IP, error) {
|
||||
return ResolveIPv4(host)
|
||||
}
|
||||
|
||||
ip := net.ParseIP(host)
|
||||
if ip != nil {
|
||||
ip, err := netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
if DefaultResolver == nil {
|
||||
ipAddr, err := net.ResolveIPAddr("ip", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return netip.Addr{}, err
|
||||
}
|
||||
|
||||
return ipAddr.IP, nil
|
||||
return nnip.IpToAddr(ipAddr.IP), nil
|
||||
}
|
||||
|
||||
return nil, ErrIPNotFound
|
||||
return netip.Addr{}, ErrIPNotFound
|
||||
}
|
||||
|
||||
// ResolveIP with a host, return ip
|
||||
func ResolveIP(host string) (net.IP, error) {
|
||||
func ResolveIP(host string) (netip.Addr, error) {
|
||||
return ResolveIPWithResolver(host, DefaultResolver)
|
||||
}
|
||||
|
||||
// ResolveIPv4ProxyServerHost proxies server host only
|
||||
func ResolveIPv4ProxyServerHost(host string) (net.IP, error) {
|
||||
func ResolveIPv4ProxyServerHost(host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv4WithResolver(host, ProxyServerHostResolver)
|
||||
}
|
||||
@ -173,7 +177,7 @@ func ResolveIPv4ProxyServerHost(host string) (net.IP, error) {
|
||||
}
|
||||
|
||||
// ResolveIPv6ProxyServerHost proxies server host only
|
||||
func ResolveIPv6ProxyServerHost(host string) (net.IP, error) {
|
||||
func ResolveIPv6ProxyServerHost(host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv6WithResolver(host, ProxyServerHostResolver)
|
||||
}
|
||||
@ -181,7 +185,7 @@ func ResolveIPv6ProxyServerHost(host string) (net.IP, error) {
|
||||
}
|
||||
|
||||
// ResolveProxyServerHost proxies server host only
|
||||
func ResolveProxyServerHost(host string) (net.IP, error) {
|
||||
func ResolveProxyServerHost(host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPWithResolver(host, ProxyServerHostResolver)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
CN "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
@ -58,7 +59,7 @@ func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string) {
|
||||
metadata.Host = host
|
||||
metadata.DNSMode = C.DNSMapping
|
||||
resolver.InsertHostByIP(metadata.DstIP, host)
|
||||
metadata.DstIP = nil
|
||||
metadata.DstIP = netip.Addr{}
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) Enable() bool {
|
||||
|
Reference in New Issue
Block a user