summaryrefslogtreecommitdiffstats
path: root/bfdd
diff options
context:
space:
mode:
authorIgor Ryzhov <iryzhov@nfware.com>2021-03-03 21:10:19 +0100
committerIgor Ryzhov <iryzhov@nfware.com>2021-03-03 21:10:19 +0100
commit632f36100c2d36e17446f384e430e8eecfa03d6e (patch)
treeea204f0c937a58f5fa0c6024bac4a797b9bc17e2 /bfdd
parentbfdd: actually return validation error instead of logging (diff)
downloadfrr-632f36100c2d36e17446f384e430e8eecfa03d6e.tar.xz
frr-632f36100c2d36e17446f384e430e8eecfa03d6e.zip
bfdd: forbid creation of the same peer with and without interface name
Currently it is possible to configure the same peer with and without interface name: ``` bfd peer 1.1.1.1 ! peer 1.1.1.1 interface enp0s3 ! ``` There are multiple problems with that: 1. Both nodes actually control the same BFD session. So the config is either duplicated or, even worse, different - and there is no way to say which one actually works. 2. When the user deletes both nodes, the session is not actually freed, because its refcount is always greater than 1. Such configuration must be forbidden. User should either have single node with wildcard name or multiple nodes with actual names. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Diffstat (limited to 'bfdd')
-rw-r--r--bfdd/bfdd_nb_config.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index b8065c605..c8dd5cc3f 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -55,10 +55,35 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
}
+struct session_iter {
+ int count;
+ bool wildcard;
+};
+
+static int session_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct session_iter *iter = arg;
+ const char *ifname;
+
+ ifname = yang_dnode_get_string(dnode, "./interface");
+
+ if (strmatch(ifname, "*"))
+ iter->wildcard = true;
+
+ iter->count++;
+
+ return YANG_ITER_CONTINUE;
+}
+
static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
{
+ const struct lyd_node *sess_dnode;
+ struct session_iter iter;
struct bfd_session *bs;
+ const char *source;
+ const char *dest;
const char *ifname;
+ const char *vrfname;
struct bfd_key bk;
struct prefix p;
@@ -80,6 +105,33 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
"When using link-local you must specify an interface");
return NB_ERR_VALIDATION;
}
+
+ iter.count = 0;
+ iter.wildcard = false;
+
+ sess_dnode = yang_dnode_get_parent(args->dnode, "sessions");
+
+ dest = yang_dnode_get_string(args->dnode, "./dest-addr");
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+
+ if (mhop) {
+ source = yang_dnode_get_string(args->dnode, "./source-addr");
+
+ yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
+ "./multi-hop[source-addr='%s'][dest-addr='%s'][vrf='%s']",
+ source, dest, vrfname);
+ } else {
+ yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
+ "./single-hop[dest-addr='%s'][vrf='%s']",
+ dest, vrfname);
+ }
+
+ if (iter.wildcard && iter.count > 1) {
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "It is not allowed to configure the same peer with and without ifname");
+ return NB_ERR_VALIDATION;
+ }
break;
case NB_EV_PREPARE: