Skip to content

Commit 0ceb885

Browse files
committed
Fix default dialer on legacy xiaomi systems
1 parent a3278af commit 0ceb885

File tree

2 files changed

+62
-40
lines changed

2 files changed

+62
-40
lines changed

common/dialer/default.go

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package dialer
22

33
import (
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

2830
type 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

4548
func 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

313335
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {

common/dialer/default_parallel_interface.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (d *DefaultDialer) dialParallelInterface(ctx context.Context, dialer net.Di
3535
conn, err := perNetDialer.DialContext(ctx, network, addr)
3636
if err != nil {
3737
select {
38-
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}:
38+
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
3939
case <-returned:
4040
}
4141
} else {
@@ -107,7 +107,7 @@ func (d *DefaultDialer) dialParallelInterfaceFastFallback(ctx context.Context, d
107107
conn, err := perNetDialer.DialContext(ctx, network, addr)
108108
if err != nil {
109109
select {
110-
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}:
110+
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
111111
case <-returned:
112112
}
113113
} else {
@@ -157,7 +157,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
157157
if err == nil {
158158
return conn, nil
159159
}
160-
errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Name, ")"))
160+
errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Index, ")"))
161161
}
162162
for _, fallbackInterface := range fallbackInterfaces {
163163
perNetListener := listener
@@ -166,7 +166,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
166166
if err == nil {
167167
return conn, nil
168168
}
169-
errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Name, ")"))
169+
errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Index, ")"))
170170
}
171171
return nil, E.Errors(errors...)
172172
}

0 commit comments

Comments
 (0)