]> git.puffer.fish Git - matthieu/frr.git/commitdiff
vrf: add a runtime check before playing with netns
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Thu, 3 Sep 2015 08:47:43 +0000 (10:47 +0200)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 9 Sep 2016 16:15:14 +0000 (12:15 -0400)
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)

lib/ns.c
vtysh/vtysh_config.c

index 6fb124181b023c0e9bd4466721a34e28cdd03e9b..4765a18ef2313c8f4d7dbd2f7c590ee4b2c0057c 100644 (file)
--- 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;
 }
index 4a1b32368607755906e9e0add465e23d1de8c0e9..118b7ba0357556afc5c3f1b4b2565585dcd6f30b 100644 (file)
@@ -184,7 +184,7 @@ vtysh_config_parse_line (const char *line)
     default:
       if (strncmp (line, "interface", strlen ("interface")) == 0)
        config = config_get (INTERFACE_NODE, line);
-      else if (strncmp (line, "ns", strlen ("ns")) == 0)
+      else if (strncmp (line, "logical-router", strlen ("ns")) == 0)
        config = config_get (NS_NODE, line);
       else if (strncmp (line, "vrf", strlen ("vrf")) == 0)
        config = config_get (VRF_NODE, line);