91 lines
1.9 KiB
Go
91 lines
1.9 KiB
Go
package netns
|
|
|
|
// inspired from https://github.com/vishvananda/netns/blob/master/netns_linux.go#L95
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/docker/docker/pkg/namesgenerator"
|
|
"golang.org/x/sys/unix"
|
|
"os"
|
|
"path"
|
|
)
|
|
|
|
// New create and persist a new namespace with random Name
|
|
func New() (handle NsHandle, error error) {
|
|
origins, err := Get()
|
|
if err != nil {
|
|
return None(), err
|
|
}
|
|
defer deferClose(&origins, &error)
|
|
|
|
if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
|
|
return None(), err
|
|
}
|
|
|
|
newNs, err := Get()
|
|
if err != nil {
|
|
return None(), err
|
|
}
|
|
|
|
err = newNs.persist()
|
|
if err != nil {
|
|
defer deferClose(&newNs, &error)
|
|
return newNs, err
|
|
}
|
|
|
|
err = Set(origins)
|
|
if err != nil {
|
|
return NsHandle{Fd: 0}, err
|
|
}
|
|
|
|
return newNs, nil
|
|
}
|
|
|
|
func deferClose(origins *NsHandle, e *error) {
|
|
// return main error, or defer action error if occurred
|
|
if err := origins.Close(); e == nil && err != nil {
|
|
e = &err
|
|
}
|
|
}
|
|
|
|
// Delete deletes a named network namespace
|
|
func Delete(ns NsHandle) error {
|
|
namedPath := path.Join(bindMountPath, ns.Name)
|
|
|
|
err := unix.Unmount(namedPath, unix.MNT_DETACH)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.Remove(namedPath)
|
|
}
|
|
|
|
// Get gets a handle to the current threads network namespace.
|
|
func Get() (NsHandle, error) {
|
|
return GetFromPath(GetPath())
|
|
}
|
|
|
|
// GetPath gets path to the current threads network namespace.
|
|
func GetPath() string {
|
|
tid := unix.Gettid()
|
|
pid := os.Getpid()
|
|
return fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid)
|
|
}
|
|
|
|
// GetFromPath gets a handle to a network namespace
|
|
// identified by the path
|
|
func GetFromPath(path string) (NsHandle, error) {
|
|
fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
|
|
if err != nil {
|
|
return None(), err
|
|
}
|
|
name := namesgenerator.GetRandomName(0)
|
|
return NsHandle{fd, name}, nil
|
|
}
|
|
|
|
// Set sets the current network namespace to the namespace represented
|
|
// by NsHandle.
|
|
func Set(ns NsHandle) error {
|
|
return unix.Setns(ns.Fd, unix.CLONE_NEWNET)
|
|
}
|