Skip to content

Commit

Permalink
Update iface.go
Browse files Browse the repository at this point in the history
  • Loading branch information
LOVAHE authored Nov 9, 2023
1 parent 5bdee82 commit 2208657
Showing 1 changed file with 19 additions and 34 deletions.
53 changes: 19 additions & 34 deletions component/iface/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package iface
import (
"errors"
"net"
"net/netip"
"strings"
"time"

"github.com/DryPeng/clashT/common/singledo"
Expand All @@ -13,7 +11,7 @@ import (
type Interface struct {
Index int
Name string
Addrs []*netip.Prefix
Addrs []*net.IPNet
HardwareAddr net.HardwareAddr
}

Expand All @@ -22,10 +20,10 @@ var (
ErrAddrNotFound = errors.New("addr not found")
)

var interfaces = singledo.NewSingle[map[string]*Interface](time.Second * 20)
var interfaces = singledo.NewSingle(time.Second * 20)

func ResolveInterface(name string) (*Interface, error) {
value, err, _ := interfaces.Do(func() (map[string]*Interface, error) {
value, err, _ := interfaces.Do(func() (any, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
Expand All @@ -38,28 +36,15 @@ func ResolveInterface(name string) (*Interface, error) {
if err != nil {
continue
}
// if not available device like Meta, dummy0, docker0, etc.
if (iface.Flags&net.FlagMulticast == 0) || (iface.Flags&net.FlagPointToPoint != 0) || (iface.Flags&net.FlagRunning == 0) {
continue
}

ipNets := make([]*netip.Prefix, 0, len(addrs))
ipNets := make([]*net.IPNet, 0, len(addrs))
for _, addr := range addrs {
ipNet := addr.(*net.IPNet)
ip, _ := netip.AddrFromSlice(ipNet.IP)

//unavailable IPv6 Address
if ip.Is6() && strings.HasPrefix(ip.String(), "fe80") {
continue
}

ones, bits := ipNet.Mask.Size()
if bits == 32 {
ip = ip.Unmap()
if v4 := ipNet.IP.To4(); v4 != nil {
ipNet.IP = v4
}

pf := netip.PrefixFrom(ip, ones)
ipNets = append(ipNets, &pf)
ipNets = append(ipNets, ipNet)
}

r[iface.Name] = &Interface{
Expand All @@ -76,7 +61,7 @@ func ResolveInterface(name string) (*Interface, error) {
return nil, err
}

ifaces := value
ifaces := value.(map[string]*Interface)
iface, ok := ifaces[name]
if !ok {
return nil, ErrIfaceNotFound
Expand All @@ -89,35 +74,35 @@ func FlushCache() {
interfaces.Reset()
}

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) PickIPv4Addr(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) PickIPv6Addr(destination net.IP) (*net.IPNet, error) {
return iface.pickIPAddr(destination, func(addr *net.IPNet) bool {
return addr.IP.To4() == nil
})
}

func (iface *Interface) pickIPAddr(destination netip.Addr, accept func(addr *netip.Prefix) bool) (*netip.Prefix, error) {
var fallback *netip.Prefix
func (iface *Interface) pickIPAddr(destination net.IP, accept func(addr *net.IPNet) bool) (*net.IPNet, error) {
var fallback *net.IPNet

for _, addr := range iface.Addrs {
if !accept(addr) {
continue
}

if fallback == nil && !addr.Addr().IsLinkLocalUnicast() {
if fallback == nil && !addr.IP.IsLinkLocalUnicast() {
fallback = addr

if !destination.IsValid() {
if destination == nil {
break
}
}

if destination.IsValid() && addr.Contains(destination) {
if destination != nil && addr.Contains(destination) {
return addr, nil
}
}
Expand Down

0 comments on commit 2208657

Please sign in to comment.