[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200307205916.15646-1-sharpd@cumulusnetworks.com>
Date: Sat, 7 Mar 2020 15:59:16 -0500
From: Donald Sharp <sharpd@...ulusnetworks.com>
To: netdev@...r.kernel.org, dsahern@...nel.org,
roopa@...ulusnetworks.com, sworley@...ulusnetworks.com
Subject: [PATCH] ip link: Prevent duplication of table id for vrf tables
Creation of different vrf's with duplicate table id's creates
a situation where two different routing entities believe
they have exclusive access to a particular table. This
leads to situations where different routing processes
clash for control of a route due to inadvertent table
id overlap. Prevent end user from making this mistake
on accident.
sharpd@eva ~/i/ip (master)> ip vrf show
Name Table
-----------------------
BLUE 1300
GREEN 1301
sharpd@eva ~/i/ip (master)> sudo ./ip link add ORANGE type vrf table 1300
Error: argument "1300" is wrong: table specified is already being used
sharpd@eva ~/i/ip (master) [255]> sudo ./ip link add ORANGE type vrf table 1302
sharpd@eva ~/i/ip (master)> ip vrf show
Name Table
-----------------------
BLUE 1300
GREEN 1301
ORANGE 1302
Signed-off-by: Donald Sharp <sharpd@...ulusnetworks.com>
---
ip/ip_common.h | 2 ++
ip/iplink_vrf.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
ip/ipvrf.c | 4 ++--
3 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 879287e3..4cc825e9 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -148,6 +148,8 @@ void xdp_dump(FILE *fp, struct rtattr *tb, bool link, bool details);
/* iplink_vrf.c */
__u32 ipvrf_get_table(const char *name);
+__u32 vrf_table_linkinfo(struct rtattr *li[]);
+int ipvrf_filter_req(struct nlmsghdr *nhl, int reqlen);
int name_is_vrf(const char *name);
#ifndef INFINITY_LIFE_TIME
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index 5d20f29d..968593f6 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -29,17 +29,64 @@ static void explain(void)
vrf_explain(stderr);
}
+static bool vrf_find_table(struct nlmsghdr *n, __u32 table)
+{
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
+ struct rtattr *tb[IFLA_MAX + 1];
+ struct rtattr *li[IFLA_INFO_MAX + 1];
+ int len = n->nlmsg_len;
+ __u32 vrf_table;
+
+ len -= NLMSG_LENGTH(sizeof(*ifi));
+ if (len < 0)
+ return false;
+
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+
+ if (!tb[IFLA_LINKINFO])
+ return false;
+
+ parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+ if (!li[IFLA_INFO_KIND])
+ return false;
+
+ vrf_table = vrf_table_linkinfo(li);
+
+ if (vrf_table == table)
+ return true;
+
+ return false;
+}
+
static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
while (argc > 0) {
if (matches(*argv, "table") == 0) {
__u32 table;
+ bool found = false;
+ struct nlmsg_chain linfo = { NULL, NULL };
NEXT_ARG();
if (rtnl_rttable_a2n(&table, *argv))
invarg("invalid table ID\n", *argv);
+
+ if (ip_link_list(ipvrf_filter_req, &linfo) == 0) {
+ struct nlmsg_list *l;
+
+ for (l = linfo.head; l; l = l->next) {
+ if (vrf_find_table(&l->h, table)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ invarg("table specified is already being used\n",
+ *argv);
+
addattr32(n, 1024, IFLA_VRF_TABLE, table);
} else if (matches(*argv, "help") == 0) {
explain();
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index b9a43675..ff0c492c 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -477,7 +477,7 @@ void vrf_reset(void)
vrf_switch("default");
}
-static int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen)
+int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen)
{
struct rtattr *linkinfo;
int err;
@@ -497,7 +497,7 @@ static int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen)
}
/* input arg is linkinfo */
-static __u32 vrf_table_linkinfo(struct rtattr *li[])
+__u32 vrf_table_linkinfo(struct rtattr *li[])
{
struct rtattr *attr[IFLA_VRF_MAX + 1];
--
2.25.1
Powered by blists - more mailing lists