From 6910a8c5ce66bbaf9f9887f19b919384608e2c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 17 Jul 2022 14:30:57 +0800 Subject: [PATCH] Improve control --- common/control/bind.go | 6 ++--- common/control/bind_linux.go | 14 ++++------- common/control/bind_windows.go | 23 ++++++++----------- common/control/interface.go | 10 ++++++++ common/control/mark_linux.go | 8 ++----- .../{protect_linux.go => protect_android.go} | 8 ++----- common/control/protect_other.go | 2 +- common/control/reuse_linux.go | 21 ----------------- common/control/reuse_other.go | 2 +- common/control/reuse_unix.go | 22 ++++++++++++++++++ common/control/reuse_windows.go | 8 ++----- go.mod | 2 ++ go.sum | 2 ++ 13 files changed, 60 insertions(+), 68 deletions(-) rename common/control/{protect_linux.go => protect_android.go} (82%) delete mode 100644 common/control/reuse_linux.go create mode 100644 common/control/reuse_unix.go diff --git a/common/control/bind.go b/common/control/bind.go index 0510848..310e78c 100644 --- a/common/control/bind.go +++ b/common/control/bind.go @@ -11,11 +11,11 @@ type BindManager interface { Update() error } -type simpleBindManager struct { +type myBindManager struct { interfaceIndexByName map[string]int } -func (m *simpleBindManager) IndexByName(name string) (int, error) { +func (m *myBindManager) IndexByName(name string) (int, error) { if index, loaded := m.interfaceIndexByName[name]; loaded { return index, nil } @@ -29,7 +29,7 @@ func (m *simpleBindManager) IndexByName(name string) (int, error) { return 0, E.New("interface ", name, " not found") } -func (m *simpleBindManager) Update() error { +func (m *myBindManager) Update() error { interfaces, err := net.Interfaces() if err != nil { return err diff --git a/common/control/bind_linux.go b/common/control/bind_linux.go index 6c7dd4e..a2e3046 100644 --- a/common/control/bind_linux.go +++ b/common/control/bind_linux.go @@ -2,8 +2,6 @@ package control import ( "syscall" - - E "github.com/sagernet/sing/common/exceptions" ) func NewBindManager() BindManager { @@ -12,11 +10,9 @@ func NewBindManager() BindManager { func BindToInterface(manager BindManager, interfaceName string) Func { return func(network, address string, conn syscall.RawConn) error { - var innerErr error - err := conn.Control(func(fd uintptr) { - innerErr = syscall.BindToDevice(int(fd), interfaceName) + return Control(conn, func(fd uintptr) error { + return syscall.BindToDevice(int(fd), interfaceName) }) - return E.Errors(innerErr, err) } } @@ -26,11 +22,9 @@ func BindToInterfaceFunc(manager BindManager, interfaceNameFunc func() string) F if interfaceName == "" { return nil } - var innerErr error - err := conn.Control(func(fd uintptr) { - innerErr = syscall.BindToDevice(int(fd), interfaceName) + return Control(conn, func(fd uintptr) error { + return syscall.BindToDevice(int(fd), interfaceName) }) - return E.Errors(innerErr, err) } } diff --git a/common/control/bind_windows.go b/common/control/bind_windows.go index 4242110..75ff5bc 100644 --- a/common/control/bind_windows.go +++ b/common/control/bind_windows.go @@ -6,8 +6,6 @@ import ( "net/netip" "syscall" "unsafe" - - E "github.com/sagernet/sing/common/exceptions" ) const ( @@ -16,7 +14,7 @@ const ( ) func NewBindManager() BindManager { - return &simpleBindManager{ + return &myBindManager{ interfaceIndexByName: make(map[string]int), } } @@ -39,28 +37,25 @@ func bindInterfaceIndex(network string, address string, conn syscall.RawConn, in return err } } - var innerErr error - err = conn.Control(func(fd uintptr) { + return Control(conn, func(fd uintptr) error { handle := syscall.Handle(fd) // handle ip empty, e.g. net.Listen("udp", ":0") if ipStr == "" { - innerErr = bind4(handle, interfaceIndex) - if innerErr != nil { - return + err = bind4(handle, interfaceIndex) + if err != nil { + return err } // try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6 bind6(handle, interfaceIndex) - return + return nil } - switch network { case "tcp4", "udp4", "ip4": - innerErr = bind4(handle, interfaceIndex) - case "tcp6", "udp6": - innerErr = bind6(handle, interfaceIndex) + return bind4(handle, interfaceIndex) + default: + return bind6(handle, interfaceIndex) } }) - return E.Errors(innerErr, err) } func BindToInterface(manager BindManager, interfaceName string) Func { diff --git a/common/control/interface.go b/common/control/interface.go index a2aa170..68ac882 100644 --- a/common/control/interface.go +++ b/common/control/interface.go @@ -2,6 +2,8 @@ package control import ( "syscall" + + E "github.com/sagernet/sing/common/exceptions" ) type Func = func(network, address string, conn syscall.RawConn) error @@ -19,3 +21,11 @@ func Append(oldFunc Func, newFunc Func) Func { return newFunc(network, address, conn) } } + +func Control(conn syscall.RawConn, block func(fd uintptr) error) error { + var innerErr error + err := conn.Control(func(fd uintptr) { + innerErr = block(fd) + }) + return E.Errors(innerErr, err) +} diff --git a/common/control/mark_linux.go b/common/control/mark_linux.go index 040ebf7..5226617 100644 --- a/common/control/mark_linux.go +++ b/common/control/mark_linux.go @@ -2,16 +2,12 @@ package control import ( "syscall" - - E "github.com/sagernet/sing/common/exceptions" ) func RoutingMark(mark int) Func { return func(network, address string, conn syscall.RawConn) error { - var innerErr error - err := conn.Control(func(fd uintptr) { - innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark) + return Control(conn, func(fd uintptr) error { + return syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark) }) - return E.Errors(innerErr, err) } } diff --git a/common/control/protect_linux.go b/common/control/protect_android.go similarity index 82% rename from common/control/protect_linux.go rename to common/control/protect_android.go index 62e234c..2ee5b57 100644 --- a/common/control/protect_linux.go +++ b/common/control/protect_android.go @@ -1,5 +1,3 @@ -//go:build linux - package control import ( @@ -36,10 +34,8 @@ func sendAncillaryFileDescriptors(protectPath string, fileDescriptors []int) err func ProtectPath(protectPath string) Func { return func(network, address string, conn syscall.RawConn) error { - var innerErr error - err := conn.Control(func(fd uintptr) { - innerErr = sendAncillaryFileDescriptors(protectPath, []int{int(fd)}) + return Control(conn, func(fd uintptr) error { + return sendAncillaryFileDescriptors(protectPath, []int{int(fd)}) }) - return E.Errors(innerErr, err) } } diff --git a/common/control/protect_other.go b/common/control/protect_other.go index 3a5ca0f..49299b5 100644 --- a/common/control/protect_other.go +++ b/common/control/protect_other.go @@ -1,4 +1,4 @@ -//go:build !linux +//go:build !android package control diff --git a/common/control/reuse_linux.go b/common/control/reuse_linux.go deleted file mode 100644 index 3d92db1..0000000 --- a/common/control/reuse_linux.go +++ /dev/null @@ -1,21 +0,0 @@ -package control - -import ( - "syscall" - - E "github.com/sagernet/sing/common/exceptions" -) - -func ReuseAddr() Func { - return func(network, address string, conn syscall.RawConn) error { - var innerErr error - err := conn.Control(func(fd uintptr) { - const SO_REUSEPORT = 0xf - innerErr = E.Errors( - syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1), - syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEPORT, 1), - ) - }) - return E.Errors(innerErr, err) - } -} diff --git a/common/control/reuse_other.go b/common/control/reuse_other.go index 69c5be4..0709424 100644 --- a/common/control/reuse_other.go +++ b/common/control/reuse_other.go @@ -1,4 +1,4 @@ -//go:build !linux && !windows +//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows package control diff --git a/common/control/reuse_unix.go b/common/control/reuse_unix.go new file mode 100644 index 0000000..c841c31 --- /dev/null +++ b/common/control/reuse_unix.go @@ -0,0 +1,22 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package control + +import ( + "syscall" + + E "github.com/sagernet/sing/common/exceptions" + + "golang.org/x/sys/unix" +) + +func ReuseAddr() Func { + return func(network, address string, conn syscall.RawConn) error { + return Control(conn, func(fd uintptr) error { + return E.Errors( + unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1), + unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1), + ) + }) + } +} diff --git a/common/control/reuse_windows.go b/common/control/reuse_windows.go index 6b1132c..b7f4cf9 100644 --- a/common/control/reuse_windows.go +++ b/common/control/reuse_windows.go @@ -2,16 +2,12 @@ package control import ( "syscall" - - E "github.com/sagernet/sing/common/exceptions" ) func ReuseAddr() Func { return func(network, address string, conn syscall.RawConn) error { - var innerErr error - err := conn.Control(func(fd uintptr) { - innerErr = syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + return Control(conn, func(fd uintptr) error { + return syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) }) - return E.Errors(innerErr, err) } } diff --git a/go.mod b/go.mod index 219df77..5e43a31 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/sagernet/sing go 1.18 + +require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 diff --git a/go.sum b/go.sum index e69de29..28ab7f7 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=