]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospfd.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / ospfd / ospfd.c
index 2298c2261a9af283c587dd5e29da86598cdb24e0..a18e2de72511b7d14429489e376ba4f8fd98be84 100644 (file)
@@ -38,6 +38,7 @@
 #include "bfd.h"
 #include "libfrr.h"
 #include "defaults.h"
+#include "lib_errors.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_network.h"
 #include "ospfd/ospf_spf.h"
 #include "ospfd/ospf_packet.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_abr.h"
 #include "ospfd/ospf_flood.h"
-#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_ase.h"
 
 
@@ -170,7 +171,7 @@ void ospf_router_id_update(struct ospf *ospf)
 
                /* Flush (inline) all external LSAs which now match the new
                   router-id,
-                  need to adjust the OSPF_LSA_SELF flag, so the flush doesnt
+                  need to adjust the OSPF_LSA_SELF flag, so the flush doesn't
                   hit
                   asserts in ospf_refresher_unregister_lsa(). This step is
                   needed
@@ -233,12 +234,10 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
        new->instance = instance;
        new->router_id.s_addr = htonl(0);
        new->router_id_static.s_addr = htonl(0);
-
-       if (name) {
+       if (name && !strmatch(name, VRF_DEFAULT_NAME)) {
                new->vrf_id = VRF_UNKNOWN;
                /* Freed in ospf_finish_final */
                new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
-               vrf = vrf_lookup_by_name(new->name);
                if (IS_DEBUG_OSPF_EVENT)
                        zlog_debug(
                                "%s: Create new ospf instance with vrf_name %s vrf_id %u",
@@ -309,12 +308,8 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
                         new->lsa_refresh_interval, &new->t_lsa_refresher);
        new->lsa_refresher_started = monotime(NULL);
 
-       if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1)) == NULL) {
-               zlog_err(
-                       "ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
-                       OSPF_MAX_PACKET_SIZE + 1);
-               exit(1);
-       }
+       new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1);
+
        new->t_read = NULL;
        new->oi_write_q = list_new();
        new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT;
@@ -329,7 +324,8 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
        new->fd = -1;
        if ((ospf_sock_init(new)) < 0) {
                if (new->vrf_id != VRF_UNKNOWN)
-                       zlog_warn(
+                       flog_err(
+                               EC_LIB_SOCKET,
                                "%s: ospf_sock_init is unable to open a socket",
                                __func__);
                return new;
@@ -380,6 +376,9 @@ struct ospf *ospf_lookup_by_inst_name(unsigned short instance, const char *name)
        struct ospf *ospf = NULL;
        struct listnode *node, *nnode;
 
+       if (name == NULL || strmatch(name, VRF_DEFAULT_NAME))
+               return ospf_lookup_by_vrf_id(VRF_DEFAULT);
+
        for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) {
                if ((ospf->instance == instance)
                    && ((ospf->name == NULL && name == NULL)
@@ -636,7 +635,7 @@ static void ospf_finish_final(struct ospf *ospf)
        for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
                ospf_vl_delete(ospf, vl_data);
 
-       list_delete_and_null(&ospf->vlinks);
+       list_delete(&ospf->vlinks);
 
        /* Remove any ospf interface config params */
        FOR_ALL_INTERFACES (vrf, ifp) {
@@ -650,7 +649,7 @@ static void ospf_finish_final(struct ospf *ospf)
        /* Reset interface. */
        for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
                ospf_if_free(oi);
-       list_delete_and_null(&ospf->oiflist);
+       list_delete(&ospf->oiflist);
 
        /* De-Register VRF */
        ospf_zebra_vrf_deregister(ospf);
@@ -720,8 +719,6 @@ static void ospf_finish_final(struct ospf *ospf)
        ospf_lsdb_free(ospf->lsdb);
 
        for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) {
-               struct ospf_lsa *lsa;
-
                if ((lsa = rn->info) != NULL) {
                        ospf_lsa_unlock(&lsa);
                        rn->info = NULL;
@@ -752,12 +749,11 @@ static void ospf_finish_final(struct ospf *ospf)
                ospf_ase_external_lsas_finish(ospf->external_lsas);
        }
 
-       list_delete_and_null(&ospf->areas);
-       list_delete_and_null(&ospf->oi_write_q);
+       list_delete(&ospf->areas);
+       list_delete(&ospf->oi_write_q);
 
        for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
                struct list *ext_list;
-               struct listnode *node;
                struct ospf_external *ext;
 
                ext_list = ospf->external[i];
@@ -870,7 +866,7 @@ static void ospf_area_free(struct ospf_area *area)
        ospf_lsa_unlock(&area->router_lsa_self);
 
        route_table_finish(area->ranges);
-       list_delete_and_null(&area->oiflist);
+       list_delete(&area->oiflist);
 
        if (EXPORT_NAME(area))
                free(EXPORT_NAME(area));
@@ -894,6 +890,7 @@ void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
 
        area = ospf_area_lookup_by_area_id(ospf, area_id);
        if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
+           && !ospf_vl_count(ospf, area)
            && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
            && area->external_routing == OSPF_AREA_DEFAULT
            && area->no_summary == 0 && area->default_cost == 1
@@ -1152,6 +1149,32 @@ void ospf_interface_area_unset(struct ospf *ospf, struct interface *ifp)
        update_redistributed(ospf, 0); /* interfaces possibly removed */
 }
 
+bool ospf_interface_area_is_already_set(struct ospf *ospf,
+                                       struct interface *ifp)
+{
+       struct route_node *rn_oi;
+
+       if (!ospf)
+               return false; /* Ospf not ready yet */
+
+       /* Find interfaces that may need to be removed. */
+       for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi;
+            rn_oi = route_next(rn_oi)) {
+               struct ospf_interface *oi = rn_oi->info;
+
+               if (oi == NULL)
+                       continue;
+
+               if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+                       continue;
+               /* at least one route covered by interface
+                * that implies already done
+                */
+               return true;
+       }
+       return false;
+}
+
 /* Check whether interface matches given network
  * returns: 1, true. 0, false
  */
@@ -1301,7 +1324,7 @@ void ospf_ls_upd_queue_empty(struct ospf_interface *oi)
                if ((lst = (struct list *)rn->info)) {
                        for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa))
                                ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */
-                       list_delete_and_null(&lst);
+                       list_delete(&lst);
                        rn->info = NULL;
                }
 
@@ -2077,6 +2100,10 @@ static int ospf_vrf_enable(struct vrf *vrf)
 
        ospf = ospf_lookup_by_name(vrf->name);
        if (ospf) {
+               if (ospf->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
+                       XFREE(MTYPE_OSPF_TOP, ospf->name);
+                       ospf->name = NULL;
+               }
                old_vrf_id = ospf->vrf_id;
                /* We have instance configured, link to VRF and make it "up". */
                ospf_vrf_link(ospf, vrf);
@@ -2087,25 +2114,17 @@ static int ospf_vrf_enable(struct vrf *vrf)
                                old_vrf_id);
 
                if (old_vrf_id != ospf->vrf_id) {
-                       if (ospfd_privs.change(ZPRIVS_RAISE)) {
-                               zlog_err(
-                                       "ospf_sock_init: could not raise privs, %s",
-                                       safe_strerror(errno));
-                       }
-
-                       /* stop zebra redist to us for old vrf */
-                       zclient_send_dereg_requests(zclient, old_vrf_id);
+                       frr_elevate_privs(&ospfd_privs) {
+                               /* stop zebra redist to us for old vrf */
+                               zclient_send_dereg_requests(zclient,
+                                                           old_vrf_id);
 
-                       ospf_set_redist_vrf_bitmaps(ospf);
+                               ospf_set_redist_vrf_bitmaps(ospf);
 
-                       /* start zebra redist to us for new vrf */
-                       ospf_zebra_vrf_register(ospf);
+                               /* start zebra redist to us for new vrf */
+                               ospf_zebra_vrf_register(ospf);
 
-                       ret = ospf_sock_init(ospf);
-                       if (ospfd_privs.change(ZPRIVS_LOWER)) {
-                               zlog_err(
-                                       "ospf_sock_init: could not lower privs, %s",
-                                       safe_strerror(errno));
+                               ret = ospf_sock_init(ospf);
                        }
                        if (ret < 0 || ospf->fd <= 0)
                                return 0;
@@ -2156,7 +2175,7 @@ static int ospf_vrf_disable(struct vrf *vrf)
 void ospf_vrf_init(void)
 {
        vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
-                ospf_vrf_delete);
+                ospf_vrf_delete, NULL);
 }
 
 void ospf_vrf_terminate(void)