mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-04 20:37:40 +03:00
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
package control
|
|
|
|
import (
|
|
"net"
|
|
"net/netip"
|
|
_ "unsafe"
|
|
|
|
"github.com/sagernet/sing/common"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
)
|
|
|
|
var _ InterfaceFinder = (*DefaultInterfaceFinder)(nil)
|
|
|
|
type DefaultInterfaceFinder struct {
|
|
interfaces []Interface
|
|
}
|
|
|
|
func NewDefaultInterfaceFinder() *DefaultInterfaceFinder {
|
|
return &DefaultInterfaceFinder{}
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) Update() error {
|
|
netIfs, err := net.Interfaces()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
interfaces := make([]Interface, 0, len(netIfs))
|
|
for _, netIf := range netIfs {
|
|
ifAddrs, err := netIf.Addrs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
interfaces = append(interfaces, Interface{
|
|
Index: netIf.Index,
|
|
MTU: netIf.MTU,
|
|
Name: netIf.Name,
|
|
Addresses: common.Map(ifAddrs, M.PrefixFromNet),
|
|
HardwareAddr: netIf.HardwareAddr,
|
|
Flags: netIf.Flags,
|
|
})
|
|
}
|
|
f.interfaces = interfaces
|
|
return nil
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) UpdateInterfaces(interfaces []Interface) {
|
|
f.interfaces = interfaces
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) Interfaces() []Interface {
|
|
return f.interfaces
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) InterfaceIndexByName(name string) (int, error) {
|
|
for _, netInterface := range f.interfaces {
|
|
if netInterface.Name == name {
|
|
return netInterface.Index, nil
|
|
}
|
|
}
|
|
netInterface, err := net.InterfaceByName(name)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
f.Update()
|
|
return netInterface.Index, nil
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) InterfaceNameByIndex(index int) (string, error) {
|
|
for _, netInterface := range f.interfaces {
|
|
if netInterface.Index == index {
|
|
return netInterface.Name, nil
|
|
}
|
|
}
|
|
netInterface, err := net.InterfaceByIndex(index)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
f.Update()
|
|
return netInterface.Name, nil
|
|
}
|
|
|
|
func (f *DefaultInterfaceFinder) InterfaceByAddr(addr netip.Addr) (*Interface, error) {
|
|
for _, netInterface := range f.interfaces {
|
|
for _, prefix := range netInterface.Addresses {
|
|
if prefix.Contains(addr) {
|
|
return &netInterface, nil
|
|
}
|
|
}
|
|
}
|
|
err := f.Update()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, netInterface := range f.interfaces {
|
|
for _, prefix := range netInterface.Addresses {
|
|
if prefix.Contains(addr) {
|
|
return &netInterface, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: &net.IPAddr{IP: addr.AsSlice()}, Err: E.New("no such network interface")}
|
|
}
|