github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/control/bind_finder_default.go (about)

     1  package control
     2  
     3  import (
     4  	"net"
     5  	"net/netip"
     6  	_ "unsafe"
     7  
     8  	"github.com/sagernet/sing/common"
     9  	M "github.com/sagernet/sing/common/metadata"
    10  )
    11  
    12  type DefaultInterfaceFinder struct {
    13  	interfaces []Interface
    14  }
    15  
    16  func NewDefaultInterfaceFinder() *DefaultInterfaceFinder {
    17  	return &DefaultInterfaceFinder{}
    18  }
    19  
    20  func (f *DefaultInterfaceFinder) Update() error {
    21  	netIfs, err := net.Interfaces()
    22  	if err != nil {
    23  		return err
    24  	}
    25  	interfaces := make([]Interface, 0, len(netIfs))
    26  	for _, netIf := range netIfs {
    27  		ifAddrs, err := netIf.Addrs()
    28  		if err != nil {
    29  			return err
    30  		}
    31  		interfaces = append(interfaces, Interface{
    32  			Index:     netIf.Index,
    33  			MTU:       netIf.MTU,
    34  			Name:      netIf.Name,
    35  			Addresses: common.Map(ifAddrs, M.PrefixFromNet),
    36  		})
    37  	}
    38  	f.interfaces = interfaces
    39  	return nil
    40  }
    41  
    42  func (f *DefaultInterfaceFinder) UpdateInterfaces(interfaces []Interface) {
    43  	f.interfaces = interfaces
    44  }
    45  
    46  func (f *DefaultInterfaceFinder) InterfaceIndexByName(name string) (int, error) {
    47  	for _, netInterface := range f.interfaces {
    48  		if netInterface.Name == name {
    49  			return netInterface.Index, nil
    50  		}
    51  	}
    52  	netInterface, err := net.InterfaceByName(name)
    53  	if err != nil {
    54  		return 0, err
    55  	}
    56  	f.Update()
    57  	return netInterface.Index, nil
    58  }
    59  
    60  func (f *DefaultInterfaceFinder) InterfaceNameByIndex(index int) (string, error) {
    61  	for _, netInterface := range f.interfaces {
    62  		if netInterface.Index == index {
    63  			return netInterface.Name, nil
    64  		}
    65  	}
    66  	netInterface, err := net.InterfaceByIndex(index)
    67  	if err != nil {
    68  		return "", err
    69  	}
    70  	f.Update()
    71  	return netInterface.Name, nil
    72  }
    73  
    74  //go:linkname errNoSuchInterface net.errNoSuchInterface
    75  var errNoSuchInterface error
    76  
    77  func (f *DefaultInterfaceFinder) InterfaceByAddr(addr netip.Addr) (*Interface, error) {
    78  	for _, netInterface := range f.interfaces {
    79  		for _, prefix := range netInterface.Addresses {
    80  			if prefix.Contains(addr) {
    81  				return &netInterface, nil
    82  			}
    83  		}
    84  	}
    85  	err := f.Update()
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	for _, netInterface := range f.interfaces {
    90  		for _, prefix := range netInterface.Addresses {
    91  			if prefix.Contains(addr) {
    92  				return &netInterface, nil
    93  			}
    94  		}
    95  	}
    96  	return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: &net.IPAddr{IP: addr.AsSlice()}, Err: errNoSuchInterface}
    97  }