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