Skip to content

Commit

Permalink
Allows to create and delete named network namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-maurice authored and vishvananda committed Jul 28, 2020
1 parent 1e46305 commit db3c7e5
Showing 1 changed file with 52 additions and 6 deletions.
58 changes: 52 additions & 6 deletions netns_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,24 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"syscall"

"golang.org/x/sys/unix"
)

// Deprecated: use syscall pkg instead (go >= 1.5 needed).
const (
CLONE_NEWUTS = 0x04000000 /* New utsname group? */
CLONE_NEWIPC = 0x08000000 /* New ipcs */
CLONE_NEWUSER = 0x10000000 /* New user namespace */
CLONE_NEWPID = 0x20000000 /* New pid namespace */
CLONE_NEWNET = 0x40000000 /* New network namespace */
CLONE_IO = 0x80000000 /* Get io context */
CLONE_NEWUTS = 0x04000000 /* New utsname group? */
CLONE_NEWIPC = 0x08000000 /* New ipcs */
CLONE_NEWUSER = 0x10000000 /* New user namespace */
CLONE_NEWPID = 0x20000000 /* New pid namespace */
CLONE_NEWNET = 0x40000000 /* New network namespace */
CLONE_IO = 0x80000000 /* Get io context */
bindMountPath = "/run/netns" /* Bind mount path for named netns */
)

// Setns sets namespace using syscall. Note that this should be a method
Expand All @@ -44,6 +47,49 @@ func New() (ns NsHandle, err error) {
return Get()
}

// NewNamed creates a new named network namespace and returns a handle to it
func NewNamed(name string) (NsHandle, error) {
if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
err = os.MkdirAll(bindMountPath, 0755)
if err != nil {
return None(), err
}
}

newNs, err := New()
if err != nil {
return None(), err
}

namedPath := path.Join(bindMountPath, name)

f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
if err != nil {
return None(), err
}
f.Close()

nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())
err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "")
if err != nil {
return None(), err
}

return newNs, nil
}

// DeleteNamed deletes a named network namespace
func DeleteNamed(name string) error {
namedPath := path.Join(bindMountPath, name)

err := syscall.Unmount(namedPath, syscall.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 GetFromThread(os.Getpid(), unix.Gettid())
Expand Down

0 comments on commit db3c7e5

Please sign in to comment.