]> git.proxmox.com Git - mirror_frr.git/commitdiff
ospfd: Fix ospfd crash
authorOlivier Dugeon <olivier.dugeon@orange.com>
Fri, 9 Feb 2018 11:13:07 +0000 (12:13 +0100)
committerOlivier Dugeon <olivier.dugeon@orange.com>
Wed, 21 Feb 2018 17:44:20 +0000 (18:44 +0100)
 - ospfd/ospf_opaque.c: Update issue #1652 by introducing a new
function 'free_opaque_info_owner()' to clean list of callback owner
and call this function in appropriate place where 'listdelete_and_null'
is not used.

 - ospfd/ospf_packet.c: In case of crash, ospfd is not been able to
flush LSA. In case of self Opaque LSA, when restarting, ospfd crash
during the resynchronisation process with its neighbor due to an
empty list of LSA to flood. Just add a control on the list count
in 'ospf_ls_upd_queue_send()' to escape the function and avoid the
problem.

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
ospfd/ospf_opaque.c
ospfd/ospf_packet.c

index 1c586d252cb752ff95880f97c28e1cc5df1a9a0e..009fd997eab9a34beea663b7fb7a879474d92f87 100644 (file)
@@ -75,6 +75,7 @@ static void ospf_opaque_funclist_init(void);
 static void ospf_opaque_funclist_term(void);
 static void free_opaque_info_per_type(void *val);
 static void free_opaque_info_per_id(void *val);
+static void free_opaque_info_owner(void *val);
 static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa);
 static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa);
 
@@ -439,9 +440,11 @@ void ospf_delete_opaque_functab(u_char lsa_type, u_char opaque_type)
                        if (functab->opaque_type == opaque_type) {
                                /* Cleanup internal control information, if it
                                 * still remains. */
-                               if (functab->oipt != NULL)
+                               if (functab->oipt != NULL) {
                                        free_opaque_info_per_type(
                                                functab->oipt);
+                                       free_opaque_info_owner(functab->oipt);
+                               }
 
                                /* Dequeue listnode entry from the list. */
                                listnode_delete(funclist, functab);
@@ -572,6 +575,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
                top = ospf_lookup_by_vrf_id(new->vrf_id);
                if (new->area != NULL && (top = new->area->ospf) == NULL) {
                        free_opaque_info_per_type((void *)oipt);
+                       free_opaque_info_owner(oipt);
                        oipt = NULL;
                        goto out; /* This case may not exist. */
                }
@@ -583,6 +587,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
                        "register_opaque_info_per_type: Unexpected LSA-type(%u)",
                        new->data->type);
                free_opaque_info_per_type((void *)oipt);
+               free_opaque_info_owner(oipt);
                oipt = NULL;
                goto out; /* This case may not exist. */
        }
@@ -600,6 +605,35 @@ out:
        return oipt;
 }
 
+/* Remove "oipt" from its owner's self-originated LSA list. */
+static void free_opaque_info_owner(void *val)
+{
+       struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;
+
+        switch (oipt->lsa_type) {
+        case OSPF_OPAQUE_LINK_LSA: {
+                struct ospf_interface *oi =
+                        (struct ospf_interface *)(oipt->owner);
+                listnode_delete(oi->opaque_lsa_self, oipt);
+                break;
+        }
+        case OSPF_OPAQUE_AREA_LSA: {
+                struct ospf_area *area = (struct ospf_area *)(oipt->owner);
+                listnode_delete(area->opaque_lsa_self, oipt);
+                break;
+        }
+        case OSPF_OPAQUE_AS_LSA: {
+                struct ospf *top = (struct ospf *)(oipt->owner);
+                listnode_delete(top->opaque_lsa_self, oipt);
+                break;
+        }
+        default:
+                zlog_warn("free_opaque_info_owner: Unexpected LSA-type(%u)",
+                          oipt->lsa_type);
+                break; /* This case may not exist. */
+        }
+}
+
 static void free_opaque_info_per_type(void *val)
 {
        struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val;
index 86703596102111d31a6a6c58ed874db8f5a22069..881226683c572f1a183f6273cd301be8e9fa89c9 100644 (file)
@@ -3897,6 +3897,10 @@ static void ospf_ls_upd_queue_send(struct ospf_interface *oi,
                zlog_debug("listcount = %d, [%s]dst %s", listcount(update),
                           IF_NAME(oi), inet_ntoa(addr));
 
+       /* Check that we have really something to process */
+       if (listcount(update) == 0)
+               return;
+
        op = ospf_ls_upd_packet_new(update, oi);
 
        /* Prepare OSPF common header. */