Fix default dialer on legacy xiaomi systems

This commit is contained in:
世界 2024-12-21 21:26:42 +08:00
parent eb2f45babe
commit 62ee8903e1
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
2 changed files with 62 additions and 40 deletions

View file

@ -2,8 +2,10 @@ package dialer
import ( import (
"context" "context"
"errors"
"net" "net"
"net/netip" "net/netip"
"syscall"
"time" "time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
@ -36,6 +38,7 @@ type DefaultDialer struct {
isWireGuardListener bool isWireGuardListener bool
networkManager adapter.NetworkManager networkManager adapter.NetworkManager
networkStrategy *C.NetworkStrategy networkStrategy *C.NetworkStrategy
defaultNetworkStrategy bool
networkType []C.InterfaceType networkType []C.InterfaceType
fallbackNetworkType []C.InterfaceType fallbackNetworkType []C.InterfaceType
networkFallbackDelay time.Duration networkFallbackDelay time.Duration
@ -51,6 +54,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
listener net.ListenConfig listener net.ListenConfig
interfaceFinder control.InterfaceFinder interfaceFinder control.InterfaceFinder
networkStrategy *C.NetworkStrategy networkStrategy *C.NetworkStrategy
defaultNetworkStrategy bool
networkType []C.InterfaceType networkType []C.InterfaceType
fallbackNetworkType []C.InterfaceType fallbackNetworkType []C.InterfaceType
networkFallbackDelay time.Duration networkFallbackDelay time.Duration
@ -98,6 +102,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy) networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
if networkStrategy == nil { if networkStrategy == nil {
networkStrategy = common.Ptr(C.NetworkStrategyDefault) networkStrategy = common.Ptr(C.NetworkStrategyDefault)
defaultNetworkStrategy = true
} }
networkType = common.Map(options.NetworkType, option.InterfaceType.Build) networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build) fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
@ -202,6 +207,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
isWireGuardListener: options.IsWireGuardListener, isWireGuardListener: options.IsWireGuardListener,
networkManager: networkManager, networkManager: networkManager,
networkStrategy: networkStrategy, networkStrategy: networkStrategy,
defaultNetworkStrategy: defaultNetworkStrategy,
networkType: networkType, networkType: networkType,
fallbackNetworkType: fallbackNetworkType, fallbackNetworkType: fallbackNetworkType,
networkFallbackDelay: networkFallbackDelay, networkFallbackDelay: networkFallbackDelay,
@ -265,8 +271,14 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store) conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
} }
if err != nil { if err != nil {
// bind interface failed on legacy xiaomi systems
if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
d.networkStrategy = nil
return d.DialContext(ctx, network, address)
} else {
return nil, err return nil, err
} }
}
if !fastFallback && !isPrimary { if !fastFallback && !isPrimary {
d.networkLastFallback.Store(time.Now()) d.networkLastFallback.Store(time.Now())
} }
@ -307,7 +319,17 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina
if destination.IsIPv4() && !destination.Addr.IsUnspecified() { if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
network += "4" network += "4"
} }
return trackPacketConn(d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)) packetConn, err := d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
if err != nil {
// bind interface failed on legacy xiaomi systems
if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
d.networkStrategy = nil
return d.ListenPacket(ctx, destination)
} else {
return nil, err
}
}
return trackPacketConn(packetConn, nil)
} }
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) { func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {

View file

@ -35,7 +35,7 @@ func (d *DefaultDialer) dialParallelInterface(ctx context.Context, dialer net.Di
conn, err := perNetDialer.DialContext(ctx, network, addr) conn, err := perNetDialer.DialContext(ctx, network, addr)
if err != nil { if err != nil {
select { select {
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}: case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
case <-returned: case <-returned:
} }
} else { } else {
@ -107,7 +107,7 @@ func (d *DefaultDialer) dialParallelInterfaceFastFallback(ctx context.Context, d
conn, err := perNetDialer.DialContext(ctx, network, addr) conn, err := perNetDialer.DialContext(ctx, network, addr)
if err != nil { if err != nil {
select { select {
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}: case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
case <-returned: case <-returned:
} }
} else { } else {
@ -157,7 +157,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
if err == nil { if err == nil {
return conn, nil return conn, nil
} }
errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Name, ")")) errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Index, ")"))
} }
for _, fallbackInterface := range fallbackInterfaces { for _, fallbackInterface := range fallbackInterfaces {
perNetListener := listener perNetListener := listener
@ -166,7 +166,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
if err == nil { if err == nil {
return conn, nil return conn, nil
} }
errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Name, ")")) errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Index, ")"))
} }
return nil, E.Errors(errors...) return nil, E.Errors(errors...)
} }