Refactor: metadata use netip.Addr

This commit is contained in:
yaling888
2022-04-20 01:52:51 +08:00
committed by adlyq
parent 6c4791480e
commit 7ca1a03d73
45 changed files with 374 additions and 346 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}
})
}

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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()

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 {