firecracker-netns/internal/netns/netns.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)
}