From 4691b65ae4c3e50c295dce4fc007738080826b49 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 22 Dec 2017 16:02:51 +0100 Subject: [PATCH] lib: add namespace name structure in zebra message The addition of the name of the netns in the vrf message introduces also a limitation when the size of the netns is bigger than 15 bytes. Then the netns are ignored by the library. In addition to this, some sanity checks have been introduced. some functions to create the netns from a call not coming from the vty is being added with traces. Also, the ns vty function is reentrant, if the context is already created. Signed-off-by: Philippe Guibert Signed-off-by: Renato Westphal --- lib/ns.c | 25 +++++++++++++++++++++++++ lib/vrf.c | 6 +++--- lib/vrf.h | 2 ++ lib/zclient.c | 4 ++-- zebra/zebra_vrf.c | 2 +- zebra/zserv.c | 12 ++++++++++-- 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/lib/ns.c b/lib/ns.c index 5af896632c..e2c042d16c 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -28,6 +28,9 @@ #include #endif +/* for basename */ +#include + #include "if.h" #include "ns.h" #include "log.h" @@ -353,6 +356,7 @@ char *ns_netns_pathname(struct vty *vty, const char *name) { static char pathname[PATH_MAX]; char *result; + char *check_base; if (name[0] == '/') /* absolute pathname */ result = realpath(name, pathname); @@ -367,6 +371,21 @@ char *ns_netns_pathname(struct vty *vty, const char *name) if (vty) vty_out(vty, "Invalid pathname: %s\n", safe_strerror(errno)); + else + zlog_warn("Invalid pathname: %s", + safe_strerror(errno)); + return NULL; + } + check_base = basename(pathname); + if (check_base != NULL && strlen(check_base) + 1 > NS_NAMSIZ) { + if (vty) + vty_out(vty, "NS name (%s) invalid:" + " too long( %d needed)\n", + check_base, NS_NAMSIZ-1); + else + zlog_warn("NS name (%s) invalid:" + " too long ( %d needed)", + check_base, NS_NAMSIZ-1); return NULL; } return pathname; @@ -489,6 +508,8 @@ int ns_handler_create(struct vty *vty, struct vrf *vrf, if (ns && ns->vrf_ctxt) { struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt; + if (vrf2 == vrf) + return CMD_SUCCESS; if (vty) vty_out(vty, "NS %s is already configured" " with VRF %u(%s)\n", @@ -507,6 +528,10 @@ int ns_handler_create(struct vty *vty, struct vrf *vrf, } ns->vrf_ctxt = (void *)vrf; vrf->ns_ctxt = (void *)ns; + /* update VRF netns NAME */ + if (vrf) + strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ); + if (!ns_enable(ns)) { if (vty) vty_out(vty, "Can not associate NS %u with NETNS %s\n", diff --git a/lib/vrf.c b/lib/vrf.c index e855f3f83b..5b85effabd 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -21,6 +21,9 @@ #include +/* for basename */ +#include + #include "if.h" #include "vrf.h" #include "vrf_int.h" @@ -131,8 +134,6 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) if (vrf == NULL) { vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf)); vrf->vrf_id = VRF_UNKNOWN; - RB_INIT(if_name_head, &vrf->ifaces_by_name); - RB_INIT(if_index_head, &vrf->ifaces_by_index); QOBJ_REG(vrf, vrf); new = 1; @@ -156,7 +157,6 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) strlcpy(vrf->name, name, sizeof(vrf->name)); RB_INSERT(vrf_name_head, &vrfs_by_name, vrf); } - if (new &&vrf_master.vrf_new_hook) (*vrf_master.vrf_new_hook)(vrf); diff --git a/lib/vrf.h b/lib/vrf.h index 16d75c3efb..c1da4e8bbc 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -42,6 +42,7 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #endif #define VRF_NAMSIZ 36 +#define NS_NAMSIZ 16 #define VRF_DEFAULT_NAME "Default-IP-Routing-Table" @@ -60,6 +61,7 @@ struct vrf_data { union { struct { uint32_t table_id; + char netns_name[NS_NAMSIZ]; } l; }; }; diff --git a/lib/zclient.c b/lib/zclient.c index 714888a3f3..9260e0b3ba 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1402,8 +1402,8 @@ static void zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id) /* Lookup/create vrf by vrf_id. */ vrf = vrf_get(vrf_id, vrfname_tmp); - vrf->data = data; - + vrf->data.l.table_id = data.l.table_id; + memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ); vrf_enable(vrf); } diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 276687ca83..874a9c74e7 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -77,7 +77,7 @@ void zebra_vrf_update_all(struct zserv *client) struct vrf *vrf; RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if (vrf->vrf_id) + if (vrf->vrf_id != VRF_UNKNOWN) zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id)); } } diff --git a/zebra/zserv.c b/zebra/zserv.c index b3b1fa79e9..f269422986 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -20,6 +20,8 @@ #include #include +/* for basename */ +#include #include "prefix.h" #include "command.h" @@ -182,13 +184,19 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp) static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) { struct vrf_data data; + const char *netns_name = zvrf_ns_name(zvrf); data.l.table_id = zvrf->table_id; - /* Pass the tableid */ + + if (netns_name) + strlcpy(data.l.netns_name, + basename((char *)netns_name), NS_NAMSIZ); + else + memset(data.l.netns_name, 0, NS_NAMSIZ); + /* Pass the tableid and the netns NAME */ stream_put(s, &data, sizeof(struct vrf_data)); /* Interface information. */ stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ); - /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); } -- 2.39.5