@@ -2,8 +2,10 @@ package dialer
22
33import (
44 "context"
5+ "errors"
56 "net"
67 "net/netip"
8+ "syscall"
79 "time"
810
911 "github.com/sagernet/sing-box/adapter"
@@ -26,34 +28,36 @@ var (
2628)
2729
2830type DefaultDialer struct {
29- dialer4 tcpDialer
30- dialer6 tcpDialer
31- udpDialer4 net.Dialer
32- udpDialer6 net.Dialer
33- udpListener net.ListenConfig
34- udpAddr4 string
35- udpAddr6 string
36- isWireGuardListener bool
37- networkManager adapter.NetworkManager
38- networkStrategy * C.NetworkStrategy
39- networkType []C.InterfaceType
40- fallbackNetworkType []C.InterfaceType
41- networkFallbackDelay time.Duration
42- networkLastFallback atomic.TypedValue [time.Time ]
31+ dialer4 tcpDialer
32+ dialer6 tcpDialer
33+ udpDialer4 net.Dialer
34+ udpDialer6 net.Dialer
35+ udpListener net.ListenConfig
36+ udpAddr4 string
37+ udpAddr6 string
38+ isWireGuardListener bool
39+ networkManager adapter.NetworkManager
40+ networkStrategy * C.NetworkStrategy
41+ defaultNetworkStrategy bool
42+ networkType []C.InterfaceType
43+ fallbackNetworkType []C.InterfaceType
44+ networkFallbackDelay time.Duration
45+ networkLastFallback atomic.TypedValue [time.Time ]
4346}
4447
4548func NewDefault (ctx context.Context , options option.DialerOptions ) (* DefaultDialer , error ) {
4649 networkManager := service.FromContext [adapter.NetworkManager ](ctx )
4750 platformInterface := service.FromContext [platform.Interface ](ctx )
4851
4952 var (
50- dialer net.Dialer
51- listener net.ListenConfig
52- interfaceFinder control.InterfaceFinder
53- networkStrategy * C.NetworkStrategy
54- networkType []C.InterfaceType
55- fallbackNetworkType []C.InterfaceType
56- networkFallbackDelay time.Duration
53+ dialer net.Dialer
54+ listener net.ListenConfig
55+ interfaceFinder control.InterfaceFinder
56+ networkStrategy * C.NetworkStrategy
57+ defaultNetworkStrategy bool
58+ networkType []C.InterfaceType
59+ fallbackNetworkType []C.InterfaceType
60+ networkFallbackDelay time.Duration
5761 )
5862 if networkManager != nil {
5963 interfaceFinder = networkManager .InterfaceFinder ()
@@ -98,6 +102,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
98102 networkStrategy = (* C .NetworkStrategy )(options .NetworkStrategy )
99103 if networkStrategy == nil {
100104 networkStrategy = common .Ptr (C .NetworkStrategyDefault )
105+ defaultNetworkStrategy = true
101106 }
102107 networkType = common .Map (options .NetworkType , option .InterfaceType .Build )
103108 fallbackNetworkType = common .Map (options .FallbackNetworkType , option .InterfaceType .Build )
@@ -192,19 +197,20 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
192197 return nil , err
193198 }
194199 return & DefaultDialer {
195- dialer4 : tcpDialer4 ,
196- dialer6 : tcpDialer6 ,
197- udpDialer4 : udpDialer4 ,
198- udpDialer6 : udpDialer6 ,
199- udpListener : listener ,
200- udpAddr4 : udpAddr4 ,
201- udpAddr6 : udpAddr6 ,
202- isWireGuardListener : options .IsWireGuardListener ,
203- networkManager : networkManager ,
204- networkStrategy : networkStrategy ,
205- networkType : networkType ,
206- fallbackNetworkType : fallbackNetworkType ,
207- networkFallbackDelay : networkFallbackDelay ,
200+ dialer4 : tcpDialer4 ,
201+ dialer6 : tcpDialer6 ,
202+ udpDialer4 : udpDialer4 ,
203+ udpDialer6 : udpDialer6 ,
204+ udpListener : listener ,
205+ udpAddr4 : udpAddr4 ,
206+ udpAddr6 : udpAddr6 ,
207+ isWireGuardListener : options .IsWireGuardListener ,
208+ networkManager : networkManager ,
209+ networkStrategy : networkStrategy ,
210+ defaultNetworkStrategy : defaultNetworkStrategy ,
211+ networkType : networkType ,
212+ fallbackNetworkType : fallbackNetworkType ,
213+ networkFallbackDelay : networkFallbackDelay ,
208214 }, nil
209215}
210216
@@ -265,7 +271,13 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
265271 conn , isPrimary , err = d .dialParallelInterfaceFastFallback (ctx , dialer , network , address .String (), * strategy , interfaceType , fallbackInterfaceType , fallbackDelay , d .networkLastFallback .Store )
266272 }
267273 if err != nil {
268- return nil , err
274+ // bind interface failed on legacy xiaomi systems
275+ if d .defaultNetworkStrategy && errors .Is (err , syscall .EPERM ) {
276+ d .networkStrategy = nil
277+ return d .DialContext (ctx , network , address )
278+ } else {
279+ return nil , err
280+ }
269281 }
270282 if ! fastFallback && ! isPrimary {
271283 d .networkLastFallback .Store (time .Now ())
@@ -307,7 +319,17 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina
307319 if destination .IsIPv4 () && ! destination .Addr .IsUnspecified () {
308320 network += "4"
309321 }
310- return trackPacketConn (d .listenSerialInterfacePacket (ctx , d .udpListener , network , "" , * strategy , interfaceType , fallbackInterfaceType , fallbackDelay ))
322+ packetConn , err := d .listenSerialInterfacePacket (ctx , d .udpListener , network , "" , * strategy , interfaceType , fallbackInterfaceType , fallbackDelay )
323+ if err != nil {
324+ // bind interface failed on legacy xiaomi systems
325+ if d .defaultNetworkStrategy && errors .Is (err , syscall .EPERM ) {
326+ d .networkStrategy = nil
327+ return d .ListenPacket (ctx , destination )
328+ } else {
329+ return nil , err
330+ }
331+ }
332+ return trackPacketConn (packetConn , nil )
311333}
312334
313335func (d * DefaultDialer ) ListenPacketCompat (network , address string ) (net.PacketConn , error ) {
0 commit comments