summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Ryzhov <iryzhov@nfware.com>2021-11-06 01:22:07 +0300
committerIgor Ryzhov <iryzhov@nfware.com>2021-11-11 14:57:59 +0300
commitce27a13e90885de3a830e4ec78afc9efeadae42e (patch)
treeb1417330f259a03ee93bea098330e71d5a8c234b
parent0ac8055ca1a9662d6e8197dff9a91759331991e7 (diff)
lib: fix vrf deletion when the last interface is deleted
Currently, we automatically delete an inactive VRF when its last interface is deleted. This code introduces a couple of crashes because of the following problems: - vrf_delete is called before calling if_del hook, so daemons may try to dereference an ifp->vrf pointer which is freed - in if_terminate, we continue to use the VRF in the loop condition after the last interface is deleted This check is needed only when the interface is deleted by the user, because if the interface is deleted by the system, VRF must still exist in the system. Move the check to appropriate places to fix crashes. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
-rw-r--r--lib/if.c9
-rw-r--r--lib/vrf.c5
-rw-r--r--ospfd/ospf_interface.c3
3 files changed, 9 insertions, 8 deletions
diff --git a/lib/if.c b/lib/if.c
index 71d2f5d9cc..a40f04f5a2 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -303,9 +303,6 @@ void if_delete(struct interface **ifp)
if (ptr->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(vrf, ptr);
- if (!vrf_is_enabled(vrf))
- vrf_delete(vrf);
-
if_delete_retain(ptr);
list_delete(&ptr->connected);
@@ -1420,7 +1417,7 @@ static int lib_interface_create(struct nb_cb_create_args *args)
static int lib_interface_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
-
+ struct vrf *vrf;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -1436,9 +1433,13 @@ static int lib_interface_destroy(struct nb_cb_destroy_args *args)
break;
case NB_EV_APPLY:
ifp = nb_running_unset_entry(args->dnode);
+ vrf = ifp->vrf;
ifp->configured = false;
if_delete(&ifp);
+
+ if (!vrf_is_enabled(vrf))
+ vrf_delete(vrf);
break;
}
diff --git a/lib/vrf.c b/lib/vrf.c
index aaedb63800..a9a5a83794 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -539,13 +539,10 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
static void vrf_terminate_single(struct vrf *vrf)
{
- int enabled = vrf_is_enabled(vrf);
-
/* Clear configured flag and invoke delete. */
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
if_terminate(vrf);
- if (enabled)
- vrf_delete(vrf);
+ vrf_delete(vrf);
}
/* Terminate VRF module. */
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 60e109ea80..ccfeddfc66 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -971,11 +971,14 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
static void ospf_vl_if_delete(struct ospf_vl_data *vl_data)
{
struct interface *ifp = vl_data->vl_oi->ifp;
+ struct vrf *vrf = ifp->vrf;
vl_data->vl_oi->address->u.prefix4.s_addr = INADDR_ANY;
vl_data->vl_oi->address->prefixlen = 0;
ospf_if_free(vl_data->vl_oi);
if_delete(&ifp);
+ if (!vrf_is_enabled(vrf))
+ vrf_delete(vrf);
vlink_count--;
}