From 632f36100c2d36e17446f384e430e8eecfa03d6e Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 3 Mar 2021 23:10:19 +0300 Subject: [PATCH] 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 --- bfdd/bfdd_nb_config.c | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index b8065c6052..c8dd5cc3f6 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: