diff options
| author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-05-01 22:14:00 -0300 |
|---|---|---|
| committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-06-05 14:36:54 -0300 |
| commit | 81b504228564980bf4dcc7ad4808e2833012c35e (patch) | |
| tree | 3202d8c4803bba8d2fe5fed4ca4ac1f00370d1b2 /lib/filter_nb.c | |
| parent | 88b8bfdc8af8e9ea45d8b7149efd9fcc8fc2e95f (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/filter_nb.c')
| -rw-r--r-- | lib/filter_nb.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 54811ac245..9df37d7ccc 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -98,6 +98,19 @@ prefix_list_length_validate(const struct lyd_node *dnode) return NB_ERR_VALIDATION; } +/** + * Sets prefix list entry to blank value. + * + * \param[out] ple prefix list entry to modify. + */ +static void prefix_list_entry_set_empty(struct prefix_list_entry *ple) +{ + ple->any = false; + memset(&ple->prefix, 0, sizeof(ple->prefix)); + ple->ge = 0; + ple->le = 0; +} + /* * XPath: /frr-filter:lib/access-list-legacy */ @@ -836,8 +849,8 @@ static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) pl = nb_running_get_entry(args->dnode, NULL, true); ple = prefix_list_entry_new(); ple->pl = pl; - ple->any = 1; ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); + prefix_list_entry_set_empty(ple); nb_running_set_entry(args->dnode, ple); return NB_OK; @@ -852,7 +865,7 @@ static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args) ple = nb_running_unset_entry(args->dnode); if (ple->installed) - prefix_list_entry_delete(ple->pl, ple, 0); + prefix_list_entry_delete2(ple); else prefix_list_entry_free(ple); @@ -904,7 +917,6 @@ lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) prefix_list_entry_update_start(ple); yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL); - ple->any = 0; /* Finish prefix entry update procedure. */ prefix_list_entry_update_finish(ple); @@ -926,7 +938,6 @@ lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) prefix_list_entry_update_start(ple); memset(&ple->prefix, 0, sizeof(ple->prefix)); - ple->any = 1; /* Finish prefix entry update procedure. */ prefix_list_entry_update_finish(ple); @@ -1087,6 +1098,7 @@ static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy( static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) { struct prefix_list_entry *ple; + int type; if (args->event != NB_EV_APPLY) return NB_OK; @@ -1096,8 +1108,24 @@ static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) /* Start prefix entry update procedure. */ prefix_list_entry_update_start(ple); + ple->any = true; + + /* Fill prefix struct from scratch. */ memset(&ple->prefix, 0, sizeof(ple->prefix)); - ple->any = 1; + + type = yang_dnode_get_enum(args->dnode, "../../type"); + switch (type) { + case 0: /* ipv4 */ + ple->prefix.family = AF_INET; + ple->ge = 0; + ple->le = IPV4_MAX_BITLEN; + break; + case 1: /* ipv6 */ + ple->prefix.family = AF_INET6; + ple->ge = 0; + ple->le = IPV6_MAX_BITLEN; + break; + } /* Finish prefix entry update procedure. */ prefix_list_entry_update_finish(ple); @@ -1117,8 +1145,7 @@ static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args) /* Start prefix entry update procedure. */ prefix_list_entry_update_start(ple); - memset(&ple->prefix, 0, sizeof(ple->prefix)); - ple->any = 1; + prefix_list_entry_set_empty(ple); /* Finish prefix entry update procedure. */ prefix_list_entry_update_finish(ple); |
