diff --git a/common/dialer/default.go b/common/dialer/default.go index 4cf13883..10ed752b 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -3,10 +3,10 @@ package dialer import ( "context" "net" - "runtime" "time" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/warning" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" @@ -16,6 +16,41 @@ import ( "github.com/database64128/tfo-go" ) +var warnBindInterfaceOnUnsupportedPlatform = warning.New( + func() bool { + return !(C.IsLinux || C.IsWindows) + }, + "outbound option `bind_interface` is only supported on Linux and Windows", +) + +var warnRoutingMarkOnUnsupportedPlatform = warning.New( + func() bool { + return !C.IsLinux + }, + "outbound option `routing_mark` is only supported on Linux", +) + +var warnReuseAdderOnUnsupportedPlatform = warning.New( + func() bool { + return !(C.IsDarwin || C.IsDragonfly || C.IsFreebsd || C.IsLinux || C.IsNetbsd || C.IsOpenbsd || C.IsSolaris || C.IsWindows) + }, + "outbound option `reuse_addr` is unsupported on current platform", +) + +var warnProtectPathOnNonAndroid = warning.New( + func() bool { + return !C.IsAndroid + }, + "outbound option `protect_path` is only supported on Android", +) + +var warnTFOOnUnsupportedPlatform = warning.New( + func() bool { + return !(C.IsDarwin || C.IsFreebsd || C.IsLinux || C.IsWindows) + }, + "outbound option `tcp_fast_open` is unsupported on current platform", +) + type DefaultDialer struct { tfo.Dialer net.ListenConfig @@ -25,10 +60,11 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia var dialer net.Dialer var listener net.ListenConfig if options.BindInterface != "" { + warnBindInterfaceOnUnsupportedPlatform.Check() dialer.Control = control.Append(dialer.Control, control.BindToInterface(router.InterfaceBindManager(), options.BindInterface)) listener.Control = control.Append(listener.Control, control.BindToInterface(router.InterfaceBindManager(), options.BindInterface)) } else if router.AutoDetectInterface() { - if runtime.GOOS == "windows" { + if C.IsWindows { dialer.Control = control.Append(dialer.Control, control.BindToInterfaceIndexFunc(func() int { return router.AutoDetectInterfaceIndex() })) @@ -48,6 +84,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia listener.Control = control.Append(listener.Control, control.BindToInterface(router.InterfaceBindManager(), router.DefaultInterface())) } if options.RoutingMark != 0 { + warnRoutingMarkOnUnsupportedPlatform.Check() dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark)) listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark)) } else if router.DefaultMark() != 0 { @@ -55,9 +92,11 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia listener.Control = control.Append(listener.Control, control.RoutingMark(router.DefaultMark())) } if options.ReuseAddr { + warnReuseAdderOnUnsupportedPlatform.Check() listener.Control = control.Append(listener.Control, control.ReuseAddr()) } if options.ProtectPath != "" { + warnProtectPathOnNonAndroid.Check() dialer.Control = control.Append(dialer.Control, control.ProtectPath(options.ProtectPath)) listener.Control = control.Append(listener.Control, control.ProtectPath(options.ProtectPath)) } @@ -66,6 +105,9 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia } else { dialer.Timeout = C.DefaultTCPTimeout } + if options.TCPFastOpen { + warnTFOOnUnsupportedPlatform.Check() + } return &DefaultDialer{tfo.Dialer{Dialer: dialer, DisableTFO: !options.TCPFastOpen}, listener} } diff --git a/common/warning/warning.go b/common/warning/warning.go new file mode 100644 index 00000000..dbcdc3d8 --- /dev/null +++ b/common/warning/warning.go @@ -0,0 +1,31 @@ +package warning + +import ( + "sync" + + "github.com/sagernet/sing-box/log" +) + +type Warning struct { + logger log.Logger + check CheckFunc + message string + checkOnce sync.Once +} + +type CheckFunc = func() bool + +func New(checkFunc CheckFunc, message string) Warning { + return Warning{ + check: checkFunc, + message: message, + } +} + +func (w *Warning) Check() { + w.checkOnce.Do(func() { + if w.check() { + log.Warn(w.message) + } + }) +} diff --git a/constant/goos/gengoos.go b/constant/goos/gengoos.go new file mode 100644 index 00000000..4b7c6662 --- /dev/null +++ b/constant/goos/gengoos.go @@ -0,0 +1,68 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import ( + "bytes" + "fmt" + "log" + "os" + "strconv" + "strings" +) + +var gooses []string + +func main() { + data, err := os.ReadFile("../../go/build/syslist.go") + if err != nil { + log.Fatal(err) + } + const goosPrefix = `const goosList = ` + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, goosPrefix) { + text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix)) + if err != nil { + log.Fatalf("parsing goosList: %v", err) + } + gooses = strings.Fields(text) + } + } + + for _, target := range gooses { + if target == "nacl" { + continue + } + var tags []string + if target == "linux" { + tags = append(tags, "!android") // must explicitly exclude android for linux + } + if target == "solaris" { + tags = append(tags, "!illumos") // must explicitly exclude illumos for solaris + } + if target == "darwin" { + tags = append(tags, "!ios") // must explicitly exclude ios for darwin + } + tags = append(tags, target) // must explicitly include target for bootstrapping purposes + var buf bytes.Buffer + fmt.Fprintf(&buf, "// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.\n\n") + fmt.Fprintf(&buf, "//go:build %s\n", strings.Join(tags, " && ")) + fmt.Fprintf(&buf, "package goos\n\n") + fmt.Fprintf(&buf, "const GOOS = `%s`\n\n", target) + for _, goos := range gooses { + value := 0 + if goos == target { + value = 1 + } + fmt.Fprintf(&buf, "const Is%s = %d\n", strings.Title(goos), value) + } + err := os.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0o666) + if err != nil { + log.Fatal(err) + } + } +} diff --git a/constant/goos/goos.go b/constant/goos/goos.go new file mode 100644 index 00000000..ebb521fe --- /dev/null +++ b/constant/goos/goos.go @@ -0,0 +1,12 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package goos contains GOOS-specific constants. +package goos + +// The next line makes 'go generate' write the zgoos*.go files with +// per-OS information, including constants named Is$GOOS for every +// known GOOS. The constant is 1 on the current system, 0 otherwise; +// multiplying by them is useful for defining GOOS-specific constants. +//go:generate go run gengoos.go diff --git a/constant/goos/zgoos_aix.go b/constant/goos/zgoos_aix.go new file mode 100644 index 00000000..ff861550 --- /dev/null +++ b/constant/goos/zgoos_aix.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build aix + +package goos + +const GOOS = `aix` + +const IsAix = 1 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_android.go b/constant/goos/zgoos_android.go new file mode 100644 index 00000000..e8aaa124 --- /dev/null +++ b/constant/goos/zgoos_android.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build android + +package goos + +const GOOS = `android` + +const IsAix = 0 +const IsAndroid = 1 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_darwin.go b/constant/goos/zgoos_darwin.go new file mode 100644 index 00000000..decdd496 --- /dev/null +++ b/constant/goos/zgoos_darwin.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !ios && darwin + +package goos + +const GOOS = `darwin` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 1 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_dragonfly.go b/constant/goos/zgoos_dragonfly.go new file mode 100644 index 00000000..2224baa2 --- /dev/null +++ b/constant/goos/zgoos_dragonfly.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build dragonfly + +package goos + +const GOOS = `dragonfly` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 1 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_freebsd.go b/constant/goos/zgoos_freebsd.go new file mode 100644 index 00000000..3ee5bf99 --- /dev/null +++ b/constant/goos/zgoos_freebsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build freebsd + +package goos + +const GOOS = `freebsd` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 1 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_hurd.go b/constant/goos/zgoos_hurd.go new file mode 100644 index 00000000..8a3d3430 --- /dev/null +++ b/constant/goos/zgoos_hurd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build hurd + +package goos + +const GOOS = `hurd` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 1 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_illumos.go b/constant/goos/zgoos_illumos.go new file mode 100644 index 00000000..fc1b9a9e --- /dev/null +++ b/constant/goos/zgoos_illumos.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build illumos + +package goos + +const GOOS = `illumos` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 1 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_ios.go b/constant/goos/zgoos_ios.go new file mode 100644 index 00000000..746e769e --- /dev/null +++ b/constant/goos/zgoos_ios.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build ios + +package goos + +const GOOS = `ios` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 1 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_js.go b/constant/goos/zgoos_js.go new file mode 100644 index 00000000..6cf2a5d9 --- /dev/null +++ b/constant/goos/zgoos_js.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build js + +package goos + +const GOOS = `js` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 1 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_linux.go b/constant/goos/zgoos_linux.go new file mode 100644 index 00000000..cb9d6e8a --- /dev/null +++ b/constant/goos/zgoos_linux.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !android && linux + +package goos + +const GOOS = `linux` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 1 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_netbsd.go b/constant/goos/zgoos_netbsd.go new file mode 100644 index 00000000..8285928d --- /dev/null +++ b/constant/goos/zgoos_netbsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build netbsd + +package goos + +const GOOS = `netbsd` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 1 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_openbsd.go b/constant/goos/zgoos_openbsd.go new file mode 100644 index 00000000..3f739a4a --- /dev/null +++ b/constant/goos/zgoos_openbsd.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build openbsd + +package goos + +const GOOS = `openbsd` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 1 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_plan9.go b/constant/goos/zgoos_plan9.go new file mode 100644 index 00000000..d4c1c651 --- /dev/null +++ b/constant/goos/zgoos_plan9.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build plan9 + +package goos + +const GOOS = `plan9` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 1 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_solaris.go b/constant/goos/zgoos_solaris.go new file mode 100644 index 00000000..69e3285a --- /dev/null +++ b/constant/goos/zgoos_solaris.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build !illumos && solaris + +package goos + +const GOOS = `solaris` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 1 +const IsWindows = 0 +const IsZos = 0 diff --git a/constant/goos/zgoos_windows.go b/constant/goos/zgoos_windows.go new file mode 100644 index 00000000..16158be7 --- /dev/null +++ b/constant/goos/zgoos_windows.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build windows + +package goos + +const GOOS = `windows` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 1 +const IsZos = 0 diff --git a/constant/goos/zgoos_zos.go b/constant/goos/zgoos_zos.go new file mode 100644 index 00000000..fb6165c7 --- /dev/null +++ b/constant/goos/zgoos_zos.go @@ -0,0 +1,25 @@ +// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. + +//go:build zos + +package goos + +const GOOS = `zos` + +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 1 diff --git a/constant/os.go b/constant/os.go new file mode 100644 index 00000000..792dda55 --- /dev/null +++ b/constant/os.go @@ -0,0 +1,37 @@ +package constant + +import ( + "github.com/sagernet/sing-box/constant/goos" +) + +const IsAndroid = goos.IsAndroid == 1 + +const IsDarwin = goos.IsDarwin == 1 + +const IsDragonfly = goos.IsDragonfly == 1 + +const IsFreebsd = goos.IsFreebsd == 1 + +const IsHurd = goos.IsHurd == 1 + +const IsIllumos = goos.IsIllumos == 1 + +const IsIos = goos.IsIos == 1 + +const IsJs = goos.IsJs == 1 + +const IsLinux = goos.IsLinux == 1 + +const IsNacl = goos.IsNacl == 1 + +const IsNetbsd = goos.IsNetbsd == 1 + +const IsOpenbsd = goos.IsOpenbsd == 1 + +const IsPlan9 = goos.IsPlan9 == 1 + +const IsSolaris = goos.IsSolaris == 1 + +const IsWindows = goos.IsWindows == 1 + +const IsZos = goos.IsZos == 1 diff --git a/inbound/tun.go b/inbound/tun.go index 187e1433..b57a6782 100644 --- a/inbound/tun.go +++ b/inbound/tun.go @@ -6,7 +6,6 @@ import ( "context" "net" "net/netip" - "runtime" "strconv" "strings" @@ -140,10 +139,9 @@ func (t *Tun) NewError(ctx context.Context, err error) { } func mkInterfaceName() (tunName string) { - switch runtime.GOOS { - case "darwin": + if C.IsDarwin { tunName = "utun" - default: + } else { tunName = "tun" } interfaces, err := net.Interfaces() diff --git a/route/router.go b/route/router.go index 3bb1a9e4..e72bc218 100644 --- a/route/router.go +++ b/route/router.go @@ -21,6 +21,7 @@ import ( "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/sniff" "github.com/sagernet/sing-box/common/urltest" + "github.com/sagernet/sing-box/common/warning" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" @@ -38,6 +39,27 @@ import ( "golang.org/x/net/dns/dnsmessage" ) +var warnDefaultInterfaceOnUnsupportedPlatform = warning.New( + func() bool { + return !(C.IsLinux || C.IsWindows) + }, + "route option `default_mark` is only supported on Linux and Windows", +) + +var warnDefaultMarkOnNonLinux = warning.New( + func() bool { + return !C.IsLinux + }, + "route option `default_mark` is only supported on Linux", +) + +var warnFindProcessOnUnsupportedPlatform = warning.New( + func() bool { + return !(C.IsLinux || C.IsWindows || C.IsDarwin) + }, + "route option `find_process` is only supported on Linux, Windows, and Mac OS X", +) + var _ adapter.Router = (*Router)(nil) type Router struct { @@ -75,6 +97,16 @@ type Router struct { } func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions) (*Router, error) { + if options.DefaultInterface != "" { + warnDefaultInterfaceOnUnsupportedPlatform.Check() + } + if options.DefaultMark != 0 { + warnDefaultMarkOnNonLinux.Check() + } + if options.FindProcess { + warnFindProcessOnUnsupportedPlatform.Check() + } + router := &Router{ ctx: ctx, logger: logger, @@ -225,9 +257,12 @@ func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.Cont if hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess { searcher, err := process.NewSearcher(logger) if err != nil { - return nil, E.Cause(err, "create process searcher") + if err != os.ErrInvalid { + logger.Warn(E.Cause(err, "create process searcher")) + } + } else { + router.processSearcher = searcher } - router.processSearcher = searcher } return router, nil } @@ -388,7 +423,8 @@ func (r *Router) Start() error { if starter, isStarter := r.processSearcher.(common.Starter); isStarter { err := starter.Start() if err != nil { - return E.Cause(err, "initialize process searcher") + r.logger.Error(E.Cause(err, "initialize process searcher")) + r.processSearcher = nil } } } diff --git a/route/rule_package_name.go b/route/rule_package_name.go index d1ca09eb..3289b503 100644 --- a/route/rule_package_name.go +++ b/route/rule_package_name.go @@ -4,6 +4,13 @@ import ( "strings" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/warning" + C "github.com/sagernet/sing-box/constant" +) + +var warnPackageNameOnNonAndroid = warning.New( + func() bool { return !C.IsAndroid }, + "rule item `package_name` is only supported on Android", ) var _ RuleItem = (*PackageNameItem)(nil) @@ -14,6 +21,7 @@ type PackageNameItem struct { } func NewPackageNameItem(packageNameList []string) *PackageNameItem { + warnPackageNameOnNonAndroid.Check() rule := &PackageNameItem{ packageNames: packageNameList, packageMap: make(map[string]bool), diff --git a/route/rule_process.go b/route/rule_process.go index ec874a4f..84f474b2 100644 --- a/route/rule_process.go +++ b/route/rule_process.go @@ -5,6 +5,13 @@ import ( "strings" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/warning" + C "github.com/sagernet/sing-box/constant" +) + +var warnProcessNameOnNonSupportedPlatform = warning.New( + func() bool { return !(C.IsLinux || C.IsWindows || C.IsDarwin) }, + "rule item `process_item` is only supported on Linux, Windows, and Mac OS X", ) var _ RuleItem = (*ProcessItem)(nil) @@ -15,6 +22,7 @@ type ProcessItem struct { } func NewProcessItem(processNameList []string) *ProcessItem { + warnProcessNameOnNonSupportedPlatform.Check() rule := &ProcessItem{ processes: processNameList, processMap: make(map[string]bool), diff --git a/route/rule_user.go b/route/rule_user.go index bed97fba..22710ef9 100644 --- a/route/rule_user.go +++ b/route/rule_user.go @@ -4,9 +4,22 @@ import ( "strings" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/warning" + C "github.com/sagernet/sing-box/constant" F "github.com/sagernet/sing/common/format" ) +var ( + warnUserOnNonLinux = warning.New( + func() bool { return !C.IsLinux }, + "rule item `user` is only supported on Linux", + ) + warnUserOnCGODisabled = warning.New( + func() bool { return !C.CGO_ENABLED }, + "rule item `user` is only supported with CGO enabled, rebuild with CGO_ENABLED=1", + ) +) + var _ RuleItem = (*UserItem)(nil) type UserItem struct { @@ -15,6 +28,8 @@ type UserItem struct { } func NewUserItem(users []string) *UserItem { + warnUserOnNonLinux.Check() + warnUserOnCGODisabled.Check() userMap := make(map[string]bool) for _, protocol := range users { userMap[protocol] = true diff --git a/route/rule_user_id.go b/route/rule_user_id.go index 43ab704e..59841300 100644 --- a/route/rule_user_id.go +++ b/route/rule_user_id.go @@ -4,9 +4,16 @@ import ( "strings" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/warning" + C "github.com/sagernet/sing-box/constant" F "github.com/sagernet/sing/common/format" ) +var warnUserIDOnNonLinux = warning.New( + func() bool { return !C.IsLinux }, + "rule item `user_id` is only supported on Linux", +) + var _ RuleItem = (*UserIdItem)(nil) type UserIdItem struct { @@ -15,6 +22,7 @@ type UserIdItem struct { } func NewUserIDItem(userIdList []int32) *UserIdItem { + warnUserIDOnNonLinux.Check() rule := &UserIdItem{ userIds: userIdList, userIdMap: make(map[int32]bool), diff --git a/test/clash_test.go b/test/clash_test.go index 8e5535b8..90ceff7a 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -8,11 +8,11 @@ import ( "io" "net" "net/netip" - "runtime" "sync" "testing" "time" + C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing/common/control" F "github.com/sagernet/sing/common/format" @@ -37,13 +37,10 @@ var allImages = []string{ ImageV2RayCore, } -var ( - localIP = netip.MustParseAddr("127.0.0.1") - isDarwin = runtime.GOOS == "darwin" -) +var localIP = netip.MustParseAddr("127.0.0.1") func init() { - if isDarwin { + if C.IsDarwin { var err error localIP, err = defaultRouteIP() if err != nil { diff --git a/test/docker_test.go b/test/docker_test.go index 10d41eb2..2ed6c29f 100644 --- a/test/docker_test.go +++ b/test/docker_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + C "github.com/sagernet/sing-box/constant" F "github.com/sagernet/sing/common/format" "github.com/docker/docker/api/types" @@ -47,7 +48,7 @@ func startDockerContainer(t *testing.T, options DockerOptions) { containerOptions.ExposedPorts = make(nat.PortSet) var hostOptions container.HostConfig - if !isDarwin { + if !C.IsDarwin { hostOptions.NetworkMode = "host" } hostOptions.PortBindings = make(nat.PortMap)