ipnetns: add a runtime check for RTM_GETNSID support
The goal of this patch is to test during the runtime if the command RTM_GETNSID is supported by the kernel. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
This commit is contained in:
parent
5a2ce86823
commit
4c7d9a5888
58
ip/ipnetns.c
58
ip/ipnetns.c
|
|
@ -34,6 +34,56 @@ static int usage(void)
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int have_rtnl_getnsid = -1;
|
||||||
|
|
||||||
|
static int ipnetns_accept_msg(const struct sockaddr_nl *who,
|
||||||
|
struct nlmsghdr *n, void *arg)
|
||||||
|
{
|
||||||
|
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
|
||||||
|
|
||||||
|
if (n->nlmsg_type == NLMSG_ERROR &&
|
||||||
|
(err->error == -EOPNOTSUPP || err->error == -EINVAL))
|
||||||
|
have_rtnl_getnsid = 0;
|
||||||
|
else
|
||||||
|
have_rtnl_getnsid = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipnetns_have_nsid(void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
struct nlmsghdr n;
|
||||||
|
struct rtgenmsg g;
|
||||||
|
char buf[1024];
|
||||||
|
} req;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (have_rtnl_getnsid < 0) {
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
|
||||||
|
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
req.n.nlmsg_type = RTM_GETNSID;
|
||||||
|
req.g.rtgen_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
fd = open("/proc/self/ns/net", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("open(\"/proc/self/ns/net\")");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addattr32(&req.n, 1024, NETNSA_FD, fd);
|
||||||
|
|
||||||
|
if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
|
||||||
|
perror("request send failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rtnl_listen(&rth, ipnetns_accept_msg, NULL);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return have_rtnl_getnsid;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_netnsid_from_name(const char *name)
|
static int get_netnsid_from_name(const char *name)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -95,9 +145,11 @@ static int netns_list(int argc, char **argv)
|
||||||
if (strcmp(entry->d_name, "..") == 0)
|
if (strcmp(entry->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
printf("%s", entry->d_name);
|
printf("%s", entry->d_name);
|
||||||
id = get_netnsid_from_name(entry->d_name);
|
if (ipnetns_have_nsid()) {
|
||||||
if (id >= 0)
|
id = get_netnsid_from_name(entry->d_name);
|
||||||
printf(" (id: %d)", id);
|
if (id >= 0)
|
||||||
|
printf(" (id: %d)", id);
|
||||||
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue