43 lines
1014 B
Go
43 lines
1014 B
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package prober
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
|
|
"github.com/vishvananda/netns"
|
|
)
|
|
|
|
// inNetns runs fn while the current OS thread is switched into the named
|
|
// network namespace. The thread is locked for the duration so the switch is safe.
|
|
// The original netns is restored before returning.
|
|
// If nsName is empty, fn is run in the current namespace without any switching.
|
|
func inNetns(nsName string, fn func() error) error {
|
|
if nsName == "" {
|
|
return fn()
|
|
}
|
|
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
origNs, err := netns.Get()
|
|
if err != nil {
|
|
return fmt.Errorf("get current netns: %w", err)
|
|
}
|
|
defer func() { _ = origNs.Close() }()
|
|
defer func() { _ = netns.Set(origNs) }()
|
|
|
|
targetNs, err := netns.GetFromName(nsName)
|
|
if err != nil {
|
|
return fmt.Errorf("get netns %q: %w", nsName, err)
|
|
}
|
|
defer func() { _ = targetNs.Close() }()
|
|
|
|
if err := netns.Set(targetNs); err != nil {
|
|
return fmt.Errorf("enter netns %q: %w", nsName, err)
|
|
}
|
|
|
|
return fn()
|
|
}
|