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>
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);
static int lib_interface_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
-
+ struct vrf *vrf;
switch (args->event) {
case NB_EV_VALIDATE:
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;
}
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. */
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--;
}