fix(dialer): split netns into platform file to support android cross-compile

This commit is contained in:
ginuerzh
2026-06-15 16:50:44 +08:00
parent 3b3eaa609a
commit 81dc9331b8
3 changed files with 63 additions and 23 deletions
+3 -23
View File
@@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"runtime"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@@ -12,7 +11,6 @@ import (
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
ctxvalue "github.com/go-gost/x/ctx" ctxvalue "github.com/go-gost/x/ctx"
xnet "github.com/go-gost/x/internal/net" xnet "github.com/go-gost/x/internal/net"
"github.com/vishvananda/netns"
) )
const ( const (
@@ -54,29 +52,11 @@ func (d *Dialer) Dial(ctx context.Context, network, addr string) (conn net.Conn,
}) })
if d.Netns != "" { if d.Netns != "" {
runtime.LockOSThread() restore, err := switchNetns(d.Netns)
defer runtime.UnlockOSThread()
originNs, err := netns.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("netns.Get(): %v", err) return nil, err
}
defer netns.Set(originNs)
var ns netns.NsHandle
if strings.HasPrefix(d.Netns, "/") {
ns, err = netns.GetFromPath(d.Netns)
} else {
ns, err = netns.GetFromName(d.Netns)
}
if err != nil {
return nil, fmt.Errorf("netns.Get(%s): %v", d.Netns, err)
}
defer ns.Close()
if err := netns.Set(ns); err != nil {
return nil, fmt.Errorf("netns.Set(%s): %v", d.Netns, err)
} }
defer restore()
} }
if d.DialFunc != nil { if d.DialFunc != nil {
+11
View File
@@ -0,0 +1,11 @@
//go:build android
package dialer
import "fmt"
// switchNetns is a no-op stub — network namespace switching is not supported
// on Android (requires privileged kernel syscalls unavailable to app sandboxes).
func switchNetns(name string) (restore func(), err error) {
return nil, fmt.Errorf("netns not supported on android")
}
+49
View File
@@ -0,0 +1,49 @@
//go:build linux && !android
package dialer
import (
"fmt"
"runtime"
"strings"
"github.com/vishvananda/netns"
)
// switchNetns enters the named network namespace and returns a cleanup
// function that restores the original namespace. The caller must defer
// the returned function.
func switchNetns(name string) (restore func(), err error) {
runtime.LockOSThread()
originNs, err := netns.Get()
if err != nil {
runtime.UnlockOSThread()
return nil, fmt.Errorf("netns.Get(): %v", err)
}
var ns netns.NsHandle
if strings.HasPrefix(name, "/") {
ns, err = netns.GetFromPath(name)
} else {
ns, err = netns.GetFromName(name)
}
if err != nil {
netns.Set(originNs)
runtime.UnlockOSThread()
return nil, fmt.Errorf("netns.Get(%s): %v", name, err)
}
if err := netns.Set(ns); err != nil {
ns.Close()
netns.Set(originNs)
runtime.UnlockOSThread()
return nil, fmt.Errorf("netns.Set(%s): %v", name, err)
}
return func() {
netns.Set(originNs)
ns.Close()
runtime.UnlockOSThread()
}, nil
}