Refactor: metadata use netip.Addr
This commit is contained in:
@ -5,6 +5,7 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
@ -28,10 +29,10 @@ func (c *client) Exchange(m *D.Msg) (*D.Msg, error) {
|
||||
|
||||
func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) {
|
||||
var (
|
||||
ip net.IP
|
||||
ip netip.Addr
|
||||
err error
|
||||
)
|
||||
if ip = net.ParseIP(c.host); ip == nil {
|
||||
if ip, err = netip.ParseAddr(c.host); err != nil {
|
||||
if c.r == nil {
|
||||
return nil, fmt.Errorf("dns %s not a valid ip", c.host)
|
||||
} else {
|
||||
@ -62,7 +63,9 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
defer func() {
|
||||
_ = conn.Close()
|
||||
}()
|
||||
|
||||
// miekg/dns ExchangeContext doesn't respond to context cancel.
|
||||
// this is a workaround
|
||||
|
@ -1,9 +1,9 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -27,7 +27,7 @@ type dhcpClient struct {
|
||||
ifaceInvalidate time.Time
|
||||
dnsInvalidate time.Time
|
||||
|
||||
ifaceAddr *net.IPNet
|
||||
ifaceAddr *netip.Prefix
|
||||
done chan struct{}
|
||||
resolver *Resolver
|
||||
err error
|
||||
@ -127,12 +127,12 @@ func (d *dhcpClient) invalidate() (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
addr, err := ifaceObj.PickIPv4Addr(nil)
|
||||
addr, err := ifaceObj.PickIPv4Addr(netip.Addr{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if time.Now().Before(d.dnsInvalidate) && d.ifaceAddr.IP.Equal(addr.IP) && bytes.Equal(d.ifaceAddr.Mask, addr.Mask) {
|
||||
if time.Now().Before(d.dnsInvalidate) && d.ifaceAddr == addr {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/component/fakeip"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
@ -24,54 +22,51 @@ func (h *ResolverEnhancer) MappingEnabled() bool {
|
||||
return h.mode == C.DNSFakeIP || h.mode == C.DNSMapping
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) IsExistFakeIP(ip net.IP) bool {
|
||||
func (h *ResolverEnhancer) IsExistFakeIP(ip netip.Addr) bool {
|
||||
if !h.FakeIPEnabled() {
|
||||
return false
|
||||
}
|
||||
|
||||
if pool := h.fakePool; pool != nil {
|
||||
return pool.Exist(nnip.IpToAddr(ip))
|
||||
return pool.Exist(ip)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) IsFakeIP(ip net.IP) bool {
|
||||
if !h.FakeIPEnabled() {
|
||||
return false
|
||||
}
|
||||
|
||||
addr := nnip.IpToAddr(ip)
|
||||
|
||||
if pool := h.fakePool; pool != nil {
|
||||
return pool.IPNet().Contains(addr) && addr != pool.Gateway() && addr != pool.Broadcast()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) IsFakeBroadcastIP(ip net.IP) bool {
|
||||
func (h *ResolverEnhancer) IsFakeIP(ip netip.Addr) bool {
|
||||
if !h.FakeIPEnabled() {
|
||||
return false
|
||||
}
|
||||
|
||||
if pool := h.fakePool; pool != nil {
|
||||
return pool.Broadcast() == nnip.IpToAddr(ip)
|
||||
return pool.IPNet().Contains(ip) && ip != pool.Gateway() && ip != pool.Broadcast()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) FindHostByIP(ip net.IP) (string, bool) {
|
||||
addr := nnip.IpToAddr(ip)
|
||||
func (h *ResolverEnhancer) IsFakeBroadcastIP(ip netip.Addr) bool {
|
||||
if !h.FakeIPEnabled() {
|
||||
return false
|
||||
}
|
||||
|
||||
if pool := h.fakePool; pool != nil {
|
||||
if host, existed := pool.LookBack(addr); existed {
|
||||
return pool.Broadcast() == ip
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) FindHostByIP(ip netip.Addr) (string, bool) {
|
||||
if pool := h.fakePool; pool != nil {
|
||||
if host, existed := pool.LookBack(ip); existed {
|
||||
return host, true
|
||||
}
|
||||
}
|
||||
|
||||
if mapping := h.mapping; mapping != nil {
|
||||
if host, existed := h.mapping.Get(addr); existed {
|
||||
if host, existed := h.mapping.Get(ip); existed {
|
||||
return host, true
|
||||
}
|
||||
}
|
||||
@ -79,9 +74,9 @@ func (h *ResolverEnhancer) FindHostByIP(ip net.IP) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (h *ResolverEnhancer) InsertHostByIP(ip net.IP, host string) {
|
||||
func (h *ResolverEnhancer) InsertHostByIP(ip netip.Addr, host string) {
|
||||
if mapping := h.mapping; mapping != nil {
|
||||
h.mapping.Set(nnip.IpToAddr(ip), host)
|
||||
h.mapping.Set(ip, host)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,19 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/component/geodata"
|
||||
"github.com/Dreamacro/clash/component/geodata/router"
|
||||
"github.com/Dreamacro/clash/component/mmdb"
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type fallbackIPFilter interface {
|
||||
Match(net.IP) bool
|
||||
Match(netip.Addr) bool
|
||||
}
|
||||
|
||||
type geoipFilter struct {
|
||||
@ -21,9 +22,9 @@ type geoipFilter struct {
|
||||
|
||||
var geoIPMatcher *router.GeoIPMatcher
|
||||
|
||||
func (gf *geoipFilter) Match(ip net.IP) bool {
|
||||
func (gf *geoipFilter) Match(ip netip.Addr) bool {
|
||||
if !C.GeodataMode {
|
||||
record, _ := mmdb.Instance().Country(ip)
|
||||
record, _ := mmdb.Instance().Country(ip.AsSlice())
|
||||
return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate()
|
||||
}
|
||||
|
||||
@ -54,14 +55,14 @@ func (gf *geoipFilter) Match(ip net.IP) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return !geoIPMatcher.Match(ip)
|
||||
return !geoIPMatcher.Match(ip.AsSlice())
|
||||
}
|
||||
|
||||
type ipnetFilter struct {
|
||||
ipnet *net.IPNet
|
||||
ipnet *netip.Prefix
|
||||
}
|
||||
|
||||
func (inf *ipnetFilter) Match(ip net.IP) bool {
|
||||
func (inf *ipnetFilter) Match(ip netip.Addr) bool {
|
||||
return inf.ipnet.Contains(ip)
|
||||
}
|
||||
|
||||
@ -76,7 +77,7 @@ type domainFilter struct {
|
||||
func NewDomainFilter(domains []string) *domainFilter {
|
||||
df := domainFilter{tree: trie.New[bool]()}
|
||||
for _, domain := range domains {
|
||||
df.tree.Insert(domain, true)
|
||||
_ = df.tree.Insert(domain, true)
|
||||
}
|
||||
return &df
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"time"
|
||||
@ -88,21 +87,21 @@ func withMapping(mapping *cache.LruCache[netip.Addr, string]) middleware {
|
||||
host := strings.TrimRight(q.Name, ".")
|
||||
|
||||
for _, ans := range msg.Answer {
|
||||
var ip net.IP
|
||||
var ip netip.Addr
|
||||
var ttl uint32
|
||||
|
||||
switch a := ans.(type) {
|
||||
case *D.A:
|
||||
ip = a.A
|
||||
ip = nnip.IpToAddr(a.A)
|
||||
ttl = a.Hdr.Ttl
|
||||
case *D.AAAA:
|
||||
ip = a.AAAA
|
||||
ip = nnip.IpToAddr(a.AAAA)
|
||||
ttl = a.Hdr.Ttl
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
mapping.SetWithExpire(nnip.IpToAddr(ip), host, time.Now().Add(time.Second*time.Duration(ttl)))
|
||||
mapping.SetWithExpire(ip, host, time.Now().Add(time.Second*time.Duration(ttl)))
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"time"
|
||||
@ -46,8 +45,8 @@ type Resolver struct {
|
||||
}
|
||||
|
||||
// ResolveIP request with TypeA and TypeAAAA, priority return TypeA
|
||||
func (r *Resolver) ResolveIP(host string) (ip net.IP, err error) {
|
||||
ch := make(chan net.IP, 1)
|
||||
func (r *Resolver) ResolveIP(host string) (ip netip.Addr, err error) {
|
||||
ch := make(chan netip.Addr, 1)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
ip, err := r.resolveIP(host, D.TypeAAAA)
|
||||
@ -64,23 +63,23 @@ func (r *Resolver) ResolveIP(host string) (ip net.IP, err error) {
|
||||
|
||||
ip, open := <-ch
|
||||
if !open {
|
||||
return nil, resolver.ErrIPNotFound
|
||||
return netip.Addr{}, resolver.ErrIPNotFound
|
||||
}
|
||||
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// ResolveIPv4 request with TypeA
|
||||
func (r *Resolver) ResolveIPv4(host string) (ip net.IP, err error) {
|
||||
func (r *Resolver) ResolveIPv4(host string) (ip netip.Addr, err error) {
|
||||
return r.resolveIP(host, D.TypeA)
|
||||
}
|
||||
|
||||
// ResolveIPv6 request with TypeAAAA
|
||||
func (r *Resolver) ResolveIPv6(host string) (ip net.IP, err error) {
|
||||
func (r *Resolver) ResolveIPv6(host string) (ip netip.Addr, err error) {
|
||||
return r.resolveIP(host, D.TypeAAAA)
|
||||
}
|
||||
|
||||
func (r *Resolver) shouldIPFallback(ip net.IP) bool {
|
||||
func (r *Resolver) shouldIPFallback(ip netip.Addr) bool {
|
||||
for _, filter := range r.fallbackIPFilters {
|
||||
if filter.Match(ip) {
|
||||
return true
|
||||
@ -101,10 +100,10 @@ func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, e
|
||||
}
|
||||
|
||||
q := m.Question[0]
|
||||
cache, expireTime, hit := r.lruCache.GetWithExpire(q.String())
|
||||
cacheM, expireTime, hit := r.lruCache.GetWithExpire(q.String())
|
||||
if hit {
|
||||
now := time.Now()
|
||||
msg = cache.Copy()
|
||||
msg = cacheM.Copy()
|
||||
if expireTime.Before(now) {
|
||||
setMsgTTL(msg, uint32(1)) // Continue fetch
|
||||
go r.exchangeWithoutCache(ctx, m)
|
||||
@ -255,16 +254,16 @@ func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err er
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Resolver) resolveIP(host string, dnsType uint16) (ip net.IP, err error) {
|
||||
ip = net.ParseIP(host)
|
||||
if ip != nil {
|
||||
isIPv4 := ip.To4() != nil
|
||||
func (r *Resolver) resolveIP(host string, dnsType uint16) (ip netip.Addr, err error) {
|
||||
ip, err = netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
isIPv4 := ip.Is4()
|
||||
if dnsType == D.TypeAAAA && !isIPv4 {
|
||||
return ip, nil
|
||||
} else if dnsType == D.TypeA && isIPv4 {
|
||||
return ip, nil
|
||||
} else {
|
||||
return nil, resolver.ErrIPVersion
|
||||
return netip.Addr{}, resolver.ErrIPVersion
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,13 +272,13 @@ func (r *Resolver) resolveIP(host string, dnsType uint16) (ip net.IP, err error)
|
||||
|
||||
msg, err := r.Exchange(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return netip.Addr{}, err
|
||||
}
|
||||
|
||||
ips := msgToIP(msg)
|
||||
ipLength := len(ips)
|
||||
if ipLength == 0 {
|
||||
return nil, resolver.ErrIPNotFound
|
||||
return netip.Addr{}, resolver.ErrIPNotFound
|
||||
}
|
||||
|
||||
ip = ips[rand.Intn(ipLength)]
|
||||
@ -318,7 +317,7 @@ type NameServer struct {
|
||||
type FallbackFilter struct {
|
||||
GeoIP bool
|
||||
GeoIPCode string
|
||||
IPCIDR []*net.IPNet
|
||||
IPCIDR []*netip.Prefix
|
||||
Domain []string
|
||||
GeoSite []*router.DomainMatcher
|
||||
}
|
||||
@ -359,7 +358,7 @@ func NewResolver(config Config) *Resolver {
|
||||
if len(config.Policy) != 0 {
|
||||
r.policy = trie.New[*Policy]()
|
||||
for domain, nameserver := range config.Policy {
|
||||
r.policy.Insert(domain, NewPolicy(transform([]NameServer{nameserver}, defaultResolver)))
|
||||
_ = r.policy.Insert(domain, NewPolicy(transform([]NameServer{nameserver}, defaultResolver)))
|
||||
}
|
||||
}
|
||||
|
||||
|
14
dns/util.go
14
dns/util.go
@ -5,9 +5,11 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
@ -99,15 +101,15 @@ func handleMsgWithEmptyAnswer(r *D.Msg) *D.Msg {
|
||||
return msg
|
||||
}
|
||||
|
||||
func msgToIP(msg *D.Msg) []net.IP {
|
||||
ips := []net.IP{}
|
||||
func msgToIP(msg *D.Msg) []netip.Addr {
|
||||
ips := []netip.Addr{}
|
||||
|
||||
for _, answer := range msg.Answer {
|
||||
switch ans := answer.(type) {
|
||||
case *D.AAAA:
|
||||
ips = append(ips, ans.AAAA)
|
||||
ips = append(ips, nnip.IpToAddr(ans.AAAA))
|
||||
case *D.A:
|
||||
ips = append(ips, ans.A)
|
||||
ips = append(ips, nnip.IpToAddr(ans.A))
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,7 +134,7 @@ func (wpc *wrapPacketConn) RemoteAddr() net.Addr {
|
||||
return wpc.rAddr
|
||||
}
|
||||
|
||||
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, network string, dstIP net.IP, port string, opts ...dialer.Option) (net.Conn, error) {
|
||||
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, network string, dstIP netip.Addr, port string, opts ...dialer.Option) (net.Conn, error) {
|
||||
adapter, ok := tunnel.Proxies()[adapterName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("proxy adapter [%s] not found", adapterName)
|
||||
@ -147,7 +149,7 @@ func dialContextWithProxyAdapter(ctx context.Context, adapterName string, networ
|
||||
}
|
||||
|
||||
addrType := C.AtypIPv4
|
||||
if dstIP.To4() == nil {
|
||||
if dstIP.Is6() {
|
||||
addrType = C.AtypIPv6
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user