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 }