summaryrefslogtreecommitdiff
path: root/lib/plist.c
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2020-05-01 22:14:00 -0300
committerRafael Zalamena <rzalamena@opensourcerouting.org>2020-06-05 14:36:54 -0300
commit81b504228564980bf4dcc7ad4808e2833012c35e (patch)
tree3202d8c4803bba8d2fe5fed4ca4ac1f00370d1b2 /lib/plist.c
parent88b8bfdc8af8e9ea45d8b7149efd9fcc8fc2e95f (diff)
lib: fix route map crash on prefix list removal
Changes: - Refactor list entry deletion to use a function that properly notifies route map on deletion (fixes a heap-use-after-free). - Prefix list entry wild card sets `le` to maximum IP mask value and `any` is a boolean. - Fix prefix list trie removal order (in `prefix_list_entry_update_start`). - Let only the `any` callback change the value of field `any`. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'lib/plist.c')
-rw-r--r--lib/plist.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/lib/plist.c b/lib/plist.c
index 958d98dc96..981e86e2ac 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -661,6 +661,8 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple)
if (!ple->installed)
return;
+ prefix_list_trie_del(pl, ple);
+
/* List manipulation: shameless copy from `prefix_list_entry_delete`. */
if (ple->prev)
ple->prev->next = ple->next;
@@ -671,11 +673,17 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple)
else
pl->tail = ple->prev;
- prefix_list_trie_del(pl, ple);
route_map_notify_pentry_dependencies(pl->name, ple,
RMAP_EVENT_PLIST_DELETED);
pl->count--;
+ route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_DELETED);
+ if (pl->master->delete_hook)
+ (*pl->master->delete_hook)(pl);
+
+ if (pl->head || pl->tail || pl->desc)
+ pl->master->recent = pl;
+
ple->installed = false;
}
@@ -695,6 +703,14 @@ void prefix_list_entry_update_finish(struct prefix_list_entry *ple)
if (ple->installed)
return;
+ /*
+ * Check if the entry is installable:
+ * We can only install entry if at least the prefix is provided (IPv4
+ * or IPv6).
+ */
+ if (ple->prefix.family != AF_INET && ple->prefix.family != AF_INET6)
+ return;
+
/* List manipulation: shameless copy from `prefix_list_entry_add`. */
if (pl->tail && ple->seq > pl->tail->seq)
point = NULL;
@@ -742,6 +758,21 @@ void prefix_list_entry_update_finish(struct prefix_list_entry *ple)
ple->installed = true;
}
+/**
+ * Same as `prefix_list_entry_delete` but without `free()`ing the list if its
+ * empty.
+ *
+ * \param[in] ple prefix list entry.
+ */
+void prefix_list_entry_delete2(struct prefix_list_entry *ple)
+{
+ /* Does the boiler plate list removal and entry removal notification. */
+ prefix_list_entry_update_start(ple);
+
+ /* Effective `free()` memory. */
+ prefix_list_entry_free(ple);
+}
+
/* Return string of prefix_list_type. */
static const char *prefix_list_type_str(struct prefix_list_entry *pentry)
{