From b8bd28f357fb41921b8e9ce2087f03b2d91ab556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 11 Jul 2026 15:52:20 +0800 Subject: [PATCH] Fix netns manager --- common/netns/manager_linux.go | 57 +++++++++++++++++++++++++++++-- common/netns/manager_stub.go | 25 +++++++++++--- common/netns/netns.go | 63 ----------------------------------- 3 files changed, 75 insertions(+), 70 deletions(-) diff --git a/common/netns/manager_linux.go b/common/netns/manager_linux.go index 3a5ab5c56..f53279c30 100644 --- a/common/netns/manager_linux.go +++ b/common/netns/manager_linux.go @@ -9,20 +9,65 @@ import ( "syscall" "github.com/sagernet/netlink" + "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/logger" vnetns "github.com/vishvananda/netns" ) +type Manager struct { + logger logger.ContextLogger + namespaces []option.NetworkNamespace + holderArgs []string + paths map[string]string + holders []*holder +} + type holder struct { command *exec.Cmd pipeWriter *os.File pidFile string } -func (m *Manager) start() error { +func NewManager(logger logger.ContextLogger, namespaces []option.NetworkNamespace, holderArgs []string) (*Manager, error) { + paths := make(map[string]string) + for _, namespace := range namespaces { + if namespace.Tag == "" { + return nil, E.New("network namespace: missing tag") + } + _, duplicated := paths[namespace.Tag] + if duplicated { + return nil, E.New("network namespace: duplicated tag: ", namespace.Tag) + } + switch namespace.Type { + case C.NetNsTypeDefault: + if namespace.DefaultOptions.Path == "" { + return nil, E.New("network namespace[", namespace.Tag, "]: missing path") + } + paths[namespace.Tag] = namespace.DefaultOptions.Path + case C.NetNsTypeUnshare: + paths[namespace.Tag] = "" + } + } + return &Manager{ + logger: logger, + namespaces: namespaces, + holderArgs: holderArgs, + paths: paths, + }, nil +} + +func (m *Manager) Name() string { + return "netns" +} + +func (m *Manager) Start(stage adapter.StartStage) error { + if stage != adapter.StartStateInitialize { + return nil + } for _, namespace := range m.namespaces { switch namespace.Type { case C.NetNsTypeDefault: @@ -70,7 +115,7 @@ func (m *Manager) startNamespace(namespace option.NetworkNamespace) error { return nil } -func (m *Manager) close() error { +func (m *Manager) Close() error { for _, created := range m.holders { created.pipeWriter.Close() if created.pidFile != "" { @@ -81,6 +126,14 @@ func (m *Manager) close() error { return nil } +func (m *Manager) ResolvePath(nameOrPath string) string { + path, loaded := m.paths[nameOrPath] + if loaded && path != "" { + return path + } + return nameOrPath +} + func netnsPath(pid int) string { return "/proc/" + strconv.Itoa(pid) + "/ns/net" } diff --git a/common/netns/manager_stub.go b/common/netns/manager_stub.go index 9ee604727..0bcd255af 100644 --- a/common/netns/manager_stub.go +++ b/common/netns/manager_stub.go @@ -3,18 +3,33 @@ package netns import ( + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/logger" ) -type holder struct{} +type Manager struct{} -func (m *Manager) start() error { - if len(m.namespaces) > 0 { - return E.New("network namespaces are only supported on Linux") +func NewManager(logger logger.ContextLogger, namespaces []option.NetworkNamespace, holderArgs []string) (*Manager, error) { + if len(namespaces) > 0 { + return nil, E.New("network namespaces are only supported on Linux") } + return &Manager{}, nil +} + +func (m *Manager) Name() string { + return "netns" +} + +func (m *Manager) Start(stage adapter.StartStage) error { return nil } -func (m *Manager) close() error { +func (m *Manager) Close() error { return nil } + +func (m *Manager) ResolvePath(nameOrPath string) string { + return nameOrPath +} diff --git a/common/netns/netns.go b/common/netns/netns.go index 50d39696a..79ce43e6f 100644 --- a/common/netns/netns.go +++ b/common/netns/netns.go @@ -4,73 +4,10 @@ import ( "os" "github.com/sagernet/sing-box/adapter" - C "github.com/sagernet/sing-box/constant" - "github.com/sagernet/sing-box/option" - E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/logger" ) var _ adapter.NetworkNamespaceManager = (*Manager)(nil) -type Manager struct { - logger logger.ContextLogger - namespaces []option.NetworkNamespace - holderArgs []string - paths map[string]string - holders []*holder -} - -func NewManager(logger logger.ContextLogger, namespaces []option.NetworkNamespace, holderArgs []string) (*Manager, error) { - paths := make(map[string]string) - for _, namespace := range namespaces { - if namespace.Tag == "" { - return nil, E.New("network namespace: missing tag") - } - _, duplicated := paths[namespace.Tag] - if duplicated { - return nil, E.New("network namespace: duplicated tag: ", namespace.Tag) - } - switch namespace.Type { - case C.NetNsTypeDefault: - if namespace.DefaultOptions.Path == "" { - return nil, E.New("network namespace[", namespace.Tag, "]: missing path") - } - paths[namespace.Tag] = namespace.DefaultOptions.Path - case C.NetNsTypeUnshare: - paths[namespace.Tag] = "" - } - } - return &Manager{ - logger: logger, - namespaces: namespaces, - holderArgs: holderArgs, - paths: paths, - }, nil -} - -func (m *Manager) Name() string { - return "netns" -} - -func (m *Manager) Start(stage adapter.StartStage) error { - if stage != adapter.StartStateInitialize { - return nil - } - return m.start() -} - -func (m *Manager) Close() error { - return m.close() -} - -func (m *Manager) ResolvePath(nameOrPath string) string { - path, loaded := m.paths[nameOrPath] - if loaded && path != "" { - return path - } - return nameOrPath -} - func Hold() { buffer := make([]byte, 1) for {