From: Olivier Dugeon Date: Fri, 9 Feb 2018 11:13:07 +0000 (+0100) Subject: ospfd: Fix ospfd crash X-Git-Tag: frr-4.0~8^2~2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=eb2c2672f7f741144a58e6b8d2d7a8a9f50eabe7;p=matthieu%2Ffrr.git ospfd: Fix ospfd crash - 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 --- diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 1c586d252c..009fd997ea 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -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; diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 8670359610..881226683c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -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. */