1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
package netlink
// Network namespace ID functions
//
// The kernel has a weird concept called the network namespace ID.
// This is different from the file reference in proc (and any bind-mounted
// namespaces, etc.)
//
// Instead, namespaces can be assigned a numeric ID at any time. Once set,
// the ID is fixed. The ID can either be set manually by the user, or
// automatically, triggered by certain kernel actions. The most common kernel
// action that triggers namespace ID creation is moving one end of a veth pair
// in to that namespace.
import (
"fmt"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
// These can be replaced by the values from sys/unix when it is next released.
const (
_ = iota
NETNSA_NSID
NETNSA_PID
NETNSA_FD
)
// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
// Returns -1 if the namespace does not have an ID set.
func (h *Handle) GetNetNsIdByPid(pid int) (int, error) {
return h.getNetNsId(NETNSA_PID, uint32(pid))
}
// GetNetNsIdByPid looks up the network namespace ID for a given pid (really thread id).
// Returns -1 if the namespace does not have an ID set.
func GetNetNsIdByPid(pid int) (int, error) {
return pkgHandle.GetNetNsIdByPid(pid)
}
// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
// The ID can only be set for namespaces without an ID already set.
func (h *Handle) SetNetNsIdByPid(pid, nsid int) error {
return h.setNetNsId(NETNSA_PID, uint32(pid), uint32(nsid))
}
// SetNetNSIdByPid sets the ID of the network namespace for a given pid (really thread id).
// The ID can only be set for namespaces without an ID already set.
func SetNetNsIdByPid(pid, nsid int) error {
return pkgHandle.SetNetNsIdByPid(pid, nsid)
}
// GetNetNsIdByFd looks up the network namespace ID for a given fd.
// fd must be an open file descriptor to a namespace file.
// Returns -1 if the namespace does not have an ID set.
func (h *Handle) GetNetNsIdByFd(fd int) (int, error) {
return h.getNetNsId(NETNSA_FD, uint32(fd))
}
// GetNetNsIdByFd looks up the network namespace ID for a given fd.
// fd must be an open file descriptor to a namespace file.
// Returns -1 if the namespace does not have an ID set.
func GetNetNsIdByFd(fd int) (int, error) {
return pkgHandle.GetNetNsIdByFd(fd)
}
// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
// fd must be an open file descriptor to a namespace file.
// The ID can only be set for namespaces without an ID already set.
func (h *Handle) SetNetNsIdByFd(fd, nsid int) error {
return h.setNetNsId(NETNSA_FD, uint32(fd), uint32(nsid))
}
// SetNetNSIdByFd sets the ID of the network namespace for a given fd.
// fd must be an open file descriptor to a namespace file.
// The ID can only be set for namespaces without an ID already set.
func SetNetNsIdByFd(fd, nsid int) error {
return pkgHandle.SetNetNsIdByFd(fd, nsid)
}
// getNetNsId requests the netnsid for a given type-val pair
// type should be either NETNSA_PID or NETNSA_FD
func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
req := h.newNetlinkRequest(unix.RTM_GETNSID, unix.NLM_F_REQUEST)
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
if err != nil {
return 0, err
}
for _, m := range msgs {
msg := nl.DeserializeRtGenMsg(m)
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
if err != nil {
return 0, err
}
for _, attr := range attrs {
switch attr.Attr.Type {
case NETNSA_NSID:
return int(int32(native.Uint32(attr.Value))), nil
}
}
}
return 0, fmt.Errorf("unexpected empty result")
}
// setNetNsId sets the netnsid for a given type-val pair
// type should be either NETNSA_PID or NETNSA_FD
// The ID can only be set for namespaces without an ID already set
func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
req := h.newNetlinkRequest(unix.RTM_NEWNSID, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
b1 := make([]byte, 4)
native.PutUint32(b1, newnsid)
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
req.AddData(attr1)
_, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWNSID)
return err
}
|