summaryrefslogtreecommitdiff
path: root/lib/ns.c
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2015-09-03 10:47:43 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2016-09-09 12:15:14 -0400
commitc253dcb5d80aa60112bb31ab95ae9839081064d3 (patch)
tree3b2e993379f5b46394476897e2997fb76eae8159 /lib/ns.c
parent13460c44a22415dd55846aca6fc31cf8607c90e9 (diff)
vrf: add a runtime check before playing with netns
This patch adds a runtime check to determine if netns are available. Some systems like OpenWRT have the system call setns() but don't have the kernel option CONFIG_NET_NS enabled. Reported-by: Christian Franke <chris@opensourcerouting.org> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Tested-by: Christian Franke <chris@opensourcerouting.org> (cherry picked from commit 04a3aabf58d95d01c4c8168eeff43cf9d9892eee)
Diffstat (limited to 'lib/ns.c')
-rw-r--r--lib/ns.c94
1 files changed, 57 insertions, 37 deletions
diff --git a/lib/ns.c b/lib/ns.c
index 6fb124181b..4765a18ef2 100644
--- a/lib/ns.c
+++ b/lib/ns.c
@@ -39,7 +39,6 @@
#include "command.h"
#include "vty.h"
-#ifdef HAVE_NETNS
#ifndef CLONE_NEWNET
#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */
@@ -57,7 +56,10 @@ static inline int setns(int fd, int nstype)
}
#endif /* HAVE_SETNS */
+#ifdef HAVE_NETNS
+
#define NS_DEFAULT_NAME "/proc/self/ns/net"
+static int have_netns_enabled = -1;
#else /* !HAVE_NETNS */
@@ -65,6 +67,27 @@ static inline int setns(int fd, int nstype)
#endif /* HAVE_NETNS */
+static int have_netns(void)
+{
+#ifdef HAVE_NETNS
+ if (have_netns_enabled < 0)
+ {
+ int fd = open (NS_DEFAULT_NAME, O_RDONLY);
+
+ if (fd < 0)
+ have_netns_enabled = 0;
+ else
+ {
+ have_netns_enabled = 1;
+ close(fd);
+ }
+ }
+ return have_netns_enabled;
+#else
+ return 0;
+#endif
+}
+
struct ns
{
/* Identifier, same as the vector index */
@@ -194,11 +217,10 @@ ns_lookup (ns_id_t ns_id)
static int
ns_is_enabled (struct ns *ns)
{
-#ifdef HAVE_NETNS
- return ns && ns->fd >= 0;
-#else
- return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT;
-#endif
+ if (have_netns())
+ return ns && ns->fd >= 0;
+ else
+ return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT;
}
/*
@@ -214,12 +236,12 @@ ns_enable (struct ns *ns)
if (!ns_is_enabled (ns))
{
-#ifdef HAVE_NETNS
- ns->fd = open (ns->name, O_RDONLY);
-#else
- ns->fd = -2; /* Remember that ns_enable_hook has been called */
- errno = -ENOTSUP;
-#endif
+ if (have_netns()) {
+ ns->fd = open (ns->name, O_RDONLY);
+ } else {
+ ns->fd = -2; /* Remember that ns_enable_hook has been called */
+ errno = -ENOTSUP;
+ }
if (!ns_is_enabled (ns))
{
@@ -228,10 +250,9 @@ ns_enable (struct ns *ns)
return 0;
}
-#ifdef HAVE_NETNS
- zlog_info ("NS %u is associated with NETNS %s.",
- ns->ns_id, ns->name);
-#endif
+ if (have_netns())
+ zlog_info ("NS %u is associated with NETNS %s.",
+ ns->ns_id, ns->name);
zlog_info ("NS %u is enabled.", ns->ns_id);
if (ns_master.ns_enable_hook)
@@ -256,9 +277,9 @@ ns_disable (struct ns *ns)
if (ns_master.ns_disable_hook)
(*ns_master.ns_disable_hook) (ns->ns_id, &ns->info);
-#ifdef HAVE_NETNS
- close (ns->fd);
-#endif
+ if (have_netns())
+ close (ns->fd);
+
ns->fd = -1;
}
}
@@ -497,7 +518,6 @@ ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id)
NS_BITMAP_FLAG (offset)) ? 1 : 0;
}
-#ifdef HAVE_NETNS
/*
* NS realization with NETNS
*/
@@ -633,8 +653,6 @@ ns_config_write (struct vty *vty)
return write;
}
-#endif /* HAVE_NETNS */
-
/* Initialize NS module. */
void
ns_init (void)
@@ -662,12 +680,13 @@ ns_init (void)
exit (1);
}
-#ifdef HAVE_NETNS
- /* Install NS commands. */
- install_node (&ns_node, ns_config_write);
- install_element (CONFIG_NODE, &ns_netns_cmd);
- install_element (CONFIG_NODE, &no_ns_netns_cmd);
-#endif
+ if (have_netns())
+ {
+ /* Install NS commands. */
+ install_node (&ns_node, ns_config_write);
+ install_element (CONFIG_NODE, &ns_netns_cmd);
+ install_element (CONFIG_NODE, &no_ns_netns_cmd);
+ }
}
/* Terminate NS module. */
@@ -698,17 +717,18 @@ ns_socket (int domain, int type, int protocol, ns_id_t ns_id)
return -1;
}
-#ifdef HAVE_NETNS
- ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0;
- if (ret >= 0)
+ if (have_netns())
{
- ret = socket (domain, type, protocol);
- if (ns_id != NS_DEFAULT)
- setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET);
+ ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0;
+ if (ret >= 0)
+ {
+ ret = socket (domain, type, protocol);
+ if (ns_id != NS_DEFAULT)
+ setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET);
+ }
}
-#else
- ret = socket (domain, type, protocol);
-#endif
+ else
+ ret = socket (domain, type, protocol);
return ret;
}