diff --git a/lib/ns.c b/lib/ns.c index 9aa3509923..17d70a12fe 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -51,6 +51,7 @@ RB_GENERATE(ns_head, ns, entry, ns_compare) struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +static struct ns *default_ns; static int ns_current_ns_fd; static int ns_default_ns_fd; @@ -71,16 +72,12 @@ 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 */ - -#define NS_DEFAULT_NAME "Default-logical-router" - #endif /* HAVE_NETNS */ +/* default NS ID value used when VRF backend is not NETNS */ +#define NS_DEFAULT_INTERNAL 0 + static int have_netns(void) { #ifdef HAVE_NETNS @@ -625,24 +622,28 @@ void ns_init(void) } #endif /* HAVE_NETNS */ ns_default_ns_fd = -1; + default_ns = NULL; } /* Initialize NS module. */ -void ns_init_zebra(void) +void ns_init_zebra(ns_id_t default_ns_id) { - struct ns *default_ns; + int fd; ns_init(); - /* The default NS always exists. */ - default_ns = ns_get(NS_DEFAULT); - ns_current_ns_fd = -1; + default_ns = ns_get(default_ns_id); if (!default_ns) { zlog_err("ns_init: failed to create the default NS!"); exit(1); } - + if (have_netns()) { + fd = open(NS_DEFAULT_NAME, O_RDONLY); + default_ns->fd = fd; + } + ns_current_ns_fd = -1; /* Set the default NS name. */ default_ns->name = XSTRDUP(MTYPE_NS_NAME, NS_DEFAULT_NAME); + zlog_info("ns_init: default NSID is %u", default_ns->ns_id); /* Enable the default NS. */ if (!ns_enable(default_ns)) { @@ -739,3 +740,11 @@ int ns_socket(int domain, int type, int protocol, ns_id_t ns_id) return ret; } + +ns_id_t ns_get_default_id(void) +{ + if (default_ns) + return default_ns->ns_id; + return NS_UNKNOWN; +} + diff --git a/lib/ns.h b/lib/ns.h index 73482d4d56..44257ab0c0 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -30,12 +30,17 @@ typedef u_int32_t ns_id_t; /* the default NS ID */ -#define NS_DEFAULT 0 #define NS_UNKNOWN UINT32_MAX /* Default netns directory (Linux) */ #define NS_RUN_DIR "/var/run/netns" +#ifdef HAVE_NETNS +#define NS_DEFAULT_NAME "/proc/self/ns/net" +#else /* !HAVE_NETNS */ +#define NS_DEFAULT_NAME "Default-logical-router" +#endif /* HAVE_NETNS */ + struct ns { RB_ENTRY(ns) entry; @@ -85,7 +90,7 @@ extern void ns_add_hook(int type, int (*)(struct ns *)); * NS initializer/destructor */ extern void ns_init(void); -extern void ns_init_zebra(void); +extern void ns_init_zebra(ns_id_t ns_id); extern void ns_terminate(void); /* @@ -101,10 +106,15 @@ extern char *ns_netns_pathname(struct vty *vty, const char *name); extern void *ns_info_lookup(ns_id_t ns_id); extern void ns_walk_func(int (*func)(struct ns *)); extern const char *ns_get_name(struct ns *ns); +extern ns_id_t ns_get_default_id(void); /* API that can be used by all daemons */ extern int ns_switchback_to_initial(void); extern int ns_switch_to_netns(const char *netns_name); extern void ns_init(void); + +/* The default NS ID */ +#define NS_DEFAULT ns_get_default_id() + #endif /*_ZEBRA_NS_H*/ diff --git a/lib/vrf.c b/lib/vrf.c index 7871052352..f4dc237eb3 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -34,6 +34,9 @@ #include "command.h" #include "ns.h" +/* default VRF ID value used when VRF backend is not NETNS */ +#define VRF_DEFAULT_INTERNAL 0 + DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map") @@ -646,3 +649,15 @@ void vrf_cmd_init(int (*writefunc)(struct vty *vty)) install_default(VRF_NODE); ns_cmd_init(); } + +vrf_id_t vrf_get_default_id(void) +{ + struct vrf *vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME); + + if (vrf) + return vrf->vrf_id; + if (vrf_is_backend_netns()) + return ns_get_default_id(); + else + return VRF_DEFAULT_INTERNAL; +} diff --git a/lib/vrf.h b/lib/vrf.h index 4bdc183b5c..9553d43808 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -27,11 +27,7 @@ #include "qobj.h" #include "vty.h" -/* The default NS ID */ -#define NS_DEFAULT 0 - /* The default VRF ID */ -#define VRF_DEFAULT 0 #define VRF_UNKNOWN UINT32_MAX /* Pending: May need to refine this. */ @@ -208,6 +204,7 @@ extern void vrf_cmd_init(int (*writefunc)(struct vty *vty)); /* * VRF utilities */ +extern vrf_id_t vrf_get_default_id(void); /* Create a socket serving for the given VRF */ extern int vrf_socket(int, int, int, vrf_id_t); @@ -236,4 +233,9 @@ extern int vrf_enable(struct vrf *vrf); * VRF Debugging */ extern void vrf_install_commands(void); + + +/* The default VRF ID */ +#define VRF_DEFAULT vrf_get_default_id() + #endif /*_ZEBRA_VRF_H*/ diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index c5e792bd77..966d6ed0d2 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -20,6 +20,7 @@ #include #include "ns.h" +#include "vrf.h" #include "log.h" #if defined(HAVE_NETLINK) @@ -35,6 +36,9 @@ #include "zebra_netns_id.h" +/* default NS ID value used when VRF backend is not NETNS */ +#define NS_DEFAULT_INTERNAL 0 + /* in case NEWNSID not available, the NSID will be locally obtained */ #define NS_BASE_NSID 0 @@ -312,3 +316,40 @@ ns_id_t zebra_ns_id_get(const char *netnspath) return zebra_ns_id_get_fallback(netnspath); } #endif /* ! defined(HAVE_NETLINK) */ + +#ifdef HAVE_NETNS +static void zebra_ns_create_netns_directory(void) +{ + /* check that /var/run/netns is created */ + /* S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH */ + if (mkdir(NS_RUN_DIR, 0755)) { + if (errno != EEXIST) { + zlog_warn("NS check: failed to access %s", NS_RUN_DIR); + return; + } + } +} +#endif + +ns_id_t zebra_ns_id_get_default(void) +{ +#ifdef HAVE_NETNS + int fd; +#endif /* !HAVE_NETNS */ + +#ifdef HAVE_NETNS + if (vrf_is_backend_netns()) + zebra_ns_create_netns_directory(); + fd = open(NS_DEFAULT_NAME, O_RDONLY); + + if (fd == -1) + return NS_DEFAULT_INTERNAL; + if (!vrf_is_backend_netns()) + return NS_DEFAULT_INTERNAL; + close(fd); + return zebra_ns_id_get((char *)NS_DEFAULT_NAME); +#else /* HAVE_NETNS */ + return NS_DEFAULT_INTERNAL; +#endif /* !HAVE_NETNS */ +} + diff --git a/zebra/zebra_netns_id.h b/zebra/zebra_netns_id.h index 18fdf50cf1..d6530e6694 100644 --- a/zebra/zebra_netns_id.h +++ b/zebra/zebra_netns_id.h @@ -21,5 +21,6 @@ #include "ns.h" extern ns_id_t zebra_ns_id_get(const char *netnspath); +extern ns_id_t zebra_ns_id_get_default(void); #endif /* __ZEBRA_NS_ID_H__ */ diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 50551c9b35..da5b22def2 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -34,6 +34,9 @@ #include "zebra_vxlan.h" #include "debug.h" #include "zebra_netns_notify.h" +#include "zebra_netns_id.h" + +extern struct zebra_privs_t zserv_privs; DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") @@ -229,9 +232,16 @@ int zebra_ns_disable(ns_id_t ns_id, void **info) int zebra_ns_init(void) { + ns_id_t ns_id; + dzns = zebra_ns_alloc(); - ns_init_zebra(); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + ns_id = zebra_ns_id_get_default(); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + ns_init_zebra(ns_id); ns_init();