Skip to content

Commit eec2fc3

Browse files
committed
Improve interface finder
1 parent 2fa0399 commit eec2fc3

File tree

5 files changed

+119
-24
lines changed

5 files changed

+119
-24
lines changed

common/control/bind_finder.go

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,18 @@
11
package control
22

3-
import "net"
3+
import (
4+
"net/netip"
5+
)
46

57
type InterfaceFinder interface {
68
InterfaceIndexByName(name string) (int, error)
79
InterfaceNameByIndex(index int) (string, error)
10+
InterfaceByAddr(addr netip.Addr) (*Interface, error)
811
}
912

10-
func DefaultInterfaceFinder() InterfaceFinder {
11-
return (*netInterfaceFinder)(nil)
12-
}
13-
14-
type netInterfaceFinder struct{}
15-
16-
func (w *netInterfaceFinder) InterfaceIndexByName(name string) (int, error) {
17-
netInterface, err := net.InterfaceByName(name)
18-
if err != nil {
19-
return 0, err
20-
}
21-
return netInterface.Index, nil
22-
}
23-
24-
func (w *netInterfaceFinder) InterfaceNameByIndex(index int) (string, error) {
25-
netInterface, err := net.InterfaceByIndex(index)
26-
if err != nil {
27-
return "", err
28-
}
29-
return netInterface.Name, nil
13+
type Interface struct {
14+
Index int
15+
MTU int
16+
Name string
17+
Addresses []netip.Prefix
3018
}

common/control/bind_finder_default.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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+
}

common/metadata/addr.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func SocksaddrFromNet(ap net.Addr) Socksaddr {
141141
return ParseSocksaddr(ap.String())
142142
}
143143

144-
func AddrFromNetAddr(netAddr net.Addr) netip.Addr {
144+
func AddrFromNet(netAddr net.Addr) netip.Addr {
145145
if addr := AddrPortFromNet(netAddr); addr.Addr().IsValid() {
146146
return addr.Addr()
147147
}
@@ -157,6 +157,16 @@ func AddrFromNetAddr(netAddr net.Addr) netip.Addr {
157157
}
158158
}
159159

160+
func PrefixFromNet(netAddr net.Addr) netip.Prefix {
161+
switch addr := netAddr.(type) {
162+
case *net.IPNet:
163+
bits, _ := addr.Mask.Size()
164+
return netip.PrefixFrom(AddrFromIP(addr.IP), bits)
165+
default:
166+
return netip.Prefix{}
167+
}
168+
}
169+
160170
func AddrPortFromNet(netAddr net.Addr) netip.AddrPort {
161171
var ip net.IP
162172
var port uint16

common/network/addr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func LocalAddrs() ([]netip.Addr, error) {
1313
if err != nil {
1414
return nil, err
1515
}
16-
return common.Map(interfaceAddrs, M.AddrFromNetAddr), nil
16+
return common.Map(interfaceAddrs, M.AddrFromNet), nil
1717
}
1818

1919
func IsPublicAddr(addr netip.Addr) bool {

protocol/socks/handshake.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func HandleConnection0(ctx context.Context, conn net.Conn, version byte, authent
203203
return handler.NewConnection(ctx, conn, metadata)
204204
case socks5.CommandUDPAssociate:
205205
var udpConn *net.UDPConn
206-
udpConn, err = net.ListenUDP(M.NetworkFromNetAddr("udp", M.AddrFromNetAddr(conn.LocalAddr())), net.UDPAddrFromAddrPort(netip.AddrPortFrom(M.AddrFromNetAddr(conn.LocalAddr()), 0)))
206+
udpConn, err = net.ListenUDP(M.NetworkFromNetAddr("udp", M.AddrFromNet(conn.LocalAddr())), net.UDPAddrFromAddrPort(netip.AddrPortFrom(M.AddrFromNet(conn.LocalAddr()), 0)))
207207
if err != nil {
208208
return err
209209
}

0 commit comments

Comments
 (0)