From a4d7621fc86380e951e306bc4cb019a2ff633cd5 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 4 Oct 2019 10:16:35 -0300 Subject: [PATCH 01/31] yang: update filter yang model Important changes: * Limit the access-list name length according to header definition; * Add another list (sequence) inside instances to avoid repeated fields; Signed-off-by: Rafael Zalamena --- yang/frr-filter.yang | 358 ++++++++++++++++++++++--------------------- 1 file changed, 184 insertions(+), 174 deletions(-) diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang index c55af34161..9ae8de496b 100644 --- a/yang/frr-filter.yang +++ b/yang/frr-filter.yang @@ -73,7 +73,9 @@ module frr-filter { typedef access-list-name { description "Access list name formatting"; - type string; + type string { + length 1..128; + } } typedef access-list-sequence { @@ -100,69 +102,76 @@ module frr-filter { /* * Configuration data. */ - container filter-list { + container lib { list access-list-legacy { description "Access list legacy instance"; - key "number sequence"; + key "number"; leaf number { description "Access list sequence value"; type access-list-legacy; } - leaf sequence { - description "Access list sequence value"; - type access-list-sequence; - } - - leaf action { - description "Access list action on match"; - type access-list-action; - mandatory true; - } - leaf remark { description "Access list remark"; type string; } - choice value { - description - "Standard access list: value to match. - Extended access list: source value to match."; - mandatory true; + list entry { + description "Access list legacy entry"; - leaf host { - description "Host to match"; - type inet:ipv4-address; - } - leaf network { - description "Network to match"; - type inet:ipv4-prefix; - } - leaf any { - description "Match any"; - type empty; - } - } + key "sequence"; - choice extended-value { - when "./sequence >= 100 and ./sequence <= 199 or - ./sequence >= 2000 and ./sequence <= 2699"; - description "Destination value to match"; + leaf sequence { + description "Access list sequence value"; + type access-list-sequence; + } - leaf destination-host { - description "Host to match"; - type inet:ipv4-address; + leaf action { + description "Access list action on match"; + type access-list-action; + mandatory true; } - leaf destination-network { - description "Network to match"; - type inet:ipv4-prefix; + + choice value { + description + "Standard access list: value to match. + Extended access list: source value to match."; + mandatory true; + + leaf host { + description "Host to match"; + type inet:ipv4-address; + } + leaf network { + description "Network to match"; + type inet:ipv4-prefix; + } + leaf any { + description "Match any"; + type empty; + } } - leaf destination-any { - description "Match any"; - type empty; + + choice extended-value { + when "../number >= 100 and ../number <= 199 or + ../number >= 2000 and ../number <= 2699"; + description "Destination value to match"; + mandatory true; + + leaf destination-host { + description "Host to match"; + type inet:ipv4-address; + } + leaf destination-network { + description "Network to match"; + type inet:ipv4-prefix; + } + leaf destination-any { + description "Match any"; + type empty; + } } } } @@ -170,7 +179,7 @@ module frr-filter { list access-list { description "Access list instance"; - key "type identifier sequence"; + key "type name"; leaf type { description "Access list content type"; @@ -187,85 +196,80 @@ module frr-filter { description "Media Access Control address"; value 2; } - - /* - * Protocol YANG models should augment the parent node to - * contain the routing protocol specific value. The protocol - * must also augment `value` leaf to include its specific - * values or expand the `when` statement on the existing cases. - */ - enum custom { - description "Custom data type"; - value 100; - } } } - leaf identifier { - description "Access list identifier"; + leaf name { + description "Access list name"; type access-list-name; } - leaf sequence { - description "Access list sequence value"; - type access-list-sequence; - } - - leaf action { - description "Access list action on match"; - type access-list-action; - mandatory true; - } - leaf remark { description "Access list remark"; type string; } - choice value { - description "Access list value to match"; - mandatory true; + list entry { + description "Access list entry"; - case ipv4-prefix { - when "./type = 'ipv4'"; + key "sequence"; - leaf ipv4-prefix { - description "Configure IPv4 prefix to match"; - type inet:ipv4-prefix; - } - - leaf ipv4-exact-match { - description "Exact match of prefix"; - type boolean; - default false; - } + leaf sequence { + description "Access list sequence value"; + type access-list-sequence; } - case ipv6-prefix { - when "./type = 'ipv6'"; - leaf ipv6-prefix { - description "Configure IPv6 prefix to match"; - type inet:ipv6-prefix; - } - - leaf ipv6-exact-match { - description "Exact match of prefix"; - type boolean; - default false; - } + leaf action { + description "Access list action on match"; + type access-list-action; + mandatory true; } - case mac { - when "./type = 'mac'"; - leaf mac { - description "Configure MAC address to match"; - type yang:mac-address; + choice value { + description "Access list value to match"; + mandatory true; + + case ipv4-prefix { + when "../type = 'ipv4'"; + + leaf ipv4-prefix { + description "Configure IPv4 prefix to match"; + type inet:ipv4-prefix; + } + + leaf ipv4-exact-match { + description "Exact match of prefix"; + type boolean; + default false; + } } - } - case any { - leaf any { - description "Match anything"; - type empty; + case ipv6-prefix { + when "../type = 'ipv6'"; + + leaf ipv6-prefix { + description "Configure IPv6 prefix to match"; + type inet:ipv6-prefix; + } + + leaf ipv6-exact-match { + description "Exact match of prefix"; + type boolean; + default false; + } + } + case mac { + when "../type = 'mac'"; + + leaf mac { + description "Configure MAC address to match"; + type yang:mac-address; + } + } + case any { + leaf any { + description "Match anything"; + type empty; + } } } } @@ -274,7 +278,7 @@ module frr-filter { list prefix-list { description "Prefix list instance"; - key "type name sequence"; + key "type name"; leaf type { description "Prefix list type"; @@ -295,82 +299,88 @@ module frr-filter { type access-list-name; } - leaf sequence { - description "Access list sequence value"; - type access-list-sequence; - } - - leaf action { - description "Prefix list action on match"; - type access-list-action; - mandatory true; - } - leaf description { description "Prefix list user description"; type string; } - choice value { - description "Prefix list value to match"; - mandatory true; + list entry { + description "Prefix list entry"; - case ipv4-prefix { - when "./type = 'ipv4'"; + key "sequence"; - leaf ipv4-prefix { - description "Configure IPv4 prefix to match"; - type inet:ipv4-prefix; - } - - leaf ipv4-prefix-length-greater-or-equal { - description - "Specifies if matching prefixes with length greater than - or equal to value"; - type uint8 { - range "0..32"; - } - } - - leaf ipv4-prefix-length-lesser-or-equal { - description - "Specifies if matching prefixes with length lesser than - or equal to value"; - type uint8 { - range "0..32"; - } - } + leaf sequence { + description "Access list sequence value"; + type access-list-sequence; } - case ipv6-prefix { - when "./type = 'ipv6'"; - leaf ipv6-prefix { - description "Configure IPv6 prefix to match"; - type inet:ipv6-prefix; - } - - leaf ipv6-prefix-length-greater-or-equal { - description - "Specifies if matching prefixes with length greater than - or equal to value"; - type uint8 { - range "0..128"; - } - } - - leaf ipv6-prefix-length-lesser-or-equal { - description - "Specifies if matching prefixes with length lesser than - or equal to value"; - type uint8 { - range "0..128"; - } - } + leaf action { + description "Prefix list action on match"; + type access-list-action; + mandatory true; } - case any { - leaf any { - description "Match anything"; - type empty; + + choice value { + description "Prefix list value to match"; + mandatory true; + + case ipv4-prefix { + when "../type = 'ipv4'"; + + leaf ipv4-prefix { + description "Configure IPv4 prefix to match"; + type inet:ipv4-prefix; + } + + leaf ipv4-prefix-length-greater-or-equal { + description + "Specifies if matching prefixes with length greater than + or equal to value"; + type uint8 { + range "0..32"; + } + } + + leaf ipv4-prefix-length-lesser-or-equal { + description + "Specifies if matching prefixes with length lesser than + or equal to value"; + type uint8 { + range "0..32"; + } + } + } + case ipv6-prefix { + when "../type = 'ipv6'"; + + leaf ipv6-prefix { + description "Configure IPv6 prefix to match"; + type inet:ipv6-prefix; + } + + leaf ipv6-prefix-length-greater-or-equal { + description + "Specifies if matching prefixes with length greater than + or equal to value"; + type uint8 { + range "0..128"; + } + } + + leaf ipv6-prefix-length-lesser-or-equal { + description + "Specifies if matching prefixes with length lesser than + or equal to value"; + type uint8 { + range "0..128"; + } + } + } + case any { + leaf any { + description "Match anything"; + type empty; + } } } } From 4cf24501620bf7759f087653586a7414b2950cd3 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 8 Nov 2019 14:46:17 -0300 Subject: [PATCH 02/31] lib: export access-lists shared functions These functions are going to be used by the new filter northbound implementation. Signed-off-by: Rafael Zalamena --- lib/filter.c | 83 ++++++++-------------------------------------------- lib/filter.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 71 deletions(-) diff --git a/lib/filter.c b/lib/filter.c index d61b03cbe2..cb29a7a6d4 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -34,65 +34,6 @@ DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List") DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str") DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter") -struct filter_cisco { - /* Cisco access-list */ - int extended; - struct in_addr addr; - struct in_addr addr_mask; - struct in_addr mask; - struct in_addr mask_mask; -}; - -struct filter_zebra { - /* If this filter is "exact" match then this flag is set. */ - int exact; - - /* Prefix information. */ - struct prefix prefix; -}; - -/* Filter element of access list */ -struct filter { - /* For doubly linked list. */ - struct filter *next; - struct filter *prev; - - /* Filter type information. */ - enum filter_type type; - - /* Sequence number */ - int64_t seq; - - /* Cisco access-list */ - int cisco; - - union { - struct filter_cisco cfilter; - struct filter_zebra zfilter; - } u; -}; - -/* List of access_list. */ -struct access_list_list { - struct access_list *head; - struct access_list *tail; -}; - -/* Master structure of access_list. */ -struct access_master { - /* List of access_list which name is number. */ - struct access_list_list num; - - /* List of access_list which name is string. */ - struct access_list_list str; - - /* Hook function which is executed when new access_list is added. */ - void (*add_hook)(struct access_list *); - - /* Hook function which is executed when access_list is deleted. */ - void (*delete_hook)(struct access_list *); -}; - /* Static structure for mac access_list's master. */ static struct access_master access_master_mac = { {NULL, NULL}, @@ -129,7 +70,7 @@ static struct access_master *access_master_get(afi_t afi) } /* Allocate new filter structure. */ -static struct filter *filter_new(void) +struct filter *filter_new(void) { return XCALLOC(MTYPE_ACCESS_FILTER, sizeof(struct filter)); } @@ -210,7 +151,7 @@ static void access_list_free(struct access_list *access) } /* Delete access_list from access_master and free it. */ -static void access_list_delete(struct access_list *access) +void access_list_delete(struct access_list *access) { struct filter *filter; struct filter *next; @@ -356,7 +297,7 @@ struct access_list *access_list_lookup(afi_t afi, const char *name) /* Get access list from list of access_list. If there isn't matched access_list create new one and return it. */ -static struct access_list *access_list_get(afi_t afi, const char *name) +struct access_list *access_list_get(afi_t afi, const char *name) { struct access_list *access; @@ -406,7 +347,7 @@ void access_list_delete_hook(void (*func)(struct access_list *access)) } /* Calculate new sequential number. */ -static int64_t filter_new_seq_get(struct access_list *access) +int64_t filter_new_seq_get(struct access_list *access) { int64_t maxseq; int64_t newseq; @@ -447,8 +388,8 @@ static bool access_list_empty(struct access_list *access) /* Delete filter from specified access_list. If there is hook function execute it. */ -static void access_list_filter_delete(struct access_list *access, - struct filter *filter) +void access_list_filter_delete(struct access_list *access, + struct filter *filter) { struct access_master *master; struct filter *replace = filter; @@ -478,8 +419,8 @@ static void access_list_filter_delete(struct access_list *access, } /* Add new filter to the end of specified access_list. */ -static void access_list_filter_add(struct access_list *access, - struct filter *filter) +void access_list_filter_add(struct access_list *access, + struct filter *filter) { struct filter *replace; struct filter *point; @@ -541,8 +482,8 @@ static void access_list_filter_add(struct access_list *access, host A single host address */ -static struct filter *filter_lookup_cisco(struct access_list *access, - struct filter *mnew) +struct filter *filter_lookup_cisco(struct access_list *access, + struct filter *mnew) { struct filter *mfilter; struct filter_cisco *filter; @@ -573,8 +514,8 @@ static struct filter *filter_lookup_cisco(struct access_list *access, return NULL; } -static struct filter *filter_lookup_zebra(struct access_list *access, - struct filter *mnew) +struct filter *filter_lookup_zebra(struct access_list *access, + struct filter *mnew) { struct filter *mfilter; struct filter_zebra *filter; diff --git a/lib/filter.h b/lib/filter.h index 3dd2eaaf15..4f53412330 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -23,6 +23,7 @@ #define _ZEBRA_FILTER_H #include "if.h" +#include "prefix.h" #ifdef __cplusplus extern "C" { @@ -41,6 +42,50 @@ enum filter_type { FILTER_DENY, FILTER_PERMIT, FILTER_DYNAMIC }; enum access_type { ACCESS_TYPE_STRING, ACCESS_TYPE_NUMBER }; +struct filter_cisco { + /* Cisco access-list */ + int extended; + struct in_addr addr; + struct in_addr addr_mask; + struct in_addr mask; + struct in_addr mask_mask; +}; + +struct filter_zebra { + /* If this filter is "exact" match then this flag is set. */ + int exact; + + /* Prefix information. */ + struct prefix prefix; +}; + +/* Forward declaration of access-list struct. */ +struct access_list; + +/* Filter element of access list */ +struct filter { + /* For doubly linked list. */ + struct filter *next; + struct filter *prev; + + /* Parent access-list pointer. */ + struct access_list *acl; + + /* Filter type information. */ + enum filter_type type; + + /* Sequence number */ + int64_t seq; + + /* Cisco access-list */ + int cisco; + + union { + struct filter_cisco cfilter; + struct filter_zebra zfilter; + } u; +}; + /* Access list */ struct access_list { char *name; @@ -57,6 +102,28 @@ struct access_list { struct filter *tail; }; +/* List of access_list. */ +struct access_list_list { + struct access_list *head; + struct access_list *tail; +}; + +/* Master structure of access_list. */ +struct access_master { + /* List of access_list which name is number. */ + struct access_list_list num; + + /* List of access_list which name is string. */ + struct access_list_list str; + + /* Hook function which is executed when new access_list is added. */ + void (*add_hook)(struct access_list *); + + /* Hook function which is executed when access_list is deleted. */ + void (*delete_hook)(struct access_list *); +}; + + /* Prototypes for access-list. */ extern void access_list_init(void); extern void access_list_reset(void); @@ -66,6 +133,19 @@ extern struct access_list *access_list_lookup(afi_t, const char *); extern enum filter_type access_list_apply(struct access_list *access, const void *object); +struct access_list *access_list_get(afi_t afi, const char *name); +void access_list_delete(struct access_list *access); +struct filter *filter_new(void); +void access_list_filter_add(struct access_list *access, + struct filter *filter); +void access_list_filter_delete(struct access_list *access, + struct filter *filter); +int64_t filter_new_seq_get(struct access_list *access); +struct filter *filter_lookup_cisco(struct access_list *access, + struct filter *mnew); +struct filter *filter_lookup_zebra(struct access_list *access, + struct filter *mnew); + #ifdef __cplusplus } #endif From 2fb717988832259273dee00f3bbcd9033f9c7ad0 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 11 Nov 2019 20:21:25 -0300 Subject: [PATCH 03/31] lib: export prefix-lists functions Export all functions that are going to be used by the northbound. Signed-off-by: Rafael Zalamena --- lib/plist.c | 16 ++++++++-------- lib/plist.h | 14 ++++++++++++++ lib/plist_int.h | 2 ++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/plist.c b/lib/plist.c index d18d51618a..0addb6fde0 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -178,7 +178,7 @@ static void prefix_list_free(struct prefix_list *plist) XFREE(MTYPE_PREFIX_LIST, plist); } -static struct prefix_list_entry *prefix_list_entry_new(void) +struct prefix_list_entry *prefix_list_entry_new(void) { struct prefix_list_entry *new; @@ -279,7 +279,7 @@ static struct prefix_list *prefix_list_insert(afi_t afi, int orf, return plist; } -static struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name) +struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name) { struct prefix_list *plist; @@ -294,7 +294,7 @@ static void prefix_list_trie_del(struct prefix_list *plist, struct prefix_list_entry *pentry); /* Delete prefix-list from prefix_list_master and free it. */ -static void prefix_list_delete(struct prefix_list *plist) +void prefix_list_delete(struct prefix_list *plist) { struct prefix_list_list *list; struct prefix_master *master; @@ -381,7 +381,7 @@ void prefix_list_delete_hook(void (*func)(struct prefix_list *plist)) } /* Calculate new sequential number. */ -static int64_t prefix_new_seq_get(struct prefix_list *plist) +int64_t prefix_new_seq_get(struct prefix_list *plist) { int64_t maxseq; int64_t newseq; @@ -411,7 +411,7 @@ static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist, return NULL; } -static struct prefix_list_entry * +struct prefix_list_entry * prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix, enum prefix_list_type type, int64_t seq, int le, int ge) @@ -502,9 +502,9 @@ static void prefix_list_trie_del(struct prefix_list *plist, } -static void prefix_list_entry_delete(struct prefix_list *plist, - struct prefix_list_entry *pentry, - int update_list) +void prefix_list_entry_delete(struct prefix_list *plist, + struct prefix_list_entry *pentry, + int update_list) { if (plist == NULL || pentry == NULL) return; diff --git a/lib/plist.h b/lib/plist.h index ba2846d74a..57eb763a68 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -79,6 +79,20 @@ extern void prefix_bgp_orf_remove_all(afi_t, char *); extern int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name, bool use_json); +extern struct prefix_list *prefix_list_get(afi_t afi, int orf, + const char *name); +extern void prefix_list_delete(struct prefix_list *plist); +extern int64_t prefix_new_seq_get(struct prefix_list *plist); + +extern struct prefix_list_entry *prefix_list_entry_new(void); +extern void prefix_list_entry_delete(struct prefix_list *plist, + struct prefix_list_entry *pentry, + int update_list); +extern struct prefix_list_entry * +prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix, + enum prefix_list_type type, int64_t seq, int le, + int ge); + #ifdef __cplusplus } #endif diff --git a/lib/plist_int.h b/lib/plist_int.h index ec8bbe1315..b180d18081 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -65,6 +65,8 @@ struct prefix_list_entry { unsigned long refcnt; unsigned long hitcnt; + struct prefix_list *pl; + struct prefix_list_entry *next; struct prefix_list_entry *prev; From 4470143be0dd85dcd3abcc8b7de9686b6ec40a9b Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 8 Nov 2019 14:48:50 -0300 Subject: [PATCH 04/31] lib: implement filter northbound Implement all access-list and prefix-list northbound callbacks. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 1283 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1283 insertions(+) create mode 100644 lib/filter_nb.c diff --git a/lib/filter_nb.c b/lib/filter_nb.c new file mode 100644 index 0000000000..e18064a23f --- /dev/null +++ b/lib/filter_nb.c @@ -0,0 +1,1283 @@ +/* + * FRR filter northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include "zebra.h" + +#include "lib/log.h" +#include "lib/northbound.h" +#include "lib/prefix.h" + +#include "lib/filter.h" +#include "lib/plist.h" +#include "lib/plist_int.h" + +/* + * XPath: /frr-filter:lib/access-list-legacy + */ +static int lib_access_list_legacy_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct access_list *acl; + const char *acl_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl_name = yang_dnode_get_string(dnode, "./number"); + acl = access_list_get(AFI_IP, acl_name); + nb_running_set_entry(dnode, acl); + + return NB_OK; +} + +static int lib_access_list_legacy_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct access_master *am; + struct access_list *acl; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl = nb_running_unset_entry(dnode); + am = acl->master; + if (am->delete_hook) + am->delete_hook(acl); + + access_list_delete(acl); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/remark + */ +static int lib_access_list_legacy_remark_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct access_list *acl; + const char *remark; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl = nb_running_get_entry(dnode, NULL, true); + if (acl->remark) + XFREE(MTYPE_TMP, acl->remark); + + remark = yang_dnode_get_string(dnode, NULL); + acl->remark = XSTRDUP(MTYPE_TMP, remark); + + return NB_OK; +} + +static int lib_access_list_legacy_remark_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct access_list *acl; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl = nb_running_get_entry(dnode, NULL, true); + if (acl->remark) + XFREE(MTYPE_TMP, acl->remark); + + acl->remark = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry + */ +static int lib_access_list_legacy_entry_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct access_list *acl; + struct filter *f; + uint32_t aclno; + + /* TODO: validate `filter_lookup_cisco` returns NULL. */ + + if (event != NB_EV_APPLY) + return NB_OK; + + aclno = yang_dnode_get_uint16(dnode, "../number"); + + f = filter_new(); + f->cisco = 1; + f->seq = yang_dnode_get_uint32(dnode, "./sequence"); + fc = &f->u.cfilter; + if ((aclno >= 1 && aclno <= 99) || (aclno >= 1300 && aclno <= 1999)) + fc->extended = 0; + else + fc->extended = 1; + + acl = nb_running_get_entry(dnode, NULL, true); + f->acl = acl; + access_list_filter_add(acl, f); + nb_running_set_entry(dnode, f); + + return NB_OK; +} + +static int lib_access_list_legacy_entry_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct access_list *acl; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_unset_entry(dnode); + acl = f->acl; + access_list_filter_delete(acl, f); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/action + */ +static int +lib_access_list_legacy_entry_action_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + const char *filter_type; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + filter_type = yang_dnode_get_string(dnode, NULL); + if (strcmp(filter_type, "permit") == 0) + f->type = FILTER_PERMIT; + else + f->type = FILTER_DENY; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/host + */ +static int +lib_access_list_legacy_entry_host_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + yang_dnode_get_ipv4(&fc->addr, dnode, NULL); + fc->addr_mask.s_addr = INADDR_ANY; + + return NB_OK; +} + +static int +lib_access_list_legacy_entry_host_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/network + */ +static int +lib_access_list_legacy_entry_network_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + yang_dnode_get_prefix(&p, dnode, NULL); + fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); + masklen2ip(p.prefixlen, &fc->addr_mask); + + return NB_OK; +} + +static int +lib_access_list_legacy_entry_network_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/any + */ +static int lib_access_list_legacy_entry_any_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +static int +lib_access_list_legacy_entry_any_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->addr.s_addr = INADDR_ANY; + fc->addr_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/destination-host + */ +static int lib_access_list_legacy_entry_destination_host_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + yang_dnode_get_ipv4(&fc->mask, dnode, NULL); + fc->mask_mask.s_addr = INADDR_ANY; + + return NB_OK; +} + +static int lib_access_list_legacy_entry_destination_host_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/destination-network + */ +static int lib_access_list_legacy_entry_destination_network_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + yang_dnode_get_prefix(&p, dnode, NULL); + fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); + masklen2ip(p.prefixlen, &fc->addr_mask); + + return NB_OK; +} + +static int lib_access_list_legacy_entry_destination_network_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list-legacy/entry/destination-any + */ +static int lib_access_list_legacy_entry_destination_any_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +static int lib_access_list_legacy_entry_destination_any_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct filter_cisco *fc; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fc = &f->u.cfilter; + fc->mask.s_addr = INADDR_ANY; + fc->mask_mask.s_addr = INADDR_NONE; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list + */ +static int lib_access_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct access_list *acl; + const char *acl_name; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + type = yang_dnode_get_enum(dnode, "./type"); + acl_name = yang_dnode_get_string(dnode, "./name"); + + switch (type) { + case 0: /* ipv4 */ + acl = access_list_get(AFI_IP, acl_name); + break; + case 1: /* ipv6 */ + acl = access_list_get(AFI_IP6, acl_name); + break; + case 2: /* mac */ + acl = access_list_get(AFI_L2VPN, acl_name); + break; + } + + nb_running_set_entry(dnode, acl); + + return NB_OK; +} + +static int lib_access_list_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct access_master *am; + struct access_list *acl; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl = nb_running_unset_entry(dnode); + am = acl->master; + if (am->delete_hook) + am->delete_hook(acl); + + access_list_delete(acl); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list/remark + */ +static int lib_access_list_remark_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_access_list_legacy_remark_modify(event, dnode, resource); +} + +static int lib_access_list_remark_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return lib_access_list_legacy_remark_destroy(event, dnode); +} + +/* + * XPath: /frr-filter:lib/access-list/entry + */ +static int lib_access_list_entry_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct access_list *acl; + struct filter *f; + + /* TODO: validate `filter_lookup_zebra` returns NULL. */ + + if (event != NB_EV_APPLY) + return NB_OK; + + f = filter_new(); + f->seq = yang_dnode_get_uint32(dnode, "./sequence"); + + acl = nb_running_get_entry(dnode, NULL, true); + f->acl = acl; + access_list_filter_add(acl, f); + nb_running_set_entry(dnode, f); + + return NB_OK; +} + +static int lib_access_list_entry_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct access_list *acl; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_unset_entry(dnode); + acl = f->acl; + access_list_filter_delete(acl, f); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list/entry/action + */ +static int lib_access_list_entry_action_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_access_list_legacy_entry_action_modify(event, dnode, + resource); +} + +/* + * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix + */ +static int +lib_access_list_entry_ipv4_prefix_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_zebra *fz; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + yang_dnode_get_prefix(&fz->prefix, dnode, NULL); + + return NB_OK; +} + +static int +lib_access_list_entry_ipv4_prefix_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_zebra *fz; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + memset(&fz->prefix, 0, sizeof(fz->prefix)); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match + */ +static int +lib_access_list_entry_ipv4_exact_match_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_zebra *fz; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + fz->exact = yang_dnode_get_bool(dnode, NULL); + + return NB_OK; +} + +static int +lib_access_list_entry_ipv4_exact_match_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_zebra *fz; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + fz->exact = 0; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/access-list/entry/ipv6-prefix + */ +static int +lib_access_list_entry_ipv6_prefix_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_access_list_entry_ipv4_prefix_modify(event, dnode, resource); +} + +static int +lib_access_list_entry_ipv6_prefix_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return lib_access_list_entry_ipv4_prefix_destroy(event, dnode); +} + +/* + * XPath: /frr-filter:lib/access-list/entry/ipv6-exact-match + */ +static int +lib_access_list_entry_ipv6_exact_match_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_access_list_entry_ipv4_exact_match_modify(event, dnode, + resource); +} + +static int +lib_access_list_entry_ipv6_exact_match_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return lib_access_list_entry_ipv4_exact_match_destroy(event, dnode); +} + +/* + * XPath: /frr-filter:lib/access-list/entry/mac + */ +static int lib_access_list_entry_mac_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_access_list_entry_ipv4_prefix_modify(event, dnode, resource); +} + +static int lib_access_list_entry_mac_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return lib_access_list_entry_ipv4_prefix_destroy(event, dnode); +} + +/* + * XPath: /frr-filter:lib/access-list/entry/any + */ +static int lib_access_list_entry_any_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct filter_zebra *fz; + struct filter *f; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + memset(&fz->prefix, 0, sizeof(fz->prefix)); + + type = yang_dnode_get_enum(dnode, "../../type"); + switch (type) { + case 0: /* ipv4 */ + fz->prefix.family = AF_INET; + break; + case 1: /* ipv6 */ + fz->prefix.family = AF_INET6; + break; + case 2: /* mac */ + fz->prefix.family = AF_ETHERNET; + break; + } + + return NB_OK; +} + +static int lib_access_list_entry_any_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct filter_zebra *fz; + struct filter *f; + + if (event != NB_EV_APPLY) + return NB_OK; + + f = nb_running_get_entry(dnode, NULL, true); + fz = &f->u.zfilter; + fz->prefix.family = 0; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list + */ +static int lib_prefix_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list *pl; + const char *name; + int type; + + /* TODO: validate prefix_entry_dup_check() passes. */ + + if (event != NB_EV_APPLY) + return NB_OK; + + type = yang_dnode_get_enum(dnode, "./type"); + name = yang_dnode_get_string(dnode, "./name"); + switch (type) { + case 0: /* ipv4 */ + pl = prefix_list_get(AFI_IP, 0, name); + break; + case 1: /* ipv6 */ + pl = prefix_list_get(AFI_IP6, 0, name); + break; + } + + nb_running_set_entry(dnode, pl); + + return NB_OK; +} + +static int lib_prefix_list_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct prefix_list *pl; + + if (event != NB_EV_APPLY) + return NB_OK; + + pl = nb_running_unset_entry(dnode); + prefix_list_delete(pl); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/description + */ +static int lib_prefix_list_description_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list *pl; + const char *remark; + + if (event != NB_EV_APPLY) + return NB_OK; + + pl = nb_running_get_entry(dnode, NULL, true); + if (pl->desc) + XFREE(MTYPE_TMP, pl->desc); + + remark = yang_dnode_get_string(dnode, NULL); + pl->desc = XSTRDUP(MTYPE_TMP, remark); + + return NB_OK; +} + +static int lib_prefix_list_description_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct prefix_list *pl; + + if (event != NB_EV_APPLY) + return NB_OK; + + pl = nb_running_get_entry(dnode, NULL, true); + if (pl->desc) + XFREE(MTYPE_TMP, pl->desc); + + pl->desc = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry + */ +static int lib_prefix_list_entry_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + struct prefix_list *pl; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + memset(&p, 0, sizeof(p)); + + pl = nb_running_get_entry(dnode, NULL, true); + ple = prefix_list_entry_new(); + ple->pl = pl; + ple->any = 1; + ple->seq = yang_dnode_get_int64(dnode, "./sequence"); + + return NB_OK; +} + +static int lib_prefix_list_entry_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_unset_entry(dnode); + prefix_list_entry_delete(ple->pl, ple, 1); + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/action + */ +static int lib_prefix_list_entry_action_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + const char *action_str; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + action_str = yang_dnode_get_string(dnode, "./action"); + if (strcmp(action_str, "permit") == 0) + ple->type = PREFIX_PERMIT; + else + ple->type = PREFIX_DENY; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix + */ +static int +lib_prefix_list_entry_ipv4_prefix_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_prefix(&ple->prefix, dnode, NULL); + + return NB_OK; +} + +static int +lib_prefix_list_entry_ipv4_prefix_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + memset(&ple->prefix, 0, sizeof(ple->prefix)); + ple->any = 1; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal + */ +static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + ple->ge = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + ple->ge = 0; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal + */ +static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + ple->le = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + ple->le = 0; + + return NB_OK; +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix + */ +static int +lib_prefix_list_entry_ipv6_prefix_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_prefix_list_entry_ipv4_prefix_modify(event, dnode, resource); +} + +static int +lib_prefix_list_entry_ipv6_prefix_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return lib_prefix_list_entry_ipv4_prefix_destroy(event, dnode); +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal + */ +static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( + event, dnode, resource); +} + +static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( + event, dnode); +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal + */ +static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( + event, dnode, resource); +} + +static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( + event, dnode); +} + +/* + * XPath: /frr-filter:lib/prefix-list/entry/any + */ +static int lib_prefix_list_entry_any_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + memset(&ple->prefix, 0, sizeof(ple->prefix)); + ple->any = 1; + + return NB_OK; +} + +static int lib_prefix_list_entry_any_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct prefix_list_entry *ple; + + if (event != NB_EV_APPLY) + return NB_OK; + + ple = nb_running_get_entry(dnode, NULL, true); + memset(&ple->prefix, 0, sizeof(ple->prefix)); + ple->any = 1; + + return NB_OK; +} + +/* clang-format off */ +const struct frr_yang_module_info frr_filter_info = { + .name = "frr-filter", + .nodes = { + { + .xpath = "/frr-filter:lib/access-list-legacy", + .cbs = { + .create = lib_access_list_legacy_create, + .destroy = lib_access_list_legacy_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/remark", + .cbs = { + .modify = lib_access_list_legacy_remark_modify, + .destroy = lib_access_list_legacy_remark_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry", + .cbs = { + .create = lib_access_list_legacy_entry_create, + .destroy = lib_access_list_legacy_entry_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/action", + .cbs = { + .modify = lib_access_list_legacy_entry_action_modify, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/host", + .cbs = { + .modify = lib_access_list_legacy_entry_host_modify, + .destroy = lib_access_list_legacy_entry_host_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/network", + .cbs = { + .modify = lib_access_list_legacy_entry_network_modify, + .destroy = lib_access_list_legacy_entry_network_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/any", + .cbs = { + .create = lib_access_list_legacy_entry_any_create, + .destroy = lib_access_list_legacy_entry_any_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-host", + .cbs = { + .modify = lib_access_list_legacy_entry_destination_host_modify, + .destroy = lib_access_list_legacy_entry_destination_host_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-network", + .cbs = { + .modify = lib_access_list_legacy_entry_destination_network_modify, + .destroy = lib_access_list_legacy_entry_destination_network_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list-legacy/entry/destination-any", + .cbs = { + .create = lib_access_list_legacy_entry_destination_any_create, + .destroy = lib_access_list_legacy_entry_destination_any_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list", + .cbs = { + .create = lib_access_list_create, + .destroy = lib_access_list_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/remark", + .cbs = { + .modify = lib_access_list_remark_modify, + .destroy = lib_access_list_remark_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry", + .cbs = { + .create = lib_access_list_entry_create, + .destroy = lib_access_list_entry_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/action", + .cbs = { + .modify = lib_access_list_entry_action_modify, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix", + .cbs = { + .modify = lib_access_list_entry_ipv4_prefix_modify, + .destroy = lib_access_list_entry_ipv4_prefix_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match", + .cbs = { + .modify = lib_access_list_entry_ipv4_exact_match_modify, + .destroy = lib_access_list_entry_ipv4_exact_match_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix", + .cbs = { + .modify = lib_access_list_entry_ipv6_prefix_modify, + .destroy = lib_access_list_entry_ipv6_prefix_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match", + .cbs = { + .modify = lib_access_list_entry_ipv6_exact_match_modify, + .destroy = lib_access_list_entry_ipv6_exact_match_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/mac", + .cbs = { + .modify = lib_access_list_entry_mac_modify, + .destroy = lib_access_list_entry_mac_destroy, + } + }, + { + .xpath = "/frr-filter:lib/access-list/entry/any", + .cbs = { + .create = lib_access_list_entry_any_create, + .destroy = lib_access_list_entry_any_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list", + .cbs = { + .create = lib_prefix_list_create, + .destroy = lib_prefix_list_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/description", + .cbs = { + .modify = lib_prefix_list_description_modify, + .destroy = lib_prefix_list_description_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry", + .cbs = { + .create = lib_prefix_list_entry_create, + .destroy = lib_prefix_list_entry_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/action", + .cbs = { + .modify = lib_prefix_list_entry_action_modify, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix", + .cbs = { + .modify = lib_prefix_list_entry_ipv4_prefix_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal", + .cbs = { + .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal", + .cbs = { + .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix", + .cbs = { + .modify = lib_prefix_list_entry_ipv6_prefix_modify, + .destroy = lib_prefix_list_entry_ipv6_prefix_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal", + .cbs = { + .modify = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal", + .cbs = { + .modify = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry/any", + .cbs = { + .create = lib_prefix_list_entry_any_create, + .destroy = lib_prefix_list_entry_any_destroy, + } + }, + { + .xpath = NULL, + }, + } +}; From c2aab69336a684e973a73d166a062f3e5abec389 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 8 Nov 2019 14:41:46 -0300 Subject: [PATCH 05/31] *: add filter northbound support Allow all daemons to work with filter northbound. Signed-off-by: Rafael Zalamena --- bfdd/bfdd.c | 1 + bgpd/bgp_main.c | 1 + eigrpd/eigrp_main.c | 1 + isisd/isis_main.c | 1 + lib/filter.h | 2 ++ lib/subdir.am | 1 + ospf6d/ospf6_main.c | 1 + ospfd/ospf_main.c | 1 + ripd/rip_main.c | 1 + ripngd/ripng_main.c | 1 + staticd/static_main.c | 1 + zebra/main.c | 1 + 12 files changed, 13 insertions(+) diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 39d51eb649..258f074e8c 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -111,6 +111,7 @@ static struct quagga_signal_t bfd_signals[] = { }; static const struct frr_yang_module_info *const bfdd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_bfdd_info, &frr_vrf_info, diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 04be8d83eb..f9ff99cab0 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -359,6 +359,7 @@ static void bgp_vrf_terminate(void) } static const struct frr_yang_module_info *const bgpd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index cdf1c6acdb..6c44ce361c 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -139,6 +139,7 @@ struct quagga_signal_t eigrp_signals[] = { static const struct frr_yang_module_info *const eigrpd_yang_modules[] = { &frr_eigrpd_info, + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 78654b2f1c..7d45dd9c2e 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -166,6 +166,7 @@ struct quagga_signal_t isisd_signals[] = { static const struct frr_yang_module_info *const isisd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, #ifndef FABRICD &frr_isisd_info, diff --git a/lib/filter.h b/lib/filter.h index 4f53412330..b45e471101 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -146,6 +146,8 @@ struct filter *filter_lookup_cisco(struct access_list *access, struct filter *filter_lookup_zebra(struct access_list *access, struct filter *mnew); +extern const struct frr_yang_module_info frr_filter_info; + #ifdef __cplusplus } #endif diff --git a/lib/subdir.am b/lib/subdir.am index b2f3e7c5de..ecdd43f4af 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -22,6 +22,7 @@ lib_libfrr_la_SOURCES = \ lib/distribute.c \ lib/ferr.c \ lib/filter.c \ + lib/filter_nb.c \ lib/frrcu.c \ lib/frrlua.c \ lib/frr_pthread.c \ diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 4dbe5ca321..8ae5fdcf06 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -166,6 +166,7 @@ struct quagga_signal_t ospf6_signals[] = { }; static const struct frr_yang_module_info *const ospf6d_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 6a3ba9902d..e534e72a64 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -126,6 +126,7 @@ struct quagga_signal_t ospf_signals[] = { }; static const struct frr_yang_module_info *const ospfd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 9ec32a53e3..7e381887fc 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -114,6 +114,7 @@ static struct quagga_signal_t ripd_signals[] = { }; static const struct frr_yang_module_info *const ripd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_ripd_info, &frr_route_map_info, diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index fbac750db3..010bac851b 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -114,6 +114,7 @@ struct quagga_signal_t ripng_signals[] = { }; static const struct frr_yang_module_info *const ripngd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_ripngd_info, &frr_route_map_info, diff --git a/staticd/static_main.c b/staticd/static_main.c index c77a99f280..08062f19d8 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -104,6 +104,7 @@ struct quagga_signal_t static_signals[] = { }; static const struct frr_yang_module_info *const staticd_yang_modules[] = { + &frr_filter_info, &frr_vrf_info, }; diff --git a/zebra/main.c b/zebra/main.c index 05dd70ff7a..71c7ebb62f 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -253,6 +253,7 @@ struct quagga_signal_t zebra_signals[] = { }; static const struct frr_yang_module_info *const zebra_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_zebra_info, From b62578bd9b0a261807913a22e73108da721252a9 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 8 Nov 2019 14:50:00 -0300 Subject: [PATCH 06/31] lib: migrate filter CLI to use northbound Migrate all filter commands to use the newly implemented northbound. Signed-off-by: Rafael Zalamena --- lib/filter.c | 1958 +------------------------------------------ lib/filter.h | 2 + lib/filter_cli.c | 1081 ++++++++++++++++++++++++ lib/subdir.am | 3 + vtysh/extract.pl.in | 2 +- 5 files changed, 1089 insertions(+), 1957 deletions(-) create mode 100644 lib/filter_cli.c diff --git a/lib/filter.c b/lib/filter.c index cb29a7a6d4..8085732cbd 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -535,1905 +535,6 @@ struct filter *filter_lookup_zebra(struct access_list *access, return NULL; } -static int vty_access_list_remark_unset(struct vty *vty, afi_t afi, - const char *name) -{ - struct access_list *access; - - access = access_list_lookup(afi, name); - if (!access) { - vty_out(vty, "%% access-list %s doesn't exist\n", name); - return CMD_WARNING_CONFIG_FAILED; - } - - XFREE(MTYPE_TMP, access->remark); - - if (access->head == NULL && access->tail == NULL) - access_list_delete(access); - - return CMD_SUCCESS; -} - -static int filter_set_cisco(struct vty *vty, const char *name_str, - const char *seq, const char *type_str, - const char *addr_str, const char *addr_mask_str, - const char *mask_str, const char *mask_mask_str, - int extended, int set) -{ - int ret; - enum filter_type type = FILTER_DENY; - struct filter *mfilter; - struct filter_cisco *filter; - struct access_list *access; - struct in_addr addr; - struct in_addr addr_mask; - struct in_addr mask; - struct in_addr mask_mask; - int64_t seqnum = -1; - - if (seq) - seqnum = (int64_t)atol(seq); - - /* Check of filter type. */ - if (type_str) { - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "%% filter type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - ret = inet_aton(addr_str, &addr); - if (ret <= 0) { - vty_out(vty, "%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton(addr_mask_str, &addr_mask); - if (ret <= 0) { - vty_out(vty, "%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (extended) { - ret = inet_aton(mask_str, &mask); - if (ret <= 0) { - vty_out(vty, "%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton(mask_mask_str, &mask_mask); - if (ret <= 0) { - vty_out(vty, "%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - mfilter = filter_new(); - mfilter->type = type; - mfilter->cisco = 1; - mfilter->seq = seqnum; - filter = &mfilter->u.cfilter; - filter->extended = extended; - filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr; - filter->addr_mask.s_addr = addr_mask.s_addr; - - if (extended) { - filter->mask.s_addr = mask.s_addr & ~mask_mask.s_addr; - filter->mask_mask.s_addr = mask_mask.s_addr; - } - - /* Install new filter to the access_list. */ - access = access_list_get(AFI_IP, name_str); - - if (set) { - if (filter_lookup_cisco(access, mfilter)) - filter_free(mfilter); - else - access_list_filter_add(access, mfilter); - } else { - struct filter *delete_filter; - - delete_filter = filter_lookup_cisco(access, mfilter); - if (delete_filter) - access_list_filter_delete(access, delete_filter); - - filter_free(mfilter); - } - - return CMD_SUCCESS; -} - -/* Standard access-list */ -DEFUN (access_list_standard, - access_list_standard_cmd, - "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] A.B.C.D A.B.C.D", - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Address to match\n" - "Wildcard bits\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - char *wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - address = argv[idx]->arg; - wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, wildcard, NULL, NULL, 0, 1); -} - -DEFUN (access_list_standard_nomask, - access_list_standard_nomask_cmd, - "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] A.B.C.D", - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Address to match\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - address = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, "0.0.0.0", NULL, NULL, 0, 1); -} - -DEFUN (access_list_standard_host, - access_list_standard_host_cmd, - "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] host A.B.C.D", - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "A single host address\n" - "Address to match\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - address = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, "0.0.0.0", NULL, NULL, 0, 1); -} - -DEFUN (access_list_standard_any, - access_list_standard_any_cmd, - "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] any", - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any source host\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 1); -} - -DEFUN (no_access_list_standard, - no_access_list_standard_cmd, - "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] A.B.C.D A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Address to match\n" - "Wildcard bits\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - char *wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - address = argv[idx]->arg; - wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, wildcard, NULL, NULL, 0, 0); -} - -DEFUN (no_access_list_standard_nomask, - no_access_list_standard_nomask_cmd, - "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Address to match\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - address = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, "0.0.0.0", NULL, NULL, 0, 0); -} - -DEFUN (no_access_list_standard_host, - no_access_list_standard_host_cmd, - "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] host A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "A single host address\n" - "Address to match\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *address = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - address = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - address, "0.0.0.0", NULL, NULL, 0, 0); -} - -DEFUN (no_access_list_standard_any, - no_access_list_standard_any_cmd, - "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] any", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP standard access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any source host\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 0); -} - -/* Extended access-list */ -DEFUN (access_list_extended, - access_list_extended_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *src_wildcard = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - dst = argv[idx + 2]->arg; - dst_wildcard = argv[idx + 3]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, dst, dst_wildcard, 1, 1); -} - -DEFUN (access_list_extended_mask_any, - access_list_extended_mask_any_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D any", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "Any destination host\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *src_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, "0.0.0.0", "255.255.255.255", 1, - 1); -} - -DEFUN (access_list_extended_any_mask, - access_list_extended_any_mask_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any A.B.C.D A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *dst = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - dst = argv[idx]->arg; - dst_wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", dst, dst_wildcard, - 1, 1); -} - -DEFUN (access_list_extended_any_any, - access_list_extended_any_any_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any any", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "Any destination host\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", "0.0.0.0", - "255.255.255.255", 1, 1); -} - -DEFUN (access_list_extended_mask_host, - access_list_extended_mask_host_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D host A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *src_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - dst = argv[idx + 3]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, dst, "0.0.0.0", 1, 1); -} - -DEFUN (access_list_extended_host_mask, - access_list_extended_host_mask_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D A.B.C.D A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - dst = argv[idx + 1]->arg; - dst_wildcard = argv[idx + 2]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", dst, dst_wildcard, 1, 1); -} - -DEFUN (access_list_extended_host_host, - access_list_extended_host_host_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D host A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - dst = argv[idx + 2]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", dst, "0.0.0.0", 1, 1); -} - -DEFUN (access_list_extended_any_host, - access_list_extended_any_host_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any host A.B.C.D", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *dst = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - dst = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, - 1); -} - -DEFUN (access_list_extended_host_any, - access_list_extended_host_any_cmd, - "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D any", - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "Any destination host\n") -{ - int idx_acl = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - src = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 1); -} - -DEFUN (no_access_list_extended, - no_access_list_extended_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *src_wildcard = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - dst = argv[idx + 2]->arg; - dst_wildcard = argv[idx + 3]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, dst, dst_wildcard, 1, 0); -} - -DEFUN (no_access_list_extended_mask_any, - no_access_list_extended_mask_any_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D any", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "Any destination host\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *src_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, "0.0.0.0", "255.255.255.255", 1, - 0); -} - -DEFUN (no_access_list_extended_any_mask, - no_access_list_extended_any_mask_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any A.B.C.D A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *dst = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - dst = argv[idx]->arg; - dst_wildcard = argv[idx + 1]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", dst, dst_wildcard, - 1, 0); -} - -DEFUN (no_access_list_extended_any_any, - no_access_list_extended_any_any_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any any", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "Any destination host\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", "0.0.0.0", - "255.255.255.255", 1, 0); -} - -DEFUN (no_access_list_extended_mask_host, - no_access_list_extended_mask_host_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip A.B.C.D A.B.C.D host A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Source address\n" - "Source wildcard bits\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *src_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - src_wildcard = argv[idx + 1]->arg; - dst = argv[idx + 3]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - src_wildcard, dst, "0.0.0.0", 1, 0); -} - -DEFUN (no_access_list_extended_host_mask, - no_access_list_extended_host_mask_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D A.B.C.D A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "Destination address\n" - "Destination Wildcard bits\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - char *dst_wildcard = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - dst = argv[idx + 1]->arg; - dst_wildcard = argv[idx + 2]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", dst, dst_wildcard, 1, 0); -} - -DEFUN (no_access_list_extended_host_host, - no_access_list_extended_host_host_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D host A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - char *dst = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) { - src = argv[idx]->arg; - dst = argv[idx + 2]->arg; - } - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", dst, "0.0.0.0", 1, 0); -} - -DEFUN (no_access_list_extended_any_host, - no_access_list_extended_any_host_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip any host A.B.C.D", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "Any source host\n" - "A single destination host\n" - "Destination address\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *dst = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - dst = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, - "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, - 0); -} - -DEFUN (no_access_list_extended_host_any, - no_access_list_extended_host_any_cmd, - "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] ip host A.B.C.D any", - NO_STR - "Add an access list entry\n" - "IP extended access list\n" - "IP extended access list (expanded range)\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any Internet Protocol\n" - "A single source host\n" - "Source address\n" - "Any destination host\n") -{ - int idx_acl = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *src = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - if (idx) - src = argv[idx]->arg; - - return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, - "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 0); -} - -static int filter_set_zebra(struct vty *vty, const char *name_str, - const char *seq, const char *type_str, afi_t afi, - const char *prefix_str, int exact, int set) -{ - int ret; - enum filter_type type = FILTER_DENY; - struct filter *mfilter; - struct filter_zebra *filter; - struct access_list *access; - struct prefix p; - int64_t seqnum = -1; - - if (strlen(name_str) > ACL_NAMSIZ) { - vty_out(vty, - "%% ACL name %s is invalid: length exceeds " - "%d characters\n", - name_str, ACL_NAMSIZ); - return CMD_WARNING_CONFIG_FAILED; - } - - if (seq) - seqnum = (int64_t)atol(seq); - - /* Check of filter type. */ - if (type_str) { - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "filter type must be [permit|deny]\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Check string format of prefix and prefixlen. */ - if (afi == AFI_IP) { - ret = str2prefix_ipv4(prefix_str, (struct prefix_ipv4 *)&p); - if (ret <= 0) { - vty_out(vty, - "IP address prefix/prefixlen is malformed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } else if (afi == AFI_IP6) { - ret = str2prefix_ipv6(prefix_str, (struct prefix_ipv6 *)&p); - if (ret <= 0) { - vty_out(vty, - "IPv6 address prefix/prefixlen is malformed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } else if (afi == AFI_L2VPN) { - ret = str2prefix_eth(prefix_str, (struct prefix_eth *)&p); - if (ret <= 0) { - vty_out(vty, "MAC address is malformed\n"); - return CMD_WARNING; - } - } else - return CMD_WARNING_CONFIG_FAILED; - - mfilter = filter_new(); - mfilter->type = type; - mfilter->seq = seqnum; - filter = &mfilter->u.zfilter; - prefix_copy(&filter->prefix, &p); - - /* "exact-match" */ - if (exact) - filter->exact = 1; - - /* Install new filter to the access_list. */ - access = access_list_get(afi, name_str); - - if (set) { - if (filter_lookup_zebra(access, mfilter)) - filter_free(mfilter); - else - access_list_filter_add(access, mfilter); - } else { - struct filter *delete_filter; - delete_filter = filter_lookup_zebra(access, mfilter); - if (delete_filter) - access_list_filter_delete(access, delete_filter); - - filter_free(mfilter); - } - - return CMD_SUCCESS; -} - -DEFUN (mac_access_list, - mac_access_list_cmd, - "mac access-list WORD [seq (1-4294967295)] X:X:X:X:X:X", - "Add a mac access-list\n" - "Add an access list entry\n" - "MAC zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "MAC address to match. e.g. 00:01:00:01:00:01\n") -{ - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *mac = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "X:X:X:X:X:X", &idx); - if (idx) - mac = argv[idx]->arg; - assert(mac); - - return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, - mac, 0, 1); -} - -DEFUN (no_mac_access_list, - no_mac_access_list_cmd, - "no mac access-list WORD [seq (1-4294967295)] X:X:X:X:X:X", - NO_STR - "Remove a mac access-list\n" - "Remove an access list entry\n" - "MAC zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "MAC address to match. e.g. 00:01:00:01:00:01\n") -{ - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *mac = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "X:X:X:X:X:X", &idx); - if (idx) - mac = argv[idx]->arg; - assert(mac); - - return filter_set_zebra(vty, argv[3]->arg, seq, permit_deny, AFI_L2VPN, - mac, 0, 0); -} - -DEFUN (mac_access_list_any, - mac_access_list_any_cmd, - "mac access-list WORD [seq (1-4294967295)] any", - "Add a mac access-list\n" - "Add an access list entry\n" - "MAC zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "MAC address to match. e.g. 00:01:00:01:00:01\n") -{ - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, - "00:00:00:00:00:00", 0, 1); -} - -DEFUN (no_mac_access_list_any, - no_mac_access_list_any_cmd, - "no mac access-list WORD [seq (1-4294967295)] any", - NO_STR - "Remove a mac access-list\n" - "Remove an access list entry\n" - "MAC zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "MAC address to match. e.g. 00:01:00:01:00:01\n") -{ - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, - "00:00:00:00:00:00", 0, 0); -} - -DEFUN (access_list_exact, - access_list_exact_cmd, - "access-list WORD [seq (1-4294967295)] A.B.C.D/M [exact-match]", - "Add an access list entry\n" - "IP zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Prefix to match. e.g. 10.0.0.0/8\n" - "Exact match of the prefixes\n") -{ - int idx = 0; - int exact = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *prefix = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D/M", &idx); - if (idx) - prefix = argv[idx]->arg; - assert(prefix); - - idx = 0; - if (argv_find(argv, argc, "exact-match", &idx)) - exact = 1; - - return filter_set_zebra(vty, argv[1]->arg, seq, permit_deny, - AFI_IP, prefix, exact, 1); -} - -DEFUN (access_list_any, - access_list_any_cmd, - "access-list WORD [seq (1-4294967295)] any", - "Add an access list entry\n" - "IP zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Prefix to match. e.g. 10.0.0.0/8\n") -{ - int idx_word = 1; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP, "0.0.0.0/0", 0, 1); -} - -DEFUN (no_access_list_exact, - no_access_list_exact_cmd, - "no access-list WORD [seq (1-4294967295)] A.B.C.D/M [exact-match]", - NO_STR - "Add an access list entry\n" - "IP zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Prefix to match. e.g. 10.0.0.0/8\n" - "Exact match of the prefixes\n") -{ - int idx = 0; - int exact = 0; - char *seq = NULL; - char *permit_deny = NULL; - char *prefix = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "A.B.C.D/M", &idx); - if (idx) - prefix = argv[idx]->arg; - assert(prefix); - - idx = 0; - if (argv_find(argv, argc, "exact-match", &idx)) - exact = 1; - - return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, - AFI_IP, prefix, exact, 0); -} - -DEFUN (no_access_list_any, - no_access_list_any_cmd, - "no access-list WORD [seq (1-4294967295)] any", - NO_STR - "Add an access list entry\n" - "IP zebra access-list name\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Prefix to match. e.g. 10.0.0.0/8\n") -{ - int idx_word = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP, "0.0.0.0/0", 0, 0); -} - -DEFUN (no_access_list_all, - no_access_list_all_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD>", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list name\n") -{ - int idx_acl = 2; - struct access_list *access; - struct access_master *master; - - /* Looking up access_list. */ - access = access_list_lookup(AFI_IP, argv[idx_acl]->arg); - if (access == NULL) { - vty_out(vty, "%% access-list %s doesn't exist\n", - argv[idx_acl]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - master = access->master; - - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); - /* Run hook function. */ - if (master->delete_hook) - (*master->delete_hook)(access); - - /* Delete all filter from access-list. */ - access_list_delete(access); - - return CMD_SUCCESS; -} - -DEFUN (access_list_remark, - access_list_remark_cmd, - "access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> remark LINE...", - "Add an access list entry\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" - "Access list entry comment\n" - "Comment up to 100 characters\n") -{ - int idx_acl = 1; - int idx_remark = 3; - struct access_list *access; - - access = access_list_get(AFI_IP, argv[idx_acl]->arg); - - if (access->remark) { - XFREE(MTYPE_TMP, access->remark); - access->remark = NULL; - } - access->remark = argv_concat(argv, argc, idx_remark); - - return CMD_SUCCESS; -} - -DEFUN (no_access_list_remark, - no_access_list_remark_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> remark", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" - "Access list entry comment\n") -{ - int idx_acl = 2; - return vty_access_list_remark_unset(vty, AFI_IP, argv[idx_acl]->arg); -} - -/* ALIAS_FIXME */ -DEFUN (no_access_list_remark_comment, - no_access_list_remark_comment_cmd, - "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> remark LINE...", - NO_STR - "Add an access list entry\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" - "Access list entry comment\n" - "Comment up to 100 characters\n") -{ - return no_access_list_remark(self, vty, argc, argv); -} - -DEFUN (ipv6_access_list_exact, - ipv6_access_list_exact_cmd, - "ipv6 access-list WORD [seq (1-4294967295)] X:X::X:X/M [exact-match]", - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "IPv6 prefix\n" - "Exact match of the prefixes\n") -{ - int idx = 0; - int exact = 0; - int idx_word = 2; - char *seq = NULL; - char *permit_deny = NULL; - char *prefix = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "X:X::X:X/M", &idx); - if (idx) - prefix = argv[idx]->arg; - - idx = 0; - if (argv_find(argv, argc, "exact-match", &idx)) - exact = 1; - - assert(prefix); - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP6, prefix, exact, 1); -} - -DEFUN (ipv6_access_list_any, - ipv6_access_list_any_cmd, - "ipv6 access-list WORD [seq (1-4294967295)] any", - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefixi to match\n") -{ - int idx_word = 2; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP6, "::/0", 0, 1); -} - -DEFUN (no_ipv6_access_list_exact, - no_ipv6_access_list_exact_cmd, - "no ipv6 access-list WORD [seq (1-4294967295)] X:X::X:X/M [exact-match]", - NO_STR - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Prefix to match. e.g. 3ffe:506::/32\n" - "Exact match of the prefixes\n") -{ - int idx = 0; - int exact = 0; - int idx_word = 3; - char *seq = NULL; - char *permit_deny = NULL; - char *prefix = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "X:X::X:X/M", &idx); - if (idx) - prefix = argv[idx]->arg; - assert(prefix); - - idx = 0; - if (argv_find(argv, argc, "exact-match", &idx)) - exact = 1; - - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP6, prefix, exact, 0); -} - -DEFUN (no_ipv6_access_list_any, - no_ipv6_access_list_any_cmd, - "no ipv6 access-list WORD [seq (1-4294967295)] any", - NO_STR - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefixi to match\n") -{ - int idx_word = 3; - int idx = 0; - char *seq = NULL; - char *permit_deny = NULL; - - argv_find(argv, argc, "(1-4294967295)", &idx); - if (idx) - seq = argv[idx]->arg; - - idx = 0; - argv_find(argv, argc, "permit", &idx); - argv_find(argv, argc, "deny", &idx); - if (idx) - permit_deny = argv[idx]->arg; - - return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, - AFI_IP6, "::/0", 0, 0); -} - - -DEFUN (no_ipv6_access_list_all, - no_ipv6_access_list_all_cmd, - "no ipv6 access-list WORD", - NO_STR - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n") -{ - int idx_word = 3; - struct access_list *access; - struct access_master *master; - - /* Looking up access_list. */ - access = access_list_lookup(AFI_IP6, argv[idx_word]->arg); - if (access == NULL) { - vty_out(vty, "%% access-list %s doesn't exist\n", - argv[idx_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - master = access->master; - - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); - /* Run hook function. */ - if (master->delete_hook) - (*master->delete_hook)(access); - - /* Delete all filter from access-list. */ - access_list_delete(access); - - return CMD_SUCCESS; -} - -DEFUN (ipv6_access_list_remark, - ipv6_access_list_remark_cmd, - "ipv6 access-list WORD remark LINE...", - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Access list entry comment\n" - "Comment up to 100 characters\n") -{ - int idx_word = 2; - int idx_line = 4; - struct access_list *access; - - access = access_list_get(AFI_IP6, argv[idx_word]->arg); - - if (access->remark) { - XFREE(MTYPE_TMP, access->remark); - access->remark = NULL; - } - access->remark = argv_concat(argv, argc, idx_line); - - return CMD_SUCCESS; -} - -DEFUN (no_ipv6_access_list_remark, - no_ipv6_access_list_remark_cmd, - "no ipv6 access-list WORD remark", - NO_STR - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Access list entry comment\n") -{ - int idx_word = 3; - return vty_access_list_remark_unset(vty, AFI_IP6, argv[idx_word]->arg); -} - -/* ALIAS_FIXME */ -DEFUN (no_ipv6_access_list_remark_comment, - no_ipv6_access_list_remark_comment_cmd, - "no ipv6 access-list WORD remark LINE...", - NO_STR - IPV6_STR - "Add an access list entry\n" - "IPv6 zebra access-list\n" - "Access list entry comment\n" - "Comment up to 100 characters\n") -{ - return no_ipv6_access_list_remark(self, vty, argc, argv); -} - static void config_write_access_zebra(struct vty *, struct filter *); static void config_write_access_cisco(struct vty *, struct filter *); @@ -2801,12 +902,6 @@ static void access_list_init_mac(void) install_element(ENABLE_NODE, &show_mac_access_list_cmd); install_element(ENABLE_NODE, &show_mac_access_list_name_cmd); - - /* Zebra access-list */ - install_element(CONFIG_NODE, &mac_access_list_cmd); - install_element(CONFIG_NODE, &no_mac_access_list_cmd); - install_element(CONFIG_NODE, &mac_access_list_any_cmd); - install_element(CONFIG_NODE, &no_mac_access_list_any_cmd); } /* Access-list node. */ @@ -2856,47 +951,6 @@ static void access_list_init_ipv4(void) install_element(ENABLE_NODE, &show_ip_access_list_cmd); install_element(ENABLE_NODE, &show_ip_access_list_name_cmd); - - /* Zebra access-list */ - install_element(CONFIG_NODE, &access_list_exact_cmd); - install_element(CONFIG_NODE, &access_list_any_cmd); - install_element(CONFIG_NODE, &no_access_list_exact_cmd); - install_element(CONFIG_NODE, &no_access_list_any_cmd); - - /* Standard access-list */ - install_element(CONFIG_NODE, &access_list_standard_cmd); - install_element(CONFIG_NODE, &access_list_standard_nomask_cmd); - install_element(CONFIG_NODE, &access_list_standard_host_cmd); - install_element(CONFIG_NODE, &access_list_standard_any_cmd); - install_element(CONFIG_NODE, &no_access_list_standard_cmd); - install_element(CONFIG_NODE, &no_access_list_standard_nomask_cmd); - install_element(CONFIG_NODE, &no_access_list_standard_host_cmd); - install_element(CONFIG_NODE, &no_access_list_standard_any_cmd); - - /* Extended access-list */ - install_element(CONFIG_NODE, &access_list_extended_cmd); - install_element(CONFIG_NODE, &access_list_extended_any_mask_cmd); - install_element(CONFIG_NODE, &access_list_extended_mask_any_cmd); - install_element(CONFIG_NODE, &access_list_extended_any_any_cmd); - install_element(CONFIG_NODE, &access_list_extended_host_mask_cmd); - install_element(CONFIG_NODE, &access_list_extended_mask_host_cmd); - install_element(CONFIG_NODE, &access_list_extended_host_host_cmd); - install_element(CONFIG_NODE, &access_list_extended_any_host_cmd); - install_element(CONFIG_NODE, &access_list_extended_host_any_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_any_mask_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_mask_any_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_any_any_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_host_mask_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_mask_host_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_host_host_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_any_host_cmd); - install_element(CONFIG_NODE, &no_access_list_extended_host_any_cmd); - - install_element(CONFIG_NODE, &access_list_remark_cmd); - install_element(CONFIG_NODE, &no_access_list_all_cmd); - install_element(CONFIG_NODE, &no_access_list_remark_cmd); - install_element(CONFIG_NODE, &no_access_list_remark_comment_cmd); } static int config_write_access_ipv6(struct vty *vty); @@ -2944,16 +998,6 @@ static void access_list_init_ipv6(void) install_element(ENABLE_NODE, &show_ipv6_access_list_cmd); install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd); - - install_element(CONFIG_NODE, &ipv6_access_list_exact_cmd); - install_element(CONFIG_NODE, &ipv6_access_list_any_cmd); - install_element(CONFIG_NODE, &no_ipv6_access_list_exact_cmd); - install_element(CONFIG_NODE, &no_ipv6_access_list_any_cmd); - - install_element(CONFIG_NODE, &no_ipv6_access_list_all_cmd); - install_element(CONFIG_NODE, &ipv6_access_list_remark_cmd); - install_element(CONFIG_NODE, &no_ipv6_access_list_remark_cmd); - install_element(CONFIG_NODE, &no_ipv6_access_list_remark_comment_cmd); } void access_list_init(void) @@ -2961,6 +1005,8 @@ void access_list_init(void) access_list_init_ipv4(); access_list_init_ipv6(); access_list_init_mac(); + + filter_cli_init(); } void access_list_reset(void) diff --git a/lib/filter.h b/lib/filter.h index b45e471101..5a2af88c9d 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -148,6 +148,8 @@ struct filter *filter_lookup_zebra(struct access_list *access, extern const struct frr_yang_module_info frr_filter_info; +void filter_cli_init(void); + #ifdef __cplusplus } #endif diff --git a/lib/filter_cli.c b/lib/filter_cli.c new file mode 100644 index 0000000000..71fbc9080a --- /dev/null +++ b/lib/filter_cli.c @@ -0,0 +1,1081 @@ +/* + * FRR filter CLI implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include "zebra.h" + +#include "lib/command.h" +#include "lib/filter.h" +#include "lib/northbound_cli.h" + +#ifndef VTYSH_EXTRACT_PL +#include "lib/filter_cli_clippy.c" +#endif /* VTYSH_EXTRACT_PL */ + +#define ACCESS_LIST_STR "Access list entry\n" +#define ACCESS_LIST_LEG_STR "IP standard access list\n" +#define ACCESS_LIST_LEG_EXT_STR "IP standard access list (expanded range)\n" +#define ACCESS_LIST_ELEG_STR "IP extended access list\n" +#define ACCESS_LIST_ELEG_EXT_STR "IP extended access list (expanded range)\n" +#define ACCESS_LIST_XLEG_STR \ + ACCESS_LIST_LEG_STR \ + ACCESS_LIST_LEG_EXT_STR \ + ACCESS_LIST_ELEG_STR \ + ACCESS_LIST_ELEG_EXT_STR +#define ACCESS_LIST_ZEBRA_STR "Access list entry\n" +#define ACCESS_LIST_SEQ_STR \ + "Sequence number of an entry\n" \ + "Sequence number\n" +#define ACCESS_LIST_ACTION_STR \ + "Specify packets to reject\n" \ + "Specify packets to forward\n" +#define ACCESS_LIST_REMARK_STR "Access list entry comment\n" +#define ACCESS_LIST_REMARK_LINE_STR "Comment up to 100 characters\n" + +/* + * Helper function to locate filter data structures for Cisco-style ACLs. + */ +static int64_t acl_cisco_get_seq(struct access_list *acl, const char *action, + const char *src, const char *src_mask, + const char *dst, const char *dst_mask) +{ + struct filter_cisco *fc; + struct filter f, *fn; + + memset(&f, 0, sizeof(f)); + memset(&fc, 0, sizeof(fc)); + f.cisco = 1; + if (strcmp(action, "permit") == 0) + f.type = FILTER_PERMIT; + else + f.type = FILTER_DENY; + + fc = &f.u.cfilter; + inet_pton(AF_INET, src, &fc->addr); + inet_pton(AF_INET, src_mask, &fc->addr_mask); + fc->addr.s_addr &= ~fc->addr_mask.s_addr; + if (dst != NULL) { + fc->extended = 1; + inet_pton(AF_INET, dst, &fc->mask); + inet_pton(AF_INET, dst_mask, &fc->mask_mask); + fc->mask.s_addr &= ~fc->mask_mask.s_addr; + } + + fn = filter_lookup_cisco(acl, &f); + if (fn == NULL) + return -1; + + return fn->seq; +} + +/* + * Helper function to locate filter data structures for zebra-style ACLs. + */ +static int64_t acl_zebra_get_seq(struct access_list *acl, const char *action, + const struct prefix *p, bool exact) +{ + struct filter_zebra *fz; + struct filter f, *fn; + + memset(&f, 0, sizeof(f)); + memset(&fz, 0, sizeof(fz)); + if (strcmp(action, "permit") == 0) + f.type = FILTER_PERMIT; + else + f.type = FILTER_DENY; + + fz = &f.u.zfilter; + fz->prefix = *p; + fz->exact = exact; + + fn = filter_lookup_zebra(acl, &f); + if (fn == NULL) + return -1; + + return fn->seq; +} + +/* + * Helper function to concatenate address with mask in Cisco style. + */ +static void concat_addr_mask_v4(const char *addr, const char *mask, char *dst, + size_t dstlen) +{ + struct in_addr ia; + int plen; + + assert(inet_pton(AF_INET, mask, &ia) == 1); + plen = ip_masklen(ia); + snprintf(dst, dstlen, "%s/%d", addr, plen); +} + +/* + * Cisco (legacy) access lists. + */ +DEFPY( + access_list_std, access_list_std_cmd, + "access-list <(1-99)|(1300-1999)>$number [seq (1-4294967295)$seq] $action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask|any>", + ACCESS_LIST_STR + ACCESS_LIST_LEG_STR + ACCESS_LIST_LEG_EXT_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "A single host address\n" + "Address to match\n" + "Address to match\n" + "Wildcard bits\n" + "Any source host\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char ipmask[64]; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the access-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use access-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = filter_new_seq_get(acl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (host_str != NULL && mask_str == NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/host", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, host_str); + } else if (host_str != NULL && mask_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/network", + xpath_entry); + concat_addr_mask_v4(host_str, mask_str, ipmask, sizeof(ipmask)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_access_list_std, no_access_list_std_cmd, + "no access-list <(1-99)|(1300-1999)>$number [seq (1-4294967295)$seq] $action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask|any>", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_LEG_STR + ACCESS_LIST_LEG_EXT_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "A single host address\n" + "Address to match\n" + "Address to match\n" + "Wildcard bits\n" + "Any source host\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq_str != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']/entry[sequence='%s']", + number_str, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (host_str != NULL) + sseq = acl_cisco_get_seq(acl, action, host_str, + mask_str ? mask_str : "0.0.0.0", NULL, + NULL); + else + sseq = acl_cisco_get_seq(acl, action, "0.0.0.0", + "255.255.255.255", NULL, NULL); + if (sseq == -1) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + access_list_ext, access_list_ext_cmd, + "access-list <(100-199)|(2000-2699)>$number [seq (1-4294967295)$seq] $action ip ", + ACCESS_LIST_STR + ACCESS_LIST_ELEG_STR + ACCESS_LIST_ELEG_EXT_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "IPv4 address\n" + "Source address to match\n" + "Source address mask to apply\n" + "Single source host\n" + "Source address to match\n" + "Any source host\n" + "Destination address to match\n" + "Destination address mask to apply\n" + "Single destination host\n" + "Destination address to match\n" + "Any destination host\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char ipmask[64]; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the access-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use access-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = filter_new_seq_get(acl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (src_str != NULL && src_mask_str == NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/host", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, src_str); + } else if (src_str != NULL && src_mask_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/network", + xpath_entry); + concat_addr_mask_v4(src_str, src_mask_str, ipmask, + sizeof(ipmask)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + if (dst_str != NULL && dst_mask_str == NULL) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/destination-host", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, src_str); + } else if (dst_str != NULL && dst_mask_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/destination-network", xpath_entry); + concat_addr_mask_v4(dst_str, dst_mask_str, ipmask, + sizeof(ipmask)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/destination-any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_access_list_ext, no_access_list_ext_cmd, + "no access-list <(100-199)|(2000-2699)>$number [seq (1-4294967295)$seq] $action ip ", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_ELEG_STR + ACCESS_LIST_ELEG_EXT_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Any Internet Protocol\n" + "Source address to match\n" + "Source address mask to apply\n" + "Single source host\n" + "Source address to match\n" + "Any source host\n" + "Destination address to match\n" + "Destination address mask to apply\n" + "Single destination host\n" + "Destination address to match\n" + "Any destination host\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq_str != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']/entry[sequence='%s']", + number_str, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (src_str != NULL) { + if (dst_str != NULL) + sseq = acl_cisco_get_seq( + acl, action, src_str, + src_mask_str ? src_mask_str : "0.0.0.0", + dst_str, + dst_mask_str ? dst_mask_str : "0.0.0.0"); + else + sseq = acl_cisco_get_seq(acl, action, src_str, + src_mask_str ? src_mask_str + : "0.0.0.0", + "0.0.0.0", "255.255.255.255"); + } else { + if (dst_str != NULL) + sseq = acl_cisco_get_seq(acl, action, "0.0.0.0", + "255.255.255.255", dst_str, + dst_mask_str ? dst_mask_str + : "0.0.0.0"); + else + sseq = acl_cisco_get_seq(acl, action, "0.0.0.0", + "255.255.255.255", "0.0.0.0", + "255.255.255.255"); + } + if (sseq == -1) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_access_list_legacy, no_access_list_legacy_cmd, + "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_XLEG_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + access_list_legacy_remark, access_list_legacy_remark_cmd, + "access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark LINE...", + ACCESS_LIST_STR + ACCESS_LIST_XLEG_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']", number_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 3); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_access_list_legacy_remark, no_access_list_legacy_remark_cmd, + "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_XLEG_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list-legacy[number='%s']/remark", + number_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * Zebra access lists. + */ +DEFPY( + access_list, access_list_cmd, + "access-list WORD$name [seq (1-4294967295)$seq] $action ", + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Prefix to match. e.g. 10.0.0.0/8\n" + "Exact match of the prefixes\n" + "Match any IPv4\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the access-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use access-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = filter_new_seq_get(acl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (prefix_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/ipv4-prefix", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + prefix_str); + + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv4-exact-match", xpath_entry); + if (exact) + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, + NULL); + else + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, + NULL); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_access_list, no_access_list_cmd, + "no access-list WORD$name [seq (1-4294967295)$seq] $action ", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Prefix to match. e.g. 10.0.0.0/8\n" + "Exact match of the prefixes\n" + "Match any IPv4\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int64_t sseq; + struct prefix pany; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq_str != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']", + name, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (prefix == NULL) { + memset(&pany, 0, sizeof(pany)); + pany.family = AF_INET; + sseq = acl_zebra_get_seq(acl, action, &pany, exact); + } else + sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, + exact); + if (sseq == -1) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_access_list_all, no_access_list_all_cmd, + "no access-list WORD$name", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + access_list_remark, access_list_remark_cmd, + "access-list WORD$name remark LINE...", + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 3); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_access_list_remark, no_access_list_remark_cmd, + "no access-list WORD$name remark", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv4'][name='%s']/remark", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + ipv6_access_list, ipv6_access_list_cmd, + "ipv6 access-list WORD$name [seq (1-4294967295)$seq] $action ", + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "IPv6 prefix\n" + "Exact match of the prefixes\n" + "Match any IPv6\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the access-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use access-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = filter_new_seq_get(acl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (prefix_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/ipv6-prefix", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + prefix_str); + + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv6-exact-match", xpath_entry); + if (exact) + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, + NULL); + else + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, + NULL); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_ipv6_access_list, no_ipv6_access_list_cmd, + "no ipv6 access-list WORD$name [seq (1-4294967295)$seq] $action ", + NO_STR + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "IPv6 prefix\n" + "Exact match of the prefixes\n" + "Match any IPv6\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int64_t sseq; + struct prefix pany; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq_str != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']/entry[sequence='%s']", + name, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (prefix == NULL) { + memset(&pany, 0, sizeof(pany)); + pany.family = AF_INET6; + sseq = acl_zebra_get_seq(acl, action, &pany, exact); + } else + sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, + exact); + if (sseq == -1) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_ipv6_access_list_all, no_ipv6_access_list_all_cmd, + "no ipv6 access-list WORD$name", + NO_STR + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + ipv6_access_list_remark, ipv6_access_list_remark_cmd, + "ipv6 access-list WORD$name remark LINE...", + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 3); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_ipv6_access_list_remark, no_ipv6_access_list_remark_cmd, + "no ipv6 access-list WORD$name remark", + NO_STR + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='ipv6'][name='%s']/remark", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + mac_access_list, mac_access_list_cmd, + "mac access-list WORD$name [seq (1-4294967295)$seq] $action ", + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "MAC address\n" + "Match any MAC address\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the access-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use access-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = filter_new_seq_get(acl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (mac_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/mac", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, mac_str); + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_mac_access_list, no_mac_access_list_cmd, + "no mac access-list WORD$name [seq (1-4294967295)$seq] $action ", + NO_STR + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "MAC address\n" + "Exact match of the prefixes\n" + "Match any MAC address\n") +{ + struct access_list *acl; + struct lyd_node *dnode; + int64_t sseq; + struct prefix pany; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq_str != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']/entry[sequence='%s']", + name, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']", name); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + acl = nb_running_get_entry(dnode, NULL, true); + if (prefix == NULL) { + memset(&pany, 0, sizeof(pany)); + pany.family = AF_ETHERNET; + sseq = acl_zebra_get_seq(acl, action, &pany, exact); + } else + sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, + exact); + if (sseq == -1) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_mac_access_list_all, no_mac_access_list_all_cmd, + "no mac access-list WORD$name", + NO_STR + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + mac_access_list_remark, mac_access_list_remark_cmd, + "mac access-list WORD$name remark LINE...", + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 3); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_mac_access_list_remark, no_mac_access_list_remark_cmd, + "no mac access-list WORD$name remark", + NO_STR + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/access-list[type='mac'][name='%s']/remark", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void filter_cli_init(void) +{ + /* access-list cisco-style (legacy). */ + install_element(CONFIG_NODE, &access_list_std_cmd); + install_element(CONFIG_NODE, &no_access_list_std_cmd); + install_element(CONFIG_NODE, &access_list_ext_cmd); + install_element(CONFIG_NODE, &no_access_list_ext_cmd); + install_element(CONFIG_NODE, &no_access_list_legacy_cmd); + install_element(CONFIG_NODE, &access_list_legacy_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_legacy_remark_cmd); + + /* access-list zebra-style. */ + install_element(CONFIG_NODE, &access_list_cmd); + install_element(CONFIG_NODE, &no_access_list_cmd); + install_element(CONFIG_NODE, &no_access_list_all_cmd); + install_element(CONFIG_NODE, &access_list_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_remark_cmd); + + install_element(CONFIG_NODE, &ipv6_access_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_all_cmd); + install_element(CONFIG_NODE, &ipv6_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_remark_cmd); + + install_element(CONFIG_NODE, &mac_access_list_cmd); + install_element(CONFIG_NODE, &no_mac_access_list_cmd); + install_element(CONFIG_NODE, &no_mac_access_list_all_cmd); + install_element(CONFIG_NODE, &mac_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_mac_access_list_remark_cmd); +} diff --git a/lib/subdir.am b/lib/subdir.am index ecdd43f4af..57b2cea832 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -22,6 +22,7 @@ lib_libfrr_la_SOURCES = \ lib/distribute.c \ lib/ferr.c \ lib/filter.c \ + lib/filter_cli.c \ lib/filter_nb.c \ lib/frrcu.c \ lib/frrlua.c \ @@ -128,6 +129,7 @@ nodist_lib_libfrr_la_SOURCES = \ vtysh_scan += \ lib/distribute.c \ lib/filter.c \ + lib/filter_cli.c \ lib/if.c \ lib/if_rmap.c \ lib/keychain.c \ @@ -149,6 +151,7 @@ endif clippy_scan += \ lib/if.c \ + lib/filter_cli.c \ lib/log_vty.c \ lib/nexthop_group.c \ lib/northbound_cli.c \ diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index d5142b1b55..794e1f4c73 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -98,7 +98,7 @@ sub scan_file { elsif ($file =~ /lib\/if\.c$/) { $protocol = "VTYSH_INTERFACE"; } - elsif ($file =~ /lib\/(filter|lib_vty)\.c$/) { + elsif ($file =~ /lib\/(filter|filter_cli|lib_vty)\.c$/) { $protocol = "VTYSH_ALL"; } elsif ($file =~ /lib\/agentx\.c$/) { From e0caeadd486a3062fb94a4e6a96e9671bcf7d53c Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 8 Nov 2019 16:19:38 -0300 Subject: [PATCH 07/31] lib: fix filter northbound double removal Don't auto remove filter main access list data structure, it has to be done manually (or via northbound). Signed-off-by: Rafael Zalamena --- lib/filter.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/filter.c b/lib/filter.c index 8085732cbd..fc4f4f5178 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -377,15 +377,6 @@ static struct filter *filter_seq_check(struct access_list *access, return NULL; } -/* If access_list has no filter then return 1. */ -static bool access_list_empty(struct access_list *access) -{ - if (access->head == NULL && access->tail == NULL) - return true; - else - return false; -} - /* Delete filter from specified access_list. If there is hook function execute it. */ void access_list_filter_delete(struct access_list *access, @@ -412,10 +403,6 @@ void access_list_filter_delete(struct access_list *access, /* Run hook function. */ if (master->delete_hook) (*master->delete_hook)(access); - - /* If access_list becomes empty delete it from access_master. */ - if (access_list_empty(access) && !replace) - access_list_delete(access); } /* Add new filter to the end of specified access_list. */ From 89b7c834a54ac9bacf0b97e4daa1f3ff85beee63 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 11 Nov 2019 20:25:20 -0300 Subject: [PATCH 08/31] lib: migrate prefix-list to use northbound Implement all northbound CLI commands for prefix lists. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 441 ++++++++++++++++++++++++++++++++++++++++ lib/plist.c | 516 ----------------------------------------------- 2 files changed, 441 insertions(+), 516 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 71fbc9080a..92230f176e 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -25,6 +25,8 @@ #include "lib/command.h" #include "lib/filter.h" #include "lib/northbound_cli.h" +#include "lib/plist.h" +#include "lib/plist_int.h" #ifndef VTYSH_EXTRACT_PL #include "lib/filter_cli_clippy.c" @@ -50,6 +52,8 @@ #define ACCESS_LIST_REMARK_STR "Access list entry comment\n" #define ACCESS_LIST_REMARK_LINE_STR "Comment up to 100 characters\n" +#define PREFIX_LIST_NAME_STR "Prefix list entry name\n" + /* * Helper function to locate filter data structures for Cisco-style ACLs. */ @@ -1049,6 +1053,426 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +/* + * Prefix lists. + */ +static int plist_remove(struct vty *vty, const char *iptype, const char *name, + const char *seq, const char *action, struct prefix *p, + long ge, long le) +{ + struct prefix_list_entry *pentry; + enum prefix_list_type plt; + struct prefix_list *pl; + struct lyd_node *dnode; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + + /* If the user provided sequence number, then just go for it. */ + if (seq != NULL) { + snprintf( + xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%s']", + iptype, name, seq); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + + /* Otherwise, to keep compatibility, we need to figure it out. */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype, + name); + + /* Access-list must exist before entries. */ + if (yang_dnode_exists(running_config->dnode, xpath) == false) + return CMD_WARNING; + + /* Use access-list data structure to fetch sequence. */ + if (strcmp(action, "permit") == 0) + plt = PREFIX_PERMIT; + else + plt = PREFIX_DENY; + + dnode = yang_dnode_get(running_config->dnode, xpath); + pl = nb_running_get_entry(dnode, NULL, true); + pentry = prefix_list_entry_lookup(pl, p, plt, -1, le, ge); + if (pentry == NULL) + return CMD_WARNING; + + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq); + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + ip_prefix_list, ip_prefix_list_cmd, + "ip prefix-list WORD$name [seq (1-4294967295)$seq] $action ", + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n") +{ + struct prefix_list *pl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the prefix-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use prefix-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + pl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = prefix_new_seq_get(pl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (prefix_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/ipv4-prefix", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + prefix_str); + + if (ge_str) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv4-prefix-length-greater-or-equal", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + ge_str); + } + if (le_str) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv4-prefix-length-lesser-or-equal", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + le_str); + } + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_ip_prefix_list, no_ip_prefix_list_cmd, + "no ip prefix-list WORD$name [seq (1-4294967295)$seq] $action ", + NO_STR + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n") +{ + return plist_remove(vty, "ipv4", name, seq_str, action, + (struct prefix *)prefix, ge, le); +} + +DEFPY( + no_ip_prefix_list_seq, no_ip_prefix_list_seq_cmd, + "no ip prefix-list WORD$name seq (1-4294967295)$seq", + NO_STR + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR) +{ + return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, 0, 0); +} + +DEFPY( + no_ip_prefix_list_all, no_ip_prefix_list_all_cmd, + "no ip prefix-list WORD$name", + NO_STR + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + ip_prefix_list_remark, ip_prefix_list_remark_cmd, + "ip prefix-list WORD$name remark LINE...", + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 4); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_ip_prefix_list_remark, no_ip_prefix_list_remark_cmd, + "no ip prefix-list WORD$name remark", + NO_STR + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']/remark", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +ALIAS( + no_ip_prefix_list_remark, no_ip_prefix_list_remark_line_cmd, + "no ip prefix-list WORD remark LINE...", + NO_STR + IP_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + +DEFPY( + ipv6_prefix_list, ipv6_prefix_list_cmd, + "ipv6 prefix-list WORD$name [seq (1-4294967295)] $action ", + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Any prefix match. Same as \"::0/0 le 128\"\n" + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n") +{ + struct prefix_list *pl; + struct lyd_node *dnode; + int rv; + int64_t sseq; + char xpath[XPATH_MAXLEN]; + char xpath_entry[XPATH_MAXLEN + 32]; + char xpath_value[XPATH_MAXLEN + 64]; + + /* + * Create the prefix-list first, so we can generate sequence if + * none given (backward compatibility). + */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv != CMD_SUCCESS) + return rv; + + /* Use prefix-list data structure to generate sequence. */ + dnode = yang_dnode_get(running_config->dnode, xpath); + pl = nb_running_get_entry(dnode, NULL, true); + if (seq_str == NULL) { + sseq = prefix_new_seq_get(pl); + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%" PRId64 "']", xpath, sseq); + } else + snprintf(xpath_entry, sizeof(xpath_entry), + "%s/entry[sequence='%s']", xpath, seq_str); + + nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); + + snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); + + if (prefix_str != NULL) { + snprintf(xpath_value, sizeof(xpath_value), "%s/ipv6-prefix", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + prefix_str); + + if (ge_str) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv6-prefix-length-greater-or-equal", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + ge_str); + } + if (le_str) { + snprintf(xpath_value, sizeof(xpath_value), + "%s/ipv6-prefix-length-lesser-or-equal", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + le_str); + } + } else { + snprintf(xpath_value, sizeof(xpath_value), "%s/any", + xpath_entry); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + no_ipv6_prefix_list, no_ipv6_prefix_list_cmd, + "no ipv6 prefix-list WORD$name [seq (1-4294967295)$seq] $action ", + NO_STR + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR + ACCESS_LIST_ACTION_STR + "Any prefix match. Same as \"::0/0 le 128\"\n" + "IPv6 prefix /, e.g., 3ffe::/16\n" + "Maximum prefix length to be matched\n" + "Maximum prefix length\n" + "Minimum prefix length to be matched\n" + "Minimum prefix length\n") +{ + return plist_remove(vty, "ipv6", name, seq_str, action, + (struct prefix *)prefix, ge, le); +} + +DEFPY( + no_ipv6_prefix_list_seq, no_ipv6_prefix_list_seq_cmd, + "no ipv6 prefix-list WORD$name seq (1-4294967295)$seq", + NO_STR + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_SEQ_STR) +{ + return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, 0, 0); +} + +DEFPY( + no_ipv6_prefix_list_all, no_ipv6_prefix_list_all_cmd, + "no ipv6 prefix-list WORD$name", + NO_STR + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + ipv6_prefix_list_remark, ipv6_prefix_list_remark_cmd, + "ipv6 prefix-list WORD$name remark LINE...", + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) +{ + int rv; + char *remark; + char xpath[XPATH_MAXLEN]; + char xpath_remark[XPATH_MAXLEN + 32]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); + remark = argv_concat(argv, argc, 4); + nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, NULL); + XFREE(MTYPE_TMP, remark); + + return rv; +} + +DEFPY( + no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_cmd, + "no ipv6 prefix-list WORD$name remark", + NO_STR + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']/remark", + name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +ALIAS( + no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_line_cmd, + "no ipv6 prefix-list WORD remark LINE...", + NO_STR + IPV6_STR + PREFIX_LIST_STR + PREFIX_LIST_NAME_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + void filter_cli_init(void) { /* access-list cisco-style (legacy). */ @@ -1078,4 +1502,21 @@ void filter_cli_init(void) install_element(CONFIG_NODE, &no_mac_access_list_all_cmd); install_element(CONFIG_NODE, &mac_access_list_remark_cmd); install_element(CONFIG_NODE, &no_mac_access_list_remark_cmd); + + /* prefix lists. */ + install_element(CONFIG_NODE, &ip_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_seq_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_all_cmd); + install_element(CONFIG_NODE, &ip_prefix_list_remark_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_remark_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_remark_line_cmd); + + install_element(CONFIG_NODE, &ipv6_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_all_cmd); + install_element(CONFIG_NODE, &ipv6_prefix_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_remark_line_cmd); } diff --git a/lib/plist.c b/lib/plist.c index 0addb6fde0..98e02a5f1a 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -832,280 +832,6 @@ prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new) return NULL; } -static int vty_invalid_prefix_range(struct vty *vty, const char *prefix) -{ - vty_out(vty, - "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n", - prefix); - return CMD_WARNING_CONFIG_FAILED; -} - -static int vty_prefix_list_install(struct vty *vty, afi_t afi, const char *name, - const char *seq, const char *typestr, - const char *prefix, const char *ge, - const char *le) -{ - int ret; - enum prefix_list_type type; - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix_list_entry *dup; - struct prefix p, p_tmp; - bool any = false; - int64_t seqnum = -1; - int lenum = 0; - int genum = 0; - - if (name == NULL || prefix == NULL || typestr == NULL) { - vty_out(vty, "%% Missing prefix or type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Sequential number. */ - if (seq) - seqnum = (int64_t)atol(seq); - - /* ge and le number */ - if (ge) - genum = atoi(ge); - if (le) - lenum = atoi(le); - - /* Check filter type. */ - if (strncmp("permit", typestr, 1) == 0) - type = PREFIX_PERMIT; - else if (strncmp("deny", typestr, 1) == 0) - type = PREFIX_DENY; - else { - vty_out(vty, "%% prefix type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* "any" is special token for matching any IPv4 addresses. */ - switch (afi) { - case AFI_IP: - if (strncmp("any", prefix, strlen(prefix)) == 0) { - ret = str2prefix_ipv4("0.0.0.0/0", - (struct prefix_ipv4 *)&p); - genum = 0; - lenum = IPV4_MAX_BITLEN; - any = true; - } else - ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p); - - if (ret <= 0) { - vty_out(vty, "%% Malformed IPv4 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make a copy to verify prefix matches mask length */ - prefix_copy(&p_tmp, &p); - apply_mask_ipv4((struct prefix_ipv4 *)&p_tmp); - - break; - case AFI_IP6: - if (strncmp("any", prefix, strlen(prefix)) == 0) { - ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p); - genum = 0; - lenum = IPV6_MAX_BITLEN; - any = true; - } else - ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p); - - if (ret <= 0) { - vty_out(vty, "%% Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make a copy to verify prefix matches mask length */ - prefix_copy(&p_tmp, &p); - apply_mask_ipv6((struct prefix_ipv6 *)&p_tmp); - - break; - case AFI_L2VPN: - default: - vty_out(vty, "%% Unrecognized AFI (%d)\n", afi); - return CMD_WARNING_CONFIG_FAILED; - } - - /* If prefix has bits not under the mask, adjust it to fit */ - if (!prefix_same(&p_tmp, &p)) { - char buf[PREFIX2STR_BUFFER]; - char buf_tmp[PREFIX2STR_BUFFER]; - prefix2str(&p, buf, sizeof(buf)); - prefix2str(&p_tmp, buf_tmp, sizeof(buf_tmp)); - vty_out(vty, - "%% Prefix-list %s prefix changed from %s to %s to match length\n", - name, buf, buf_tmp); - zlog_info( - "Prefix-list %s prefix changed from %s to %s to match length", - name, buf, buf_tmp); - p = p_tmp; - } - - /* ge and le check. */ - if (genum && (genum <= p.prefixlen)) - return vty_invalid_prefix_range(vty, prefix); - - if (lenum && (lenum < p.prefixlen)) - return vty_invalid_prefix_range(vty, prefix); - - if (lenum && (genum > lenum)) - return vty_invalid_prefix_range(vty, prefix); - - if (genum && (lenum == (afi == AFI_IP ? 32 : 128))) - lenum = 0; - - /* Get prefix_list with name. */ - plist = prefix_list_get(afi, 0, name); - - /* Make prefix entry. */ - pentry = prefix_list_entry_make(&p, type, seqnum, lenum, genum, any); - - /* Check same policy. */ - dup = prefix_entry_dup_check(plist, pentry); - - if (dup) { - prefix_list_entry_free(pentry); - return CMD_SUCCESS; - } - - /* Install new filter to the access_list. */ - prefix_list_entry_add(plist, pentry); - - return CMD_SUCCESS; -} - -static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi, - const char *name, const char *seq, - const char *typestr, const char *prefix, - const char *ge, const char *le) -{ - int ret; - enum prefix_list_type type; - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix p; - int64_t seqnum = -1; - int lenum = 0; - int genum = 0; - - /* Check prefix list name. */ - plist = prefix_list_lookup(afi, name); - if (!plist) { - vty_out(vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Only prefix-list name specified, delete the entire prefix-list. */ - if (seq == NULL && typestr == NULL && prefix == NULL && ge == NULL - && le == NULL) { - prefix_list_delete(plist); - return CMD_SUCCESS; - } - - /* Check sequence number. */ - if (seq) - seqnum = (int64_t)atol(seq); - - /* Sequence number specified, but nothing else. */ - if (seq && typestr == NULL && prefix == NULL && ge == NULL - && le == NULL) { - pentry = prefix_seq_check(plist, seqnum); - - if (pentry == NULL) { - vty_out(vty, - "%% Can't find prefix-list %s with sequence number %" PRIu64 "\n", - name, seqnum); - return CMD_WARNING_CONFIG_FAILED; - } - - prefix_list_entry_delete(plist, pentry, 1); - return CMD_SUCCESS; - } - - /* ge and le number */ - if (ge) - genum = atoi(ge); - if (le) - lenum = atoi(le); - - /* We must have, at a minimum, both the type and prefix here */ - if ((typestr == NULL) || (prefix == NULL)) - return CMD_WARNING_CONFIG_FAILED; - - /* Check of filter type. */ - if (strncmp("permit", typestr, 1) == 0) - type = PREFIX_PERMIT; - else if (strncmp("deny", typestr, 1) == 0) - type = PREFIX_DENY; - else { - vty_out(vty, "%% prefix type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* "any" is special token for matching any IPv4 addresses. */ - if (afi == AFI_IP) { - if (strncmp("any", prefix, strlen(prefix)) == 0) { - ret = str2prefix_ipv4("0.0.0.0/0", - (struct prefix_ipv4 *)&p); - genum = 0; - lenum = IPV4_MAX_BITLEN; - } else - ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p); - - if (ret <= 0) { - vty_out(vty, "%% Malformed IPv4 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } else if (afi == AFI_IP6) { - if (strncmp("any", prefix, strlen(prefix)) == 0) { - ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p); - genum = 0; - lenum = IPV6_MAX_BITLEN; - } else - ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p); - - if (ret <= 0) { - vty_out(vty, "%% Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Lookup prefix entry. */ - pentry = - prefix_list_entry_lookup(plist, &p, type, seqnum, lenum, genum); - - if (pentry == NULL) { - vty_out(vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Install new filter to the access_list. */ - prefix_list_entry_delete(plist, pentry, 1); - - return CMD_SUCCESS; -} - -static int vty_prefix_list_desc_unset(struct vty *vty, afi_t afi, - const char *name) -{ - struct prefix_list *plist; - - plist = prefix_list_lookup(afi, name); - if (!plist) { - vty_out(vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - XFREE(MTYPE_TMP, plist->desc); - - if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL) - prefix_list_delete(plist); - - return CMD_SUCCESS; -} - enum display_type { normal_display, summary_display, @@ -1349,72 +1075,6 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name, #include "lib/plist_clippy.c" #endif -DEFPY (ip_prefix_list, - ip_prefix_list_cmd, - "ip prefix-list WORD [seq (1-4294967295)] $action ", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - return vty_prefix_list_install(vty, AFI_IP, prefix_list, seq_str, - action, dest, ge_str, le_str); -} - -DEFPY (no_ip_prefix_list, - no_ip_prefix_list_cmd, - "no ip prefix-list WORD [seq (1-4294967295)] $action ", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n") -{ - return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, seq_str, - action, dest, ge_str, le_str); -} - -DEFPY(no_ip_prefix_list_seq, no_ip_prefix_list_seq_cmd, - "no ip prefix-list WORD seq (1-4294967295)", - NO_STR IP_STR PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n") -{ - return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, seq_str, - NULL, NULL, NULL, NULL); -} - -DEFPY (no_ip_prefix_list_all, - no_ip_prefix_list_all_cmd, - "no ip prefix-list WORD", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, NULL, NULL, - NULL, NULL, NULL); -} - DEFPY (ip_prefix_list_sequence_number, ip_prefix_list_sequence_number_cmd, "[no] ip prefix-list sequence-number", @@ -1427,56 +1087,6 @@ DEFPY (ip_prefix_list_sequence_number, return CMD_SUCCESS; } -DEFUN (ip_prefix_list_description, - ip_prefix_list_description_cmd, - "ip prefix-list WORD description LINE...", - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n" - "Up to 80 characters describing this prefix-list\n") -{ - int idx_word = 2; - int idx_line = 4; - struct prefix_list *plist; - - plist = prefix_list_get(AFI_IP, 0, argv[idx_word]->arg); - - if (plist->desc) { - XFREE(MTYPE_TMP, plist->desc); - plist->desc = NULL; - } - plist->desc = argv_concat(argv, argc, idx_line); - - return CMD_SUCCESS; -} - -DEFUN (no_ip_prefix_list_description, - no_ip_prefix_list_description_cmd, - "no ip prefix-list WORD description", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n") -{ - int idx_word = 3; - return vty_prefix_list_desc_unset(vty, AFI_IP, argv[idx_word]->arg); -} - -/* ALIAS_FIXME */ -DEFUN (no_ip_prefix_list_description_comment, - no_ip_prefix_list_description_comment_cmd, - "no ip prefix-list WORD description LINE...", - NO_STR - IP_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n" - "Up to 80 characters describing this prefix-list\n") -{ - return no_ip_prefix_list_description(self, vty, argc, argv); -} DEFPY (show_ip_prefix_list, show_ip_prefix_list_cmd, @@ -1554,61 +1164,6 @@ DEFPY (clear_ip_prefix_list, return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str); } -DEFPY (ipv6_prefix_list, - ipv6_prefix_list_cmd, - "ipv6 prefix-list WORD [seq (1-4294967295)] $action ", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefix match. Same as \"::0/0 le 128\"\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - return vty_prefix_list_install(vty, AFI_IP6, prefix_list, seq_str, - action, dest, ge_str, le_str); -} - -DEFPY (no_ipv6_prefix_list, - no_ipv6_prefix_list_cmd, - "no ipv6 prefix-list WORD [seq (1-4294967295)] $action ", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "sequence number of an entry\n" - "Sequence number\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "Any prefix match. Same as \"::0/0 le 128\"\n" - "IPv6 prefix /, e.g., 3ffe::/16\n" - "Maximum prefix length to be matched\n" - "Maximum prefix length\n" - "Minimum prefix length to be matched\n" - "Minimum prefix length\n") -{ - return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, seq_str, - action, dest, ge_str, le_str); -} - -DEFPY (no_ipv6_prefix_list_all, - no_ipv6_prefix_list_all_cmd, - "no ipv6 prefix-list WORD", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n") -{ - return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, NULL, NULL, - NULL, NULL, NULL); -} - DEFPY (ipv6_prefix_list_sequence_number, ipv6_prefix_list_sequence_number_cmd, "[no] ipv6 prefix-list sequence-number", @@ -1621,58 +1176,6 @@ DEFPY (ipv6_prefix_list_sequence_number, return CMD_SUCCESS; } -DEFUN (ipv6_prefix_list_description, - ipv6_prefix_list_description_cmd, - "ipv6 prefix-list WORD description LINE...", - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n" - "Up to 80 characters describing this prefix-list\n") -{ - int idx_word = 2; - int iddx_line = 4; - struct prefix_list *plist; - - plist = prefix_list_get(AFI_IP6, 0, argv[idx_word]->arg); - - if (plist->desc) { - XFREE(MTYPE_TMP, plist->desc); - plist->desc = NULL; - } - plist->desc = argv_concat(argv, argc, iddx_line); - - return CMD_SUCCESS; -} - -DEFUN (no_ipv6_prefix_list_description, - no_ipv6_prefix_list_description_cmd, - "no ipv6 prefix-list WORD description", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n") -{ - int idx_word = 3; - return vty_prefix_list_desc_unset(vty, AFI_IP6, argv[idx_word]->arg); -} - -/* ALIAS_FIXME */ -DEFUN (no_ipv6_prefix_list_description_comment, - no_ipv6_prefix_list_description_comment_cmd, - "no ipv6 prefix-list WORD description LINE...", - NO_STR - IPV6_STR - PREFIX_LIST_STR - "Name of a prefix list\n" - "Prefix-list specific description\n" - "Up to 80 characters describing this prefix-list\n") -{ - return no_ipv6_prefix_list_description(self, vty, argc, argv); -} - - DEFPY (show_ipv6_prefix_list, show_ipv6_prefix_list_cmd, "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]", @@ -2090,16 +1593,6 @@ static void prefix_list_init_ipv4(void) { install_node(&prefix_node); - install_element(CONFIG_NODE, &ip_prefix_list_cmd); - install_element(CONFIG_NODE, &no_ip_prefix_list_cmd); - install_element(CONFIG_NODE, &no_ip_prefix_list_seq_cmd); - install_element(CONFIG_NODE, &no_ip_prefix_list_all_cmd); - - install_element(CONFIG_NODE, &ip_prefix_list_description_cmd); - install_element(CONFIG_NODE, &no_ip_prefix_list_description_cmd); - install_element(CONFIG_NODE, - &no_ip_prefix_list_description_comment_cmd); - install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd); install_element(VIEW_NODE, &show_ip_prefix_list_cmd); @@ -2128,15 +1621,6 @@ static void prefix_list_init_ipv6(void) { install_node(&prefix_ipv6_node); - install_element(CONFIG_NODE, &ipv6_prefix_list_cmd); - install_element(CONFIG_NODE, &no_ipv6_prefix_list_cmd); - install_element(CONFIG_NODE, &no_ipv6_prefix_list_all_cmd); - - install_element(CONFIG_NODE, &ipv6_prefix_list_description_cmd); - install_element(CONFIG_NODE, &no_ipv6_prefix_list_description_cmd); - install_element(CONFIG_NODE, - &no_ipv6_prefix_list_description_comment_cmd); - install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd); install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd); From fb8884f355d6db9626fb78c99efd26d479404376 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 29 Apr 2020 15:33:46 -0300 Subject: [PATCH 09/31] lib: fix northbound conflicts Changes: - Use the northbound callback prototypes. - Re-implement the removed function: `ipv4_network_addr` (more information: https://github.com/FRRouting/frr/pull/5535 ) Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 465 +++++++++++++++++++++--------------------------- 1 file changed, 199 insertions(+), 266 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index e18064a23f..23cea50870 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -22,7 +22,6 @@ #include "zebra.h" -#include "lib/log.h" #include "lib/northbound.h" #include "lib/prefix.h" @@ -30,36 +29,43 @@ #include "lib/plist.h" #include "lib/plist_int.h" +/* Helper function. */ +static in_addr_t +ipv4_network_addr(in_addr_t hostaddr, int masklen) +{ + struct in_addr mask; + + masklen2ip(masklen, &mask); + return hostaddr & mask.s_addr; +} + /* * XPath: /frr-filter:lib/access-list-legacy */ -static int lib_access_list_legacy_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_legacy_create(struct nb_cb_create_args *args) { struct access_list *acl; const char *acl_name; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - acl_name = yang_dnode_get_string(dnode, "./number"); + acl_name = yang_dnode_get_string(args->dnode, "./number"); acl = access_list_get(AFI_IP, acl_name); - nb_running_set_entry(dnode, acl); + nb_running_set_entry(args->dnode, acl); return NB_OK; } -static int lib_access_list_legacy_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_legacy_destroy(struct nb_cb_destroy_args *args) { struct access_master *am; struct access_list *acl; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - acl = nb_running_unset_entry(dnode); + acl = nb_running_unset_entry(args->dnode); am = acl->master; if (am->delete_hook) am->delete_hook(acl); @@ -72,35 +78,33 @@ static int lib_access_list_legacy_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/access-list-legacy/remark */ -static int lib_access_list_legacy_remark_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_legacy_remark_modify(struct nb_cb_modify_args *args) { struct access_list *acl; const char *remark; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - acl = nb_running_get_entry(dnode, NULL, true); + acl = nb_running_get_entry(args->dnode, NULL, true); if (acl->remark) XFREE(MTYPE_TMP, acl->remark); - remark = yang_dnode_get_string(dnode, NULL); + remark = yang_dnode_get_string(args->dnode, NULL); acl->remark = XSTRDUP(MTYPE_TMP, remark); return NB_OK; } -static int lib_access_list_legacy_remark_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int +lib_access_list_legacy_remark_destroy(struct nb_cb_destroy_args *args) { struct access_list *acl; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - acl = nb_running_get_entry(dnode, NULL, true); + acl = nb_running_get_entry(args->dnode, NULL, true); if (acl->remark) XFREE(MTYPE_TMP, acl->remark); @@ -112,9 +116,7 @@ static int lib_access_list_legacy_remark_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/access-list-legacy/entry */ -static int lib_access_list_legacy_entry_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_legacy_entry_create(struct nb_cb_create_args *args) { struct filter_cisco *fc; struct access_list *acl; @@ -123,38 +125,37 @@ static int lib_access_list_legacy_entry_create(enum nb_event event, /* TODO: validate `filter_lookup_cisco` returns NULL. */ - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - aclno = yang_dnode_get_uint16(dnode, "../number"); + aclno = yang_dnode_get_uint16(args->dnode, "../number"); f = filter_new(); f->cisco = 1; - f->seq = yang_dnode_get_uint32(dnode, "./sequence"); + f->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); fc = &f->u.cfilter; if ((aclno >= 1 && aclno <= 99) || (aclno >= 1300 && aclno <= 1999)) fc->extended = 0; else fc->extended = 1; - acl = nb_running_get_entry(dnode, NULL, true); + acl = nb_running_get_entry(args->dnode, NULL, true); f->acl = acl; access_list_filter_add(acl, f); - nb_running_set_entry(dnode, f); + nb_running_set_entry(args->dnode, f); return NB_OK; } -static int lib_access_list_legacy_entry_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_legacy_entry_destroy(struct nb_cb_destroy_args *args) { struct access_list *acl; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_unset_entry(dnode); + f = nb_running_unset_entry(args->dnode); acl = f->acl; access_list_filter_delete(acl, f); @@ -165,18 +166,16 @@ static int lib_access_list_legacy_entry_destroy(enum nb_event event, * XPath: /frr-filter:lib/access-list-legacy/entry/action */ static int -lib_access_list_legacy_entry_action_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_legacy_entry_action_modify(struct nb_cb_modify_args *args) { const char *filter_type; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); - filter_type = yang_dnode_get_string(dnode, NULL); + f = nb_running_get_entry(args->dnode, NULL, true); + filter_type = yang_dnode_get_string(args->dnode, NULL); if (strcmp(filter_type, "permit") == 0) f->type = FILTER_PERMIT; else @@ -189,35 +188,32 @@ lib_access_list_legacy_entry_action_modify(enum nb_event event, * XPath: /frr-filter:lib/access-list-legacy/entry/host */ static int -lib_access_list_legacy_entry_host_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_legacy_entry_host_modify(struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - yang_dnode_get_ipv4(&fc->addr, dnode, NULL); + yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL); fc->addr_mask.s_addr = INADDR_ANY; return NB_OK; } static int -lib_access_list_legacy_entry_host_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_legacy_entry_host_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->addr.s_addr = INADDR_ANY; fc->addr_mask.s_addr = INADDR_NONE; @@ -229,20 +225,18 @@ lib_access_list_legacy_entry_host_destroy(enum nb_event event, * XPath: /frr-filter:lib/access-list-legacy/entry/network */ static int -lib_access_list_legacy_entry_network_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_legacy_entry_network_modify(struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; struct prefix p; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - yang_dnode_get_prefix(&p, dnode, NULL); + yang_dnode_get_prefix(&p, args->dnode, NULL); fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); masklen2ip(p.prefixlen, &fc->addr_mask); @@ -250,16 +244,15 @@ lib_access_list_legacy_entry_network_modify(enum nb_event event, } static int -lib_access_list_legacy_entry_network_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_legacy_entry_network_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->addr.s_addr = INADDR_ANY; fc->addr_mask.s_addr = INADDR_NONE; @@ -270,17 +263,16 @@ lib_access_list_legacy_entry_network_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/access-list-legacy/entry/any */ -static int lib_access_list_legacy_entry_any_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int +lib_access_list_legacy_entry_any_create(struct nb_cb_create_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->addr.s_addr = INADDR_ANY; fc->addr_mask.s_addr = INADDR_NONE; @@ -289,16 +281,15 @@ static int lib_access_list_legacy_entry_any_create(enum nb_event event, } static int -lib_access_list_legacy_entry_any_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_legacy_entry_any_destroy(struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->addr.s_addr = INADDR_ANY; fc->addr_mask.s_addr = INADDR_NONE; @@ -310,33 +301,32 @@ lib_access_list_legacy_entry_any_destroy(enum nb_event event, * XPath: /frr-filter:lib/access-list-legacy/entry/destination-host */ static int lib_access_list_legacy_entry_destination_host_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - yang_dnode_get_ipv4(&fc->mask, dnode, NULL); + yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL); fc->mask_mask.s_addr = INADDR_ANY; return NB_OK; } static int lib_access_list_legacy_entry_destination_host_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->mask.s_addr = INADDR_ANY; fc->mask_mask.s_addr = INADDR_NONE; @@ -348,19 +338,18 @@ static int lib_access_list_legacy_entry_destination_host_destroy( * XPath: /frr-filter:lib/access-list-legacy/entry/destination-network */ static int lib_access_list_legacy_entry_destination_network_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { struct filter_cisco *fc; struct filter *f; struct prefix p; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; - yang_dnode_get_prefix(&p, dnode, NULL); + yang_dnode_get_prefix(&p, args->dnode, NULL); fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); masklen2ip(p.prefixlen, &fc->addr_mask); @@ -368,15 +357,15 @@ static int lib_access_list_legacy_entry_destination_network_modify( } static int lib_access_list_legacy_entry_destination_network_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->mask.s_addr = INADDR_ANY; fc->mask_mask.s_addr = INADDR_NONE; @@ -388,16 +377,15 @@ static int lib_access_list_legacy_entry_destination_network_destroy( * XPath: /frr-filter:lib/access-list-legacy/entry/destination-any */ static int lib_access_list_legacy_entry_destination_any_create( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_create_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->mask.s_addr = INADDR_ANY; fc->mask_mask.s_addr = INADDR_NONE; @@ -406,15 +394,15 @@ static int lib_access_list_legacy_entry_destination_any_create( } static int lib_access_list_legacy_entry_destination_any_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { struct filter_cisco *fc; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; fc->mask.s_addr = INADDR_ANY; fc->mask_mask.s_addr = INADDR_NONE; @@ -425,19 +413,17 @@ static int lib_access_list_legacy_entry_destination_any_destroy( /* * XPath: /frr-filter:lib/access-list */ -static int lib_access_list_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_create(struct nb_cb_create_args *args) { struct access_list *acl; const char *acl_name; int type; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - type = yang_dnode_get_enum(dnode, "./type"); - acl_name = yang_dnode_get_string(dnode, "./name"); + type = yang_dnode_get_enum(args->dnode, "./type"); + acl_name = yang_dnode_get_string(args->dnode, "./name"); switch (type) { case 0: /* ipv4 */ @@ -451,21 +437,20 @@ static int lib_access_list_create(enum nb_event event, break; } - nb_running_set_entry(dnode, acl); + nb_running_set_entry(args->dnode, acl); return NB_OK; } -static int lib_access_list_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_destroy(struct nb_cb_destroy_args *args) { struct access_master *am; struct access_list *acl; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - acl = nb_running_unset_entry(dnode); + acl = nb_running_unset_entry(args->dnode); am = acl->master; if (am->delete_hook) am->delete_hook(acl); @@ -478,55 +463,49 @@ static int lib_access_list_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/access-list/remark */ -static int lib_access_list_remark_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_remark_modify(struct nb_cb_modify_args *args) { - return lib_access_list_legacy_remark_modify(event, dnode, resource); + return lib_access_list_legacy_remark_modify(args); } -static int lib_access_list_remark_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_remark_destroy(struct nb_cb_destroy_args *args) { - return lib_access_list_legacy_remark_destroy(event, dnode); + return lib_access_list_legacy_remark_destroy(args); } /* * XPath: /frr-filter:lib/access-list/entry */ -static int lib_access_list_entry_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_entry_create(struct nb_cb_create_args *args) { struct access_list *acl; struct filter *f; /* TODO: validate `filter_lookup_zebra` returns NULL. */ - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; f = filter_new(); - f->seq = yang_dnode_get_uint32(dnode, "./sequence"); + f->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); - acl = nb_running_get_entry(dnode, NULL, true); + acl = nb_running_get_entry(args->dnode, NULL, true); f->acl = acl; access_list_filter_add(acl, f); - nb_running_set_entry(dnode, f); + nb_running_set_entry(args->dnode, f); return NB_OK; } -static int lib_access_list_entry_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args) { struct access_list *acl; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_unset_entry(dnode); + f = nb_running_unset_entry(args->dnode); acl = f->acl; access_list_filter_delete(acl, f); @@ -536,46 +515,40 @@ static int lib_access_list_entry_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/access-list/entry/action */ -static int lib_access_list_entry_action_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_entry_action_modify(struct nb_cb_modify_args *args) { - return lib_access_list_legacy_entry_action_modify(event, dnode, - resource); + return lib_access_list_legacy_entry_action_modify(args); } /* * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix */ static int -lib_access_list_entry_ipv4_prefix_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) { struct filter_zebra *fz; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; - yang_dnode_get_prefix(&fz->prefix, dnode, NULL); + yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL); return NB_OK; } static int -lib_access_list_entry_ipv4_prefix_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) { struct filter_zebra *fz; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; memset(&fz->prefix, 0, sizeof(fz->prefix)); @@ -586,34 +559,31 @@ lib_access_list_entry_ipv4_prefix_destroy(enum nb_event event, * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match */ static int -lib_access_list_entry_ipv4_exact_match_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args) { struct filter_zebra *fz; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; - fz->exact = yang_dnode_get_bool(dnode, NULL); + fz->exact = yang_dnode_get_bool(args->dnode, NULL); return NB_OK; } static int -lib_access_list_entry_ipv4_exact_match_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args) { struct filter_zebra *fz; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; fz->exact = 0; @@ -624,74 +594,62 @@ lib_access_list_entry_ipv4_exact_match_destroy(enum nb_event event, * XPath: /frr-filter:lib/access-list/entry/ipv6-prefix */ static int -lib_access_list_entry_ipv6_prefix_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args) { - return lib_access_list_entry_ipv4_prefix_modify(event, dnode, resource); + return lib_access_list_entry_ipv4_prefix_modify(args); } static int -lib_access_list_entry_ipv6_prefix_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args) { - return lib_access_list_entry_ipv4_prefix_destroy(event, dnode); + return lib_access_list_entry_ipv4_prefix_destroy(args); } /* * XPath: /frr-filter:lib/access-list/entry/ipv6-exact-match */ static int -lib_access_list_entry_ipv6_exact_match_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_access_list_entry_ipv6_exact_match_modify(struct nb_cb_modify_args *args) { - return lib_access_list_entry_ipv4_exact_match_modify(event, dnode, - resource); + return lib_access_list_entry_ipv4_exact_match_modify(args); } static int -lib_access_list_entry_ipv6_exact_match_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_access_list_entry_ipv6_exact_match_destroy(struct nb_cb_destroy_args *args) { - return lib_access_list_entry_ipv4_exact_match_destroy(event, dnode); + return lib_access_list_entry_ipv4_exact_match_destroy(args); } /* * XPath: /frr-filter:lib/access-list/entry/mac */ -static int lib_access_list_entry_mac_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_entry_mac_modify(struct nb_cb_modify_args *args) { - return lib_access_list_entry_ipv4_prefix_modify(event, dnode, resource); + return lib_access_list_entry_ipv4_prefix_modify(args); } -static int lib_access_list_entry_mac_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_entry_mac_destroy(struct nb_cb_destroy_args *args) { - return lib_access_list_entry_ipv4_prefix_destroy(event, dnode); + return lib_access_list_entry_ipv4_prefix_destroy(args); } /* * XPath: /frr-filter:lib/access-list/entry/any */ -static int lib_access_list_entry_any_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_access_list_entry_any_create(struct nb_cb_create_args *args) { struct filter_zebra *fz; struct filter *f; int type; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; memset(&fz->prefix, 0, sizeof(fz->prefix)); - type = yang_dnode_get_enum(dnode, "../../type"); + type = yang_dnode_get_enum(args->dnode, "../../type"); switch (type) { case 0: /* ipv4 */ fz->prefix.family = AF_INET; @@ -707,16 +665,15 @@ static int lib_access_list_entry_any_create(enum nb_event event, return NB_OK; } -static int lib_access_list_entry_any_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args) { struct filter_zebra *fz; struct filter *f; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - f = nb_running_get_entry(dnode, NULL, true); + f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; fz->prefix.family = 0; @@ -726,9 +683,7 @@ static int lib_access_list_entry_any_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/prefix-list */ -static int lib_prefix_list_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_prefix_list_create(struct nb_cb_create_args *args) { struct prefix_list *pl; const char *name; @@ -736,11 +691,11 @@ static int lib_prefix_list_create(enum nb_event event, /* TODO: validate prefix_entry_dup_check() passes. */ - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - type = yang_dnode_get_enum(dnode, "./type"); - name = yang_dnode_get_string(dnode, "./name"); + type = yang_dnode_get_enum(args->dnode, "./type"); + name = yang_dnode_get_string(args->dnode, "./name"); switch (type) { case 0: /* ipv4 */ pl = prefix_list_get(AFI_IP, 0, name); @@ -750,20 +705,19 @@ static int lib_prefix_list_create(enum nb_event event, break; } - nb_running_set_entry(dnode, pl); + nb_running_set_entry(args->dnode, pl); return NB_OK; } -static int lib_prefix_list_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args) { struct prefix_list *pl; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - pl = nb_running_unset_entry(dnode); + pl = nb_running_unset_entry(args->dnode); prefix_list_delete(pl); return NB_OK; @@ -772,35 +726,32 @@ static int lib_prefix_list_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/prefix-list/description */ -static int lib_prefix_list_description_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_prefix_list_description_modify(struct nb_cb_modify_args *args) { struct prefix_list *pl; const char *remark; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - pl = nb_running_get_entry(dnode, NULL, true); + pl = nb_running_get_entry(args->dnode, NULL, true); if (pl->desc) XFREE(MTYPE_TMP, pl->desc); - remark = yang_dnode_get_string(dnode, NULL); + remark = yang_dnode_get_string(args->dnode, NULL); pl->desc = XSTRDUP(MTYPE_TMP, remark); return NB_OK; } -static int lib_prefix_list_description_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_prefix_list_description_destroy(struct nb_cb_destroy_args *args) { struct prefix_list *pl; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - pl = nb_running_get_entry(dnode, NULL, true); + pl = nb_running_get_entry(args->dnode, NULL, true); if (pl->desc) XFREE(MTYPE_TMP, pl->desc); @@ -812,37 +763,34 @@ static int lib_prefix_list_description_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/prefix-list/entry */ -static int lib_prefix_list_entry_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) { struct prefix_list_entry *ple; struct prefix_list *pl; struct prefix p; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; memset(&p, 0, sizeof(p)); - pl = nb_running_get_entry(dnode, NULL, true); + 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_int64(dnode, "./sequence"); + ple->seq = yang_dnode_get_int64(args->dnode, "./sequence"); return NB_OK; } -static int lib_prefix_list_entry_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_unset_entry(dnode); + ple = nb_running_unset_entry(args->dnode); prefix_list_entry_delete(ple->pl, ple, 1); return NB_OK; @@ -851,18 +799,16 @@ static int lib_prefix_list_entry_destroy(enum nb_event event, /* * XPath: /frr-filter:lib/prefix-list/entry/action */ -static int lib_prefix_list_entry_action_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; const char *action_str; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); - action_str = yang_dnode_get_string(dnode, "./action"); + ple = nb_running_get_entry(args->dnode, NULL, true); + action_str = yang_dnode_get_string(args->dnode, "./action"); if (strcmp(action_str, "permit") == 0) ple->type = PREFIX_PERMIT; else @@ -875,31 +821,28 @@ static int lib_prefix_list_entry_action_modify(enum nb_event event, * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix */ static int -lib_prefix_list_entry_ipv4_prefix_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_prefix(&ple->prefix, dnode, NULL); + ple = nb_running_get_entry(args->dnode, NULL, true); + yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL); return NB_OK; } static int -lib_prefix_list_entry_ipv4_prefix_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); + ple = nb_running_get_entry(args->dnode, NULL, true); memset(&ple->prefix, 0, sizeof(ple->prefix)); ple->any = 1; @@ -910,29 +853,28 @@ lib_prefix_list_entry_ipv4_prefix_destroy(enum nb_event event, * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal */ static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); - ple->ge = yang_dnode_get_uint8(dnode, NULL); + ple = nb_running_get_entry(args->dnode, NULL, true); + ple->ge = yang_dnode_get_uint8(args->dnode, NULL); return NB_OK; } static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); + ple = nb_running_get_entry(args->dnode, NULL, true); ple->ge = 0; return NB_OK; @@ -942,29 +884,28 @@ static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal */ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); - ple->le = yang_dnode_get_uint8(dnode, NULL); + ple = nb_running_get_entry(args->dnode, NULL, true); + ple->le = yang_dnode_get_uint8(args->dnode, NULL); return NB_OK; } static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); + ple = nb_running_get_entry(args->dnode, NULL, true); ple->le = 0; return NB_OK; @@ -974,84 +915,76 @@ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix */ static int -lib_prefix_list_entry_ipv6_prefix_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args) { - return lib_prefix_list_entry_ipv4_prefix_modify(event, dnode, resource); + return lib_prefix_list_entry_ipv4_prefix_modify(args); } static int -lib_prefix_list_entry_ipv6_prefix_destroy(enum nb_event event, - const struct lyd_node *dnode) +lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args) { - return lib_prefix_list_entry_ipv4_prefix_destroy(event, dnode); + return lib_prefix_list_entry_ipv4_prefix_destroy(args); } /* * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal */ static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( - event, dnode, resource); + args); } static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( - event, dnode); + args); } /* * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal */ static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) + struct nb_cb_modify_args *args) { return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( - event, dnode, resource); + args); } static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy( - enum nb_event event, const struct lyd_node *dnode) + struct nb_cb_destroy_args *args) { return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( - event, dnode); + args); } /* * XPath: /frr-filter:lib/prefix-list/entry/any */ -static int lib_prefix_list_entry_any_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) +static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); + ple = nb_running_get_entry(args->dnode, NULL, true); memset(&ple->prefix, 0, sizeof(ple->prefix)); ple->any = 1; return NB_OK; } -static int lib_prefix_list_entry_any_destroy(enum nb_event event, - const struct lyd_node *dnode) +static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args) { struct prefix_list_entry *ple; - if (event != NB_EV_APPLY) + if (args->event != NB_EV_APPLY) return NB_OK; - ple = nb_running_get_entry(dnode, NULL, true); + ple = nb_running_get_entry(args->dnode, NULL, true); memset(&ple->prefix, 0, sizeof(ple->prefix)); ple->any = 1; From ff94358e54442c7dae0458ff6f2cee05c90b9247 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 29 Apr 2020 15:28:38 -0300 Subject: [PATCH 10/31] lib: fix rebase conflicts Changes: - Remove unused variable. - Make prototypes static like the declaration. - Fix new compilers complaint about uninitialized values. - Fix new compilers complaint about small buffer for `snprintf` concatenation. Signed-off-by: Rafael Zalamena --- lib/filter.c | 1 - lib/filter_cli.c | 4 ++-- lib/filter_nb.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/filter.c b/lib/filter.c index fc4f4f5178..c9a1d683c5 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -383,7 +383,6 @@ void access_list_filter_delete(struct access_list *access, struct filter *filter) { struct access_master *master; - struct filter *replace = filter; master = access->master; diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 92230f176e..1e6d44d27f 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -1126,7 +1126,7 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_value[XPATH_MAXLEN + 128]; /* * Create the prefix-list first, so we can generate sequence if @@ -1310,7 +1310,7 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_value[XPATH_MAXLEN + 128]; /* * Create the prefix-list first, so we can generate sequence if diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 23cea50870..3e22dcd148 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -415,7 +415,7 @@ static int lib_access_list_legacy_entry_destination_any_destroy( */ static int lib_access_list_create(struct nb_cb_create_args *args) { - struct access_list *acl; + struct access_list *acl = NULL; const char *acl_name; int type; @@ -685,7 +685,7 @@ static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args) */ static int lib_prefix_list_create(struct nb_cb_create_args *args) { - struct prefix_list *pl; + struct prefix_list *pl = NULL; const char *name; int type; From 7b611145c86857f28cdd736a85a2e29b78e8582c Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 7 Nov 2019 16:55:18 -0300 Subject: [PATCH 11/31] lib: introduce the yang_dnode_iterate helper Implement helper function that iterates over data nodes that satisfy XPath query. Signed-off-by: Renato Westphal --- lib/yang.c | 26 ++++++++++++++++++++++++++ lib/yang.h | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/lib/yang.c b/lib/yang.c index c80bf20306..7ac39f4182 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -448,6 +448,32 @@ bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath_fmt, ...) return found; } +void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, + const struct lyd_node *dnode, const char *xpath_fmt, + ...) +{ + va_list ap; + char xpath[XPATH_MAXLEN]; + struct ly_set *set; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + set = lyd_find_path(dnode, xpath); + assert(set); + for (unsigned int i = 0; i < set->number; i++) { + int ret; + + dnode = set->set.d[i]; + ret = (*cb)(dnode, arg); + if (ret == YANG_ITER_STOP) + return; + } + + ly_set_free(set); +} + bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath_fmt, ...) { diff --git a/lib/yang.h b/lib/yang.h index 126521707b..3be0fe5383 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -107,6 +107,9 @@ enum yang_iter_flags { /* Callback used by the yang_snodes_iterate_*() family of functions. */ typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg); +/* Callback used by the yang_dnode_iterate() function. */ +typedef int (*yang_dnode_iter_cb)(const struct lyd_node *dnode, void *arg); + /* Return values of the 'yang_iterate_cb' callback. */ #define YANG_ITER_CONTINUE 0 #define YANG_ITER_STOP -1 @@ -357,6 +360,25 @@ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath_fmt, ...); +/* + * Iterate over all libyang data nodes that satisfy an XPath query. + * + * cb + * Function to call with each data node. + * + * arg + * Arbitrary argument passed as the second parameter in each call to 'cb'. + * + * dnode + * Base libyang data node to operate on. + * + * xpath_fmt + * XPath expression (absolute or relative). + */ +void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, + const struct lyd_node *dnode, const char *xpath_fmt, + ...); + /* * Check if the libyang data node contains a default value. Non-presence * containers are assumed to always contain a default value. From 63895e83cbba519fb0d442cf4b80c021c6114b01 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 Apr 2020 10:35:22 -0300 Subject: [PATCH 12/31] lib: fix filter northbound crash when batching Look up next sequence number by checking XPath instead of trying to access unallocated context data structures. This only applies for creation, on destroy the data structures must be there. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 88 +++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 1e6d44d27f..8bd085f05c 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -131,6 +131,38 @@ static void concat_addr_mask_v4(const char *addr, const char *mask, char *dst, snprintf(dst, dstlen, "%s/%d", addr, plen); } +/* + * Helper function to generate a sequence number for legacy commands. + */ +static int acl_get_seq_cb(const struct lyd_node *dnode, void *arg) +{ + int64_t *seq = arg; + int64_t cur_seq = yang_dnode_get_uint32(dnode, "sequence"); + + if (cur_seq > *seq) + *seq = cur_seq; + + return YANG_ITER_CONTINUE; +} + +/** + * Helper function that iterates over the XPath `xpath` on the candidate + * configuration in `vty->candidate_config`. + * + * \param[in] vty shell context with the candidate configuration. + * \param[in] xpath the XPath to look for the sequence leaf. + * \returns next unused sequence number. + */ +static long acl_get_seq(struct vty *vty, const char *xpath) +{ + int64_t seq = 0; + + yang_dnode_iterate(acl_get_seq_cb, &seq, vty->candidate_config->dnode, + "%s/entry", xpath); + + return seq + 5; +} + /* * Cisco (legacy) access lists. */ @@ -148,8 +180,6 @@ DEFPY( "Wildcard bits\n" "Any source host\n") { - struct access_list *acl; - struct lyd_node *dnode; int rv; int64_t sseq; char ipmask[64]; @@ -168,11 +198,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use access-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - acl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = filter_new_seq_get(acl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -281,8 +309,6 @@ DEFPY( "Destination address to match\n" "Any destination host\n") { - struct access_list *acl; - struct lyd_node *dnode; int rv; int64_t sseq; char ipmask[64]; @@ -301,11 +327,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use access-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - acl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = filter_new_seq_get(acl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -507,8 +531,6 @@ DEFPY( "Exact match of the prefixes\n" "Match any IPv4\n") { - struct access_list *acl; - struct lyd_node *dnode; int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; @@ -526,11 +548,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use access-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - acl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = filter_new_seq_get(acl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -694,8 +714,6 @@ DEFPY( "Exact match of the prefixes\n" "Match any IPv6\n") { - struct access_list *acl; - struct lyd_node *dnode; int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; @@ -713,11 +731,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use access-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - acl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = filter_new_seq_get(acl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -884,8 +900,6 @@ DEFPY( "MAC address\n" "Match any MAC address\n") { - struct access_list *acl; - struct lyd_node *dnode; int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; @@ -903,11 +917,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use access-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - acl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = filter_new_seq_get(acl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -1120,8 +1132,6 @@ DEFPY( "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - struct prefix_list *pl; - struct lyd_node *dnode; int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; @@ -1139,11 +1149,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use prefix-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - pl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = prefix_new_seq_get(pl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else @@ -1304,8 +1312,6 @@ DEFPY( "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - struct prefix_list *pl; - struct lyd_node *dnode; int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; @@ -1323,11 +1329,9 @@ DEFPY( if (rv != CMD_SUCCESS) return rv; - /* Use prefix-list data structure to generate sequence. */ - dnode = yang_dnode_get(running_config->dnode, xpath); - pl = nb_running_get_entry(dnode, NULL, true); if (seq_str == NULL) { - sseq = prefix_new_seq_get(pl); + /* Use XPath to find the next sequence number. */ + sseq = acl_get_seq(vty, xpath); snprintf(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else From 1d3c4b664deef0847ee0471b0d36f162f7341f88 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 Apr 2020 13:56:05 -0300 Subject: [PATCH 13/31] lib: migrate filter configuration writer Use northbound to write the configuration from now on. While here, fix how `exact-match` configuration is being created. Signed-off-by: Rafael Zalamena --- lib/filter.c | 99 +++------------------ lib/filter.h | 18 ++++ lib/filter_cli.c | 225 ++++++++++++++++++++++++++++++++++++++++++++--- lib/filter_nb.c | 6 ++ lib/plist.c | 113 ------------------------ 5 files changed, 251 insertions(+), 210 deletions(-) diff --git a/lib/filter.c b/lib/filter.c index c9a1d683c5..e6add0462b 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -29,6 +29,7 @@ #include "log.h" #include "routemap.h" #include "libfrr.h" +#include "northbound_cli.h" DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List") DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str") @@ -775,86 +776,12 @@ static void config_write_access_zebra(struct vty *vty, struct filter *mfilter) vty_out(vty, "\n"); } -static int config_write_access(struct vty *vty, afi_t afi) -{ - struct access_list *access; - struct access_master *master; - struct filter *mfilter; - int write = 0; - - master = access_master_get(afi); - if (master == NULL) - return 0; - - for (access = master->num.head; access; access = access->next) { - if (access->remark) { - vty_out(vty, "%saccess-list %s remark %s\n", - (afi == AFI_IP) ? ("") - : ((afi == AFI_IP6) ? ("ipv6 ") - : ("mac ")), - access->name, access->remark); - write++; - } - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", - (afi == AFI_IP) ? ("") - : ((afi == AFI_IP6) ? ("ipv6 ") - : ("mac ")), - access->name, mfilter->seq, - filter_type_str(mfilter)); - - if (mfilter->cisco) - config_write_access_cisco(vty, mfilter); - else - config_write_access_zebra(vty, mfilter); - - write++; - } - } - - for (access = master->str.head; access; access = access->next) { - if (access->remark) { - vty_out(vty, "%saccess-list %s remark %s\n", - (afi == AFI_IP) ? ("") - : ((afi == AFI_IP6) ? ("ipv6 ") - : ("mac ")), - access->name, access->remark); - write++; - } - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", - (afi == AFI_IP) ? ("") - : ((afi == AFI_IP6) ? ("ipv6 ") - : ("mac ")), - access->name, mfilter->seq, - filter_type_str(mfilter)); - - if (mfilter->cisco) - config_write_access_cisco(vty, mfilter); - else - config_write_access_zebra(vty, mfilter); - - write++; - } - } - return write; -} - -static int config_write_access_mac(struct vty *vty); static struct cmd_node access_mac_node = { .name = "MAC access list", .node = ACCESS_MAC_NODE, .prompt = "", - .config_write = config_write_access_mac, }; -static int config_write_access_mac(struct vty *vty) -{ - return config_write_access(vty, AFI_L2VPN); -} - static void access_list_reset_mac(void) { struct access_list *access; @@ -891,17 +818,26 @@ static void access_list_init_mac(void) } /* Access-list node. */ -static int config_write_access_ipv4(struct vty *vty); +static int config_write_access(struct vty *vty); static struct cmd_node access_node = { .name = "ipv4 access list", .node = ACCESS_NODE, .prompt = "", - .config_write = config_write_access_ipv4, + .config_write = config_write_access, }; -static int config_write_access_ipv4(struct vty *vty) +static int config_write_access(struct vty *vty) { - return config_write_access(vty, AFI_IP); + struct lyd_node *dnode; + int written = 0; + + dnode = yang_dnode_get(running_config->dnode, "/frr-filter:lib"); + if (dnode) { + nb_cli_show_dnode_cmds(vty, dnode, false); + written = 1; + } + + return written; } static void access_list_reset_ipv4(void) @@ -939,19 +875,12 @@ static void access_list_init_ipv4(void) install_element(ENABLE_NODE, &show_ip_access_list_name_cmd); } -static int config_write_access_ipv6(struct vty *vty); static struct cmd_node access_ipv6_node = { .name = "ipv6 access list", .node = ACCESS_IPV6_NODE, .prompt = "", - .config_write = config_write_access_ipv6, }; -static int config_write_access_ipv6(struct vty *vty) -{ - return config_write_access(vty, AFI_IP6); -} - static void access_list_reset_ipv6(void) { struct access_list *access; diff --git a/lib/filter.h b/lib/filter.h index 5a2af88c9d..f4bd62e40d 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -148,6 +148,24 @@ struct filter *filter_lookup_zebra(struct access_list *access, extern const struct frr_yang_module_info frr_filter_info; +/* filter_cli.c */ +struct lyd_node; +struct vty; + +extern void access_list_legacy_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +extern void access_list_legacy_remark_show(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +extern void access_list_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +extern void access_list_remark_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +extern void prefix_list_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +extern void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); + void filter_cli_init(void); #ifdef __cplusplus diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 8bd085f05c..9baeae2d7c 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -20,6 +20,8 @@ * 02110-1301 USA. */ +#include "northbound.h" +#include "prefix.h" #include "zebra.h" #include "lib/command.h" @@ -473,6 +475,50 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void access_list_legacy_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + uint16_t number = yang_dnode_get_uint16(dnode, "../number"); + bool extended; + struct prefix p; + struct in_addr mask; + + vty_out(vty, "access-list %d seq %s %s", number, + yang_dnode_get_string(dnode, "./sequence"), + yang_dnode_get_string(dnode, "./action")); + + extended = (number >= 100 && number <= 199) + || (number >= 2000 && number <= 2699); + if (extended) + vty_out(vty, " ip"); + + if (yang_dnode_exists(dnode, "./network")) { + yang_dnode_get_prefix(&p, dnode, "./network"); + masklen2ip(p.prefixlen, &mask); + vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); + } else if (yang_dnode_exists(dnode, "./host")) { + if (extended) + vty_out(vty, " host"); + + vty_out(vty, " %s", yang_dnode_get_string(dnode, "./host")); + } else if (yang_dnode_exists(dnode, "./any")) + vty_out(vty, " any"); + + if (extended) { + if (yang_dnode_exists(dnode, "./network")) { + yang_dnode_get_prefix(&p, dnode, "./network"); + masklen2ip(p.prefixlen, &mask); + vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); + } else if (yang_dnode_exists(dnode, "./host")) + vty_out(vty, " host %s", + yang_dnode_get_string(dnode, "./host")); + else if (yang_dnode_exists(dnode, "./any")) + vty_out(vty, " any"); + } + + vty_out(vty, "\n"); +} + DEFPY( access_list_legacy_remark, access_list_legacy_remark_cmd, "access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark LINE...", @@ -517,6 +563,14 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void access_list_legacy_remark_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, "access-list %s remark %s\n", + yang_dnode_get_string(dnode, "../number"), + yang_dnode_get_string(dnode, NULL)); +} + /* * Zebra access lists. */ @@ -570,12 +624,8 @@ DEFPY( snprintf(xpath_value, sizeof(xpath_value), "%s/ipv4-exact-match", xpath_entry); - if (exact) - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, - NULL); - else - nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, - NULL); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + exact ? "true" : "false"); } else { snprintf(xpath_value, sizeof(xpath_value), "%s/any", xpath_entry); @@ -753,12 +803,8 @@ DEFPY( snprintf(xpath_value, sizeof(xpath_value), "%s/ipv6-exact-match", xpath_entry); - if (exact) - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, - NULL); - else - nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, - NULL); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + exact ? "true" : "false"); } else { snprintf(xpath_value, sizeof(xpath_value), "%s/any", xpath_entry); @@ -1065,6 +1111,83 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void access_list_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + int type = yang_dnode_get_enum(dnode, "../type"); + struct prefix p; + bool is_any; + bool is_exact = false; + char macstr[PREFIX2STR_BUFFER]; + + is_any = yang_dnode_exists(dnode, "./any"); + switch (type) { + case 0: /* ipv4 */ + if (is_any) + break; + + yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); + is_exact = yang_dnode_get_bool(dnode, "./ipv4-exact-match"); + break; + case 1: /* ipv6 */ + vty_out(vty, "ipv6 "); + if (is_any) + break; + + yang_dnode_get_prefix(&p, dnode, "./ipv6-prefix"); + is_exact = yang_dnode_get_bool(dnode, "./ipv6-exact-match"); + break; + case 2: /* mac */ + vty_out(vty, "mac "); + if (is_any) + break; + + yang_dnode_get_prefix(&p, dnode, "./mac"); + break; + } + + vty_out(vty, "access-list %s seq %s %s", + yang_dnode_get_string(dnode, "../name"), + yang_dnode_get_string(dnode, "./sequence"), + yang_dnode_get_string(dnode, "./action")); + + if (!is_any) { + /* If type is MAC don't show '/mask'. */ + if (type == 2 /* mac */) { + prefix_mac2str(&p.u.prefix_eth, macstr, sizeof(macstr)); + vty_out(vty, " %s", macstr); + } else + vty_out(vty, " %pFX", &p); + } else + vty_out(vty, " any"); + + if (is_exact) + vty_out(vty, " exact-match"); + + vty_out(vty, "\n"); +} + +void access_list_remark_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + int type = yang_dnode_get_enum(dnode, "../type"); + + switch (type) { + case 0: /* ipv4 */ + break; + case 1: /* ipv6 */ + vty_out(vty, "ipv6 "); + break; + case 2: /* mac */ + vty_out(vty, "mac "); + break; + } + + vty_out(vty, "access-list %s remark %s\n", + yang_dnode_get_string(dnode, "../name"), + yang_dnode_get_string(dnode, NULL)); +} + /* * Prefix lists. */ @@ -1477,6 +1600,84 @@ ALIAS( ACCESS_LIST_REMARK_STR ACCESS_LIST_REMARK_LINE_STR) +void prefix_list_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + int type = yang_dnode_get_enum(dnode, "../type"); + const char *ge_str = NULL, *le_str = NULL; + bool is_any; + struct prefix p; + + is_any = yang_dnode_exists(dnode, "./any"); + switch (type) { + case 0: /* ipv4 */ + if (!is_any) + yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); + if (yang_dnode_exists(dnode, + "./ipv4-prefix-length-greater-or-equal")) + ge_str = yang_dnode_get_string( + dnode, "./ipv4-prefix-length-greater-or-equal"); + if (yang_dnode_exists(dnode, + "./ipv4-prefix-length-lesser-or-equal")) + le_str = yang_dnode_get_string( + dnode, "./ipv4-prefix-length-lesser-or-equal"); + + vty_out(vty, "ip "); + break; + case 1: /* ipv6 */ + if (!is_any) + yang_dnode_get_prefix(&p, dnode, "ipv6-prefix"); + if (yang_dnode_exists(dnode, + "./ipv6-prefix-length-greater-or-equal")) + ge_str = yang_dnode_get_string( + dnode, "./ipv6-prefix-length-greater-or-equal"); + if (yang_dnode_exists(dnode, + "./ipv6-prefix-length-lesser-or-equal")) + le_str = yang_dnode_get_string( + dnode, "./ipv6-prefix-length-lesser-or-equal"); + + vty_out(vty, "ipv6 "); + break; + } + + vty_out(vty, "prefix-list %s seq %s %s", + yang_dnode_get_string(dnode, "../name"), + yang_dnode_get_string(dnode, "./sequence"), + yang_dnode_get_string(dnode, "./action")); + + if (is_any) { + vty_out(vty, " any\n"); + return; + } + + vty_out(vty, " %pFX", &p); + if (ge_str) + vty_out(vty, " ge %s", ge_str); + if (le_str) + vty_out(vty, " le %s", le_str); + + vty_out(vty, "\n"); +} + +void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + int type = yang_dnode_get_enum(dnode, "../type"); + + switch (type) { + case 0: /* ipv4 */ + vty_out(vty, "ip "); + break; + case 1: /* ipv6 */ + vty_out(vty, "ipv6 "); + break; + } + + vty_out(vty, "prefix-list %s remark %s\n", + yang_dnode_get_string(dnode, "../name"), + yang_dnode_get_string(dnode, NULL)); +} + void filter_cli_init(void) { /* access-list cisco-style (legacy). */ diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 3e22dcd148..9e46e961ae 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -1007,6 +1007,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .modify = lib_access_list_legacy_remark_modify, .destroy = lib_access_list_legacy_remark_destroy, + .cli_show = access_list_legacy_remark_show, } }, { @@ -1014,6 +1015,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .create = lib_access_list_legacy_entry_create, .destroy = lib_access_list_legacy_entry_destroy, + .cli_show = access_list_legacy_show, } }, { @@ -1076,6 +1078,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .modify = lib_access_list_remark_modify, .destroy = lib_access_list_remark_destroy, + .cli_show = access_list_remark_show, } }, { @@ -1083,6 +1086,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .create = lib_access_list_entry_create, .destroy = lib_access_list_entry_destroy, + .cli_show = access_list_show, } }, { @@ -1145,6 +1149,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .modify = lib_prefix_list_description_modify, .destroy = lib_prefix_list_description_destroy, + .cli_show = prefix_list_remark_show, } }, { @@ -1152,6 +1157,7 @@ const struct frr_yang_module_info frr_filter_info = { .cbs = { .create = lib_prefix_list_entry_create, .destroy = lib_prefix_list_entry_destroy, + .cli_show = prefix_list_show, } }, { diff --git a/lib/plist.c b/lib/plist.c index 98e02a5f1a..aa420da927 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -1252,104 +1252,6 @@ DEFPY (clear_ipv6_prefix_list, return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str); } -/* Configuration write function. */ -static int config_write_prefix_afi(afi_t afi, struct vty *vty) -{ - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix_master *master; - int write = 0; - - master = prefix_master_get(afi, 0); - if (master == NULL) - return 0; - - if (!master->seqnum) { - vty_out(vty, "no ip%s prefix-list sequence-number\n", - afi == AFI_IP ? "" : "v6"); - vty_out(vty, "!\n"); - } - - for (plist = master->num.head; plist; plist = plist->next) { - if (plist->desc) { - vty_out(vty, "ip%s prefix-list %s description %s\n", - afi == AFI_IP ? "" : "v6", plist->name, - plist->desc); - write++; - } - - for (pentry = plist->head; pentry; pentry = pentry->next) { - vty_out(vty, "ip%s prefix-list %s ", - afi == AFI_IP ? "" : "v6", plist->name); - - if (master->seqnum) - vty_out(vty, "seq %" PRId64 " ", pentry->seq); - - vty_out(vty, "%s ", prefix_list_type_str(pentry)); - - if (pentry->any) - vty_out(vty, "any"); - else { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out(vty, "%s/%d", - inet_ntop(p->family, p->u.val, buf, - BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out(vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out(vty, " le %d", pentry->le); - } - vty_out(vty, "\n"); - write++; - } - /* vty_out (vty, "!\n"); */ - } - - for (plist = master->str.head; plist; plist = plist->next) { - if (plist->desc) { - vty_out(vty, "ip%s prefix-list %s description %s\n", - afi == AFI_IP ? "" : "v6", plist->name, - plist->desc); - write++; - } - - for (pentry = plist->head; pentry; pentry = pentry->next) { - vty_out(vty, "ip%s prefix-list %s ", - afi == AFI_IP ? "" : "v6", plist->name); - - if (master->seqnum) - vty_out(vty, "seq %" PRId64 " ", pentry->seq); - - vty_out(vty, "%s", prefix_list_type_str(pentry)); - - if (pentry->any) - vty_out(vty, " any"); - else { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out(vty, " %s/%d", - inet_ntop(p->family, p->u.val, buf, - BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out(vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out(vty, " le %d", pentry->le); - } - vty_out(vty, "\n"); - write++; - } - } - - return write; -} - struct stream *prefix_bgp_orf_entry(struct stream *s, struct prefix_list *plist, uint8_t init_flag, uint8_t permit_flag, uint8_t deny_flag) @@ -1545,21 +1447,13 @@ static void prefix_list_reset_afi(afi_t afi, int orf) master->recent = NULL; } - -static int config_write_prefix_ipv4(struct vty *vty); /* Prefix-list node. */ static struct cmd_node prefix_node = { .name = "ipv4 prefix list", .node = PREFIX_NODE, .prompt = "", - .config_write = config_write_prefix_ipv4, }; -static int config_write_prefix_ipv4(struct vty *vty) -{ - return config_write_prefix_afi(AFI_IP, vty); -} - static void plist_autocomplete_afi(afi_t afi, vector comps, struct cmd_token *token) { @@ -1603,20 +1497,13 @@ static void prefix_list_init_ipv4(void) install_element(ENABLE_NODE, &clear_ip_prefix_list_cmd); } -static int config_write_prefix_ipv6(struct vty *vty); /* Prefix-list node. */ static struct cmd_node prefix_ipv6_node = { .name = "ipv6 prefix list", .node = PREFIX_IPV6_NODE, .prompt = "", - .config_write = config_write_prefix_ipv6, }; -static int config_write_prefix_ipv6(struct vty *vty) -{ - return config_write_prefix_afi(AFI_IP6, vty); -} - static void prefix_list_init_ipv6(void) { install_node(&prefix_ipv6_node); From cc82bcc161503b42ac5b6b1fc2da36fc6f08b567 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 Apr 2020 17:23:51 -0300 Subject: [PATCH 14/31] lib: fix prefix list description command Changes: - Use `description` on CLI but `remark` on YANG like access-list (also because `description` is a reserved word). - Rename YANG model field and northbound code. - Fix wrong sequence type get. - Fix wrong action XPath in action callback. - Fix wrong concat in (ipv6|mac) access-list. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 18 +++++++++--------- lib/filter_nb.c | 16 ++++++++-------- yang/frr-filter.yang | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 9baeae2d7c..fd68bb59ec 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -908,7 +908,7 @@ DEFPY( nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); - remark = argv_concat(argv, argc, 3); + remark = argv_concat(argv, argc, 4); nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); rv = nb_cli_apply_changes(vty, NULL); XFREE(MTYPE_TMP, remark); @@ -1084,7 +1084,7 @@ DEFPY( nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); - remark = argv_concat(argv, argc, 3); + remark = argv_concat(argv, argc, 4); nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); rv = nb_cli_apply_changes(vty, NULL); XFREE(MTYPE_TMP, remark); @@ -1366,7 +1366,7 @@ DEFPY( DEFPY( ip_prefix_list_remark, ip_prefix_list_remark_cmd, - "ip prefix-list WORD$name remark LINE...", + "ip prefix-list WORD$name description LINE...", IP_STR PREFIX_LIST_STR PREFIX_LIST_NAME_STR @@ -1393,7 +1393,7 @@ DEFPY( DEFPY( no_ip_prefix_list_remark, no_ip_prefix_list_remark_cmd, - "no ip prefix-list WORD$name remark", + "no ip prefix-list WORD$name description", NO_STR IP_STR PREFIX_LIST_STR @@ -1412,7 +1412,7 @@ DEFPY( ALIAS( no_ip_prefix_list_remark, no_ip_prefix_list_remark_line_cmd, - "no ip prefix-list WORD remark LINE...", + "no ip prefix-list WORD description LINE...", NO_STR IP_STR PREFIX_LIST_STR @@ -1546,7 +1546,7 @@ DEFPY( DEFPY( ipv6_prefix_list_remark, ipv6_prefix_list_remark_cmd, - "ipv6 prefix-list WORD$name remark LINE...", + "ipv6 prefix-list WORD$name description LINE...", IPV6_STR PREFIX_LIST_STR PREFIX_LIST_NAME_STR @@ -1573,7 +1573,7 @@ DEFPY( DEFPY( no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_cmd, - "no ipv6 prefix-list WORD$name remark", + "no ipv6 prefix-list WORD$name description", NO_STR IPV6_STR PREFIX_LIST_STR @@ -1592,7 +1592,7 @@ DEFPY( ALIAS( no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_line_cmd, - "no ipv6 prefix-list WORD remark LINE...", + "no ipv6 prefix-list WORD description LINE...", NO_STR IPV6_STR PREFIX_LIST_STR @@ -1673,7 +1673,7 @@ void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode, break; } - vty_out(vty, "prefix-list %s remark %s\n", + vty_out(vty, "prefix-list %s description %s\n", yang_dnode_get_string(dnode, "../name"), yang_dnode_get_string(dnode, NULL)); } diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 9e46e961ae..e823c150fa 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -724,9 +724,9 @@ static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args) } /* - * XPath: /frr-filter:lib/prefix-list/description + * XPath: /frr-filter:lib/prefix-list/remark */ -static int lib_prefix_list_description_modify(struct nb_cb_modify_args *args) +static int lib_prefix_list_remark_modify(struct nb_cb_modify_args *args) { struct prefix_list *pl; const char *remark; @@ -744,7 +744,7 @@ static int lib_prefix_list_description_modify(struct nb_cb_modify_args *args) return NB_OK; } -static int lib_prefix_list_description_destroy(struct nb_cb_destroy_args *args) +static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args) { struct prefix_list *pl; @@ -778,7 +778,7 @@ static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) ple = prefix_list_entry_new(); ple->pl = pl; ple->any = 1; - ple->seq = yang_dnode_get_int64(args->dnode, "./sequence"); + ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); return NB_OK; } @@ -808,7 +808,7 @@ static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); - action_str = yang_dnode_get_string(args->dnode, "./action"); + action_str = yang_dnode_get_string(args->dnode, NULL); if (strcmp(action_str, "permit") == 0) ple->type = PREFIX_PERMIT; else @@ -1145,10 +1145,10 @@ const struct frr_yang_module_info frr_filter_info = { } }, { - .xpath = "/frr-filter:lib/prefix-list/description", + .xpath = "/frr-filter:lib/prefix-list/remark", .cbs = { - .modify = lib_prefix_list_description_modify, - .destroy = lib_prefix_list_description_destroy, + .modify = lib_prefix_list_remark_modify, + .destroy = lib_prefix_list_remark_destroy, .cli_show = prefix_list_remark_show, } }, diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang index 9ae8de496b..78db201ea1 100644 --- a/yang/frr-filter.yang +++ b/yang/frr-filter.yang @@ -299,7 +299,7 @@ module frr-filter { type access-list-name; } - leaf description { + leaf remark { description "Prefix list user description"; type string; } From 4362a7681debd81c18c7f2921f76caaec41fcd4b Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 Apr 2020 17:53:11 -0300 Subject: [PATCH 15/31] lib: fix prefix list mask length check Implement the restriction from the old CLI to northbound. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index e823c150fa..46ea71aeca 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -39,6 +39,65 @@ ipv4_network_addr(in_addr_t hostaddr, int masklen) return hostaddr & mask.s_addr; } +static enum nb_error +prefix_list_length_validate(const struct lyd_node *dnode) +{ + int type = yang_dnode_get_enum(dnode, "../../type"); + const char *xpath_le = NULL, *xpath_ge = NULL; + struct prefix p; + uint8_t le, ge; + + if (type == 0 /* ipv4 */) { + yang_dnode_get_prefix(&p, dnode, "../ipv4-prefix"); + xpath_le = "../ipv4-prefix-length-lesser-or-equal"; + xpath_ge = "../ipv4-prefix-length-greater-or-equal"; + } else { + yang_dnode_get_prefix(&p, dnode, "../ipv6-prefix"); + xpath_le = "../ipv6-prefix-length-lesser-or-equal"; + xpath_ge = "../ipv6-prefix-length-greater-or-equal"; + } + + /* + * Check rule: + * prefix length <= le. + */ + if (yang_dnode_exists(dnode, xpath_le)) { + le = yang_dnode_get_uint8(dnode, xpath_le); + if (p.prefixlen > le) + goto log_and_fail; + + } + + /* + * Check rule: + * prefix length < ge. + */ + if (yang_dnode_exists(dnode, xpath_ge)) { + ge = yang_dnode_get_uint8(dnode, xpath_ge); + if (p.prefixlen >= ge) + goto log_and_fail; + } + + /* + * Check rule: + * ge <= le. + */ + if (yang_dnode_exists(dnode, xpath_le) && + yang_dnode_exists(dnode, xpath_ge)) { + le = yang_dnode_get_uint8(dnode, xpath_le); + ge = yang_dnode_get_uint8(dnode, xpath_ge); + if (ge > le) + goto log_and_fail; + } + + return NB_OK; + + log_and_fail: + zlog_info("prefix-list: invalid prefix range for %pFX: " + "Make sure that mask length < ge <= le", &p); + return NB_ERR_VALIDATION; +} + /* * XPath: /frr-filter:lib/access-list-legacy */ @@ -857,6 +916,10 @@ static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( { struct prefix_list_entry *ple; + if (args->event == NB_EV_VALIDATE && + prefix_list_length_validate(args->dnode) != NB_OK) + return NB_ERR_VALIDATION; + if (args->event != NB_EV_APPLY) return NB_OK; @@ -888,6 +951,10 @@ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( { struct prefix_list_entry *ple; + if (args->event == NB_EV_VALIDATE && + prefix_list_length_validate(args->dnode) != NB_OK) + return NB_ERR_VALIDATION; + if (args->event != NB_EV_APPLY) return NB_OK; From 1d7b156e7eea7dfeffd0176bf4dbd11755107e96 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 Apr 2020 18:21:12 -0300 Subject: [PATCH 16/31] lib: bump filter CLI XPath buffers size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump the size of the buffers so the new compilers don't complain about possible truncation: ``` lib/filter_cli.c: In function ‘ipv6_prefix_list_magic.isra.0’: lib/filter_cli.c:1336:5: error: ‘%lld’ directive output may be truncated writing between 1 and 20 bytes into a region of size between 16 and 527 [-Werror=format-truncation=] 1336 | "%s/entry[sequence='%" PRId64 "']", xpath, sseq); | ^~~~~~~~~~~~~~~~~~~~~~ lib/filter_cli.c:1336:25: note: format string is defined here 1336 | "%s/entry[sequence='%" PRId64 "']", xpath, sseq); lib/filter_cli.c:1336:5: note: directive argument in the range [-9223372036854775803, 9223372036854775807] 1336 | "%s/entry[sequence='%" PRId64 "']", xpath, sseq); | ^~~~~~~~~~~~~~~~~~~~~~ ``` Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index fd68bb59ec..860c155afe 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -186,8 +186,8 @@ DEFPY( int64_t sseq; char ipmask[64]; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -315,8 +315,8 @@ DEFPY( int64_t sseq; char ipmask[64]; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -588,8 +588,8 @@ DEFPY( int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -767,8 +767,8 @@ DEFPY( int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -949,8 +949,8 @@ DEFPY( int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 64]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -1258,8 +1258,8 @@ DEFPY( int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 128]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the prefix-list first, so we can generate sequence if @@ -1438,8 +1438,8 @@ DEFPY( int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - char xpath_value[XPATH_MAXLEN + 128]; + char xpath_entry[XPATH_MAXLEN + 128]; + char xpath_value[XPATH_MAXLEN + 256]; /* * Create the prefix-list first, so we can generate sequence if From c7d3de9ff2e3c2741356825f72ff0ed3215e3a95 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 10:06:14 -0300 Subject: [PATCH 17/31] lib: add 'no ... remark LINE' commands Implement the commands `no ... remark LINE` for cisco and zebra style access lists to match `ipX prefix-list description LINE` command set. It useful when you just want to go through the command history and prepend a `no` to a `remark` or `description` command. Example: ``` access-list foo remark just another acl ! ! ... ! ! Suddenly we decide we no longer think that remark is useful, ! lets press up key to find that line in history and append `no`: no access-list foo remark just another acl ``` Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 860c155afe..78553c50a2 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -563,6 +563,15 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +ALIAS( + no_access_list_legacy_remark, no_access_list_legacy_remark_line_cmd, + "no access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)>$number remark LINE...", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_XLEG_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + void access_list_legacy_remark_show(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { @@ -752,6 +761,15 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +ALIAS( + no_access_list_remark, no_access_list_remark_line_cmd, + "no access-list WORD$name remark LINE...", + NO_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + DEFPY( ipv6_access_list, ipv6_access_list_cmd, "ipv6 access-list WORD$name [seq (1-4294967295)$seq] $action ", @@ -935,6 +953,16 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +ALIAS( + no_ipv6_access_list_remark, no_ipv6_access_list_remark_line_cmd, + "no ipv6 access-list WORD$name remark LINE...", + NO_STR + IPV6_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + DEFPY( mac_access_list, mac_access_list_cmd, "mac access-list WORD$name [seq (1-4294967295)$seq] $action ", @@ -1111,6 +1139,16 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +ALIAS( + no_mac_access_list_remark, no_mac_access_list_remark_line_cmd, + "no mac access-list WORD$name remark LINE...", + NO_STR + MAC_STR + ACCESS_LIST_STR + ACCESS_LIST_ZEBRA_STR + ACCESS_LIST_REMARK_STR + ACCESS_LIST_REMARK_LINE_STR) + void access_list_show(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { @@ -1412,7 +1450,7 @@ DEFPY( ALIAS( no_ip_prefix_list_remark, no_ip_prefix_list_remark_line_cmd, - "no ip prefix-list WORD description LINE...", + "no ip prefix-list WORD$name description LINE...", NO_STR IP_STR PREFIX_LIST_STR @@ -1592,7 +1630,7 @@ DEFPY( ALIAS( no_ipv6_prefix_list_remark, no_ipv6_prefix_list_remark_line_cmd, - "no ipv6 prefix-list WORD description LINE...", + "no ipv6 prefix-list WORD$name description LINE...", NO_STR IPV6_STR PREFIX_LIST_STR @@ -1688,6 +1726,7 @@ void filter_cli_init(void) install_element(CONFIG_NODE, &no_access_list_legacy_cmd); install_element(CONFIG_NODE, &access_list_legacy_remark_cmd); install_element(CONFIG_NODE, &no_access_list_legacy_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_legacy_remark_line_cmd); /* access-list zebra-style. */ install_element(CONFIG_NODE, &access_list_cmd); @@ -1695,18 +1734,21 @@ void filter_cli_init(void) install_element(CONFIG_NODE, &no_access_list_all_cmd); install_element(CONFIG_NODE, &access_list_remark_cmd); install_element(CONFIG_NODE, &no_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_remark_line_cmd); install_element(CONFIG_NODE, &ipv6_access_list_cmd); install_element(CONFIG_NODE, &no_ipv6_access_list_cmd); install_element(CONFIG_NODE, &no_ipv6_access_list_all_cmd); install_element(CONFIG_NODE, &ipv6_access_list_remark_cmd); install_element(CONFIG_NODE, &no_ipv6_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_remark_line_cmd); install_element(CONFIG_NODE, &mac_access_list_cmd); install_element(CONFIG_NODE, &no_mac_access_list_cmd); install_element(CONFIG_NODE, &no_mac_access_list_all_cmd); install_element(CONFIG_NODE, &mac_access_list_remark_cmd); install_element(CONFIG_NODE, &no_mac_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_mac_access_list_remark_line_cmd); /* prefix lists. */ install_element(CONFIG_NODE, &ip_prefix_list_cmd); From 25ceb5d807d0062d5426dd11f72cf9c279173f74 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 10:10:16 -0300 Subject: [PATCH 18/31] lib: fix access list mac removal command Copy & paste mistake: MAC commands need `X:X:X:X:X:X` and not `X:X::X:X/M` types. Also, MAC access-list don't use `exact-match`. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 78553c50a2..af24d8752c 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -1020,7 +1020,7 @@ DEFPY( DEFPY( no_mac_access_list, no_mac_access_list_cmd, - "no mac access-list WORD$name [seq (1-4294967295)$seq] $action ", + "no mac access-list WORD$name [seq (1-4294967295)$seq] $action ", NO_STR MAC_STR ACCESS_LIST_STR @@ -1028,7 +1028,6 @@ DEFPY( ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "MAC address\n" - "Exact match of the prefixes\n" "Match any MAC address\n") { struct access_list *acl; @@ -1062,10 +1061,10 @@ DEFPY( if (prefix == NULL) { memset(&pany, 0, sizeof(pany)); pany.family = AF_ETHERNET; - sseq = acl_zebra_get_seq(acl, action, &pany, exact); + sseq = acl_zebra_get_seq(acl, action, &pany, false); } else sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix, - exact); + false); if (sseq == -1) return CMD_WARNING; From a7b2821884074b0e16a4de4588a8b27b6ae086be Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 10:34:03 -0300 Subject: [PATCH 19/31] lib: fix prefix list installation Based on the function `prefix_list_entry_add` and `prefix_list_entry_delete` it was created two functions to replicate its functionality without the assumption we are always alocating a new prefix list entry. Since the prefix list entry is stored in the YANG private data structures, we want to avoid the allocation/free of memory that is hold by the schema. Every time a prefix list entry values change we must call `prefix_list_entry_update_start` to uninstall the entry from prefix list internal structures and then call `prefix_list_entry_update_finish` to put them back. The variable `installed` in the prefix list entry tracks the installation status of the internal structure. It is possible that a user unconfigures or forgets to add a `prefix` value and so we can't install the entry until then. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++- lib/plist.c | 54 +++++++++++++++++++++++++++++++++++++- lib/plist_int.h | 7 +++++ 3 files changed, 128 insertions(+), 2 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 46ea71aeca..0f6e5488fc 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -838,6 +838,7 @@ static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) ple->pl = pl; ple->any = 1; ple->seq = yang_dnode_get_uint32(args->dnode, "./sequence"); + nb_running_set_entry(args->dnode, ple); return NB_OK; } @@ -850,7 +851,10 @@ static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args) return NB_OK; ple = nb_running_unset_entry(args->dnode); - prefix_list_entry_delete(ple->pl, ple, 1); + if (ple->installed) + prefix_list_entry_delete(ple->pl, ple, 0); + else + prefix_list_entry_free(ple); return NB_OK; } @@ -867,12 +871,19 @@ static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + action_str = yang_dnode_get_string(args->dnode, NULL); if (strcmp(action_str, "permit") == 0) ple->type = PREFIX_PERMIT; else ple->type = PREFIX_DENY; + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -888,8 +899,15 @@ lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL); + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -902,9 +920,16 @@ lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + 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); + return NB_OK; } @@ -924,8 +949,15 @@ static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + ple->ge = yang_dnode_get_uint8(args->dnode, NULL); + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -938,8 +970,15 @@ static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + ple->ge = 0; + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -959,8 +998,15 @@ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + ple->le = yang_dnode_get_uint8(args->dnode, NULL); + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -973,8 +1019,15 @@ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + prefix_list_entry_update_start(ple); + ple->le = 0; + /* Finish prefix entry update procedure. */ + prefix_list_entry_update_finish(ple); + return NB_OK; } @@ -1038,9 +1091,16 @@ static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + 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); + return NB_OK; } @@ -1052,9 +1112,16 @@ static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args) return NB_OK; ple = nb_running_get_entry(args->dnode, NULL, true); + + /* Start prefix entry update procedure. */ + 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); + return NB_OK; } diff --git a/lib/plist.c b/lib/plist.c index aa420da927..9567fde372 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -187,7 +187,7 @@ struct prefix_list_entry *prefix_list_entry_new(void) return new; } -static void prefix_list_entry_free(struct prefix_list_entry *pentry) +void prefix_list_entry_free(struct prefix_list_entry *pentry) { XFREE(MTYPE_PREFIX_LIST_ENTRY, pentry); } @@ -646,6 +646,58 @@ static void prefix_list_entry_add(struct prefix_list *plist, plist->master->recent = plist; } +/** + * Prefix list entry update start procedure: + * Remove entry from previosly installed tries and notify observers.. + * + * \param[in] ple prefix list entry. + */ +void prefix_list_entry_update_start(struct prefix_list_entry *ple) +{ + struct prefix_list *pl = ple->pl; + + /* Not installed, nothing to do. */ + if (!ple->installed) + return; + + prefix_list_trie_del(pl, ple); + route_map_notify_pentry_dependencies(pl->name, ple, + RMAP_EVENT_PLIST_DELETED); + pl->count--; + + ple->installed = false; +} + +/** + * Prefix list entry update finish procedure: + * Add entry back to trie, notify observers and call master hook. + * + * \param[in] ple prefix list entry. + */ +void prefix_list_entry_update_finish(struct prefix_list_entry *ple) +{ + struct prefix_list *pl = ple->pl; + + /* Already installed, nothing to do. */ + if (ple->installed) + return; + + prefix_list_trie_add(pl, ple); + pl->count++; + + route_map_notify_pentry_dependencies(pl->name, ple, + RMAP_EVENT_PLIST_ADDED); + + /* Run hook function. */ + if (pl->master->add_hook) + (*pl->master->add_hook)(pl); + + route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_ADDED); + pl->master->recent = pl; + + ple->installed = true; +} + /* Return string of prefix_list_type. */ static const char *prefix_list_type_str(struct prefix_list_entry *pentry) { diff --git a/lib/plist_int.h b/lib/plist_int.h index b180d18081..cef78a3ef7 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -72,8 +72,15 @@ struct prefix_list_entry { /* up the chain for best match search */ struct prefix_list_entry *next_best; + + /* Flag to track trie/list installation status. */ + bool installed; }; +extern void prefix_list_entry_free(struct prefix_list_entry *pentry); +extern void prefix_list_entry_update_start(struct prefix_list_entry *ple); +extern void prefix_list_entry_update_finish(struct prefix_list_entry *ple); + #ifdef __cplusplus } #endif From 744ad1afb4f889494fb809242ae08609f0b1db68 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 12:10:40 -0300 Subject: [PATCH 20/31] lib: properly apply prefix list entries After the commands started working I noticed that prefix lists were still not working and displaying incorrect information in `show ip prefix-list`. Turns out `any` must be set to `0` when a prefix is set and the prefix entry **must** be installed in the prefix list head. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 5 +++-- lib/plist.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 0f6e5488fc..54811ac245 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -409,8 +409,8 @@ static int lib_access_list_legacy_entry_destination_network_modify( f = nb_running_get_entry(args->dnode, NULL, true); fc = &f->u.cfilter; yang_dnode_get_prefix(&p, args->dnode, NULL); - fc->addr.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); - masklen2ip(p.prefixlen, &fc->addr_mask); + fc->mask.s_addr = ipv4_network_addr(p.u.prefix4.s_addr, p.prefixlen); + masklen2ip(p.prefixlen, &fc->mask_mask); return NB_OK; } @@ -904,6 +904,7 @@ 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); diff --git a/lib/plist.c b/lib/plist.c index 9567fde372..958d98dc96 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -648,7 +648,8 @@ static void prefix_list_entry_add(struct prefix_list *plist, /** * Prefix list entry update start procedure: - * Remove entry from previosly installed tries and notify observers.. + * Remove entry from previosly installed master list, tries and notify + * observers. * * \param[in] ple prefix list entry. */ @@ -660,6 +661,16 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple) if (!ple->installed) return; + /* List manipulation: shameless copy from `prefix_list_entry_delete`. */ + if (ple->prev) + ple->prev->next = ple->next; + else + pl->head = ple->next; + if (ple->next) + ple->next->prev = ple->prev; + else + pl->tail = ple->prev; + prefix_list_trie_del(pl, ple); route_map_notify_pentry_dependencies(pl->name, ple, RMAP_EVENT_PLIST_DELETED); @@ -670,18 +681,51 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple) /** * Prefix list entry update finish procedure: - * Add entry back to trie, notify observers and call master hook. + * Add entry back master list, to the trie, notify observers and call master + * hook. * * \param[in] ple prefix list entry. */ void prefix_list_entry_update_finish(struct prefix_list_entry *ple) { struct prefix_list *pl = ple->pl; + struct prefix_list_entry *point; /* Already installed, nothing to do. */ if (ple->installed) return; + /* List manipulation: shameless copy from `prefix_list_entry_add`. */ + if (pl->tail && ple->seq > pl->tail->seq) + point = NULL; + else { + /* Check insert point. */ + for (point = pl->head; point; point = point->next) + if (point->seq >= ple->seq) + break; + } + + /* In case of this is the first element of the list. */ + ple->next = point; + + if (point) { + if (point->prev) + point->prev->next = ple; + else + pl->head = ple; + + ple->prev = point->prev; + point->prev = ple; + } else { + if (pl->tail) + pl->tail->next = ple; + else + pl->head = ple; + + ple->prev = pl->tail; + pl->tail = ple; + } + prefix_list_trie_add(pl, ple); pl->count++; From 88b8bfdc8af8e9ea45d8b7149efd9fcc8fc2e95f Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 11:45:45 -0300 Subject: [PATCH 21/31] lib: fix two filter cli problems - Show the correct cisco style access list extended information. - `assert` action so static analyzer doesn't complain about possible NULL usage. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index af24d8752c..b3d038bec3 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -505,14 +505,16 @@ void access_list_legacy_show(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " any"); if (extended) { - if (yang_dnode_exists(dnode, "./network")) { - yang_dnode_get_prefix(&p, dnode, "./network"); + if (yang_dnode_exists(dnode, "./destination-network")) { + yang_dnode_get_prefix(&p, dnode, + "./destination-network"); masklen2ip(p.prefixlen, &mask); vty_out(vty, " %pI4 %pI4", &p.u.prefix4, &mask); - } else if (yang_dnode_exists(dnode, "./host")) + } else if (yang_dnode_exists(dnode, "./destination-host")) vty_out(vty, " host %s", - yang_dnode_get_string(dnode, "./host")); - else if (yang_dnode_exists(dnode, "./any")) + yang_dnode_get_string(dnode, + "./destination-host")); + else if (yang_dnode_exists(dnode, "./destination-any")) vty_out(vty, " any"); } @@ -1259,6 +1261,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, return CMD_WARNING; /* Use access-list data structure to fetch sequence. */ + assert(action != NULL); if (strcmp(action, "permit") == 0) plt = PREFIX_PERMIT; else From 81b504228564980bf4dcc7ad4808e2833012c35e Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 1 May 2020 22:14:00 -0300 Subject: [PATCH 22/31] 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 --- lib/filter_nb.c | 41 ++++++++++++++++++++++++++++++++++------- lib/plist.c | 33 ++++++++++++++++++++++++++++++++- lib/plist_int.h | 1 + 3 files changed, 67 insertions(+), 8 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); 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) { diff --git a/lib/plist_int.h b/lib/plist_int.h index cef78a3ef7..5e0beabbc6 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -78,6 +78,7 @@ struct prefix_list_entry { }; extern void prefix_list_entry_free(struct prefix_list_entry *pentry); +extern void prefix_list_entry_delete2(struct prefix_list_entry *ple); extern void prefix_list_entry_update_start(struct prefix_list_entry *ple); extern void prefix_list_entry_update_finish(struct prefix_list_entry *ple); From cf4472c4f733496a12f2e73b3b89f38af723aa0d Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 4 May 2020 17:32:06 -0300 Subject: [PATCH 23/31] lib: implement additional CLI prefix list check Changes: - Move the `TODO` to the appropriated place and hint how to resolve it. - Apply mask to prefix when storing it in the data structures. We can't just add a validation for it otherwise it will break old CLIs. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 9df37d7ccc..f2f334d9f4 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -761,8 +761,6 @@ static int lib_prefix_list_create(struct nb_cb_create_args *args) const char *name; int type; - /* TODO: validate prefix_entry_dup_check() passes. */ - if (args->event != NB_EV_APPLY) return NB_OK; @@ -907,6 +905,20 @@ static int lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; + struct prefix p; + + if (args->event == NB_EV_VALIDATE) { + /* + * TODO: validate prefix_entry_dup_check() passes. + * + * This needs to be implemented using YANG lyd_node + * navigation, because the `priv` data structures are not + * available at `NB_EV_VALIDATE` phase. An easier + * alternative would be mark `ipvx-prefix` as unique + * (see RFC 7950, Section 7.8.3. The list "unique" Statement). + */ + return NB_OK; + } if (args->event != NB_EV_APPLY) return NB_OK; @@ -918,6 +930,16 @@ lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args) yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL); + /* Apply mask and correct original address if necessary. */ + prefix_copy(&p, &ple->prefix); + apply_mask(&p); + if (!prefix_same(&ple->prefix, &p)) { + zlog_info("%s: bad network %pFX correcting it to %pFX", + __func__, &ple->prefix, &p); + prefix_copy(&ple->prefix, &p); + } + + /* Finish prefix entry update procedure. */ prefix_list_entry_update_finish(ple); From 019f8325a5ae3c5f698b5141d072878e828d323c Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 4 May 2020 17:34:07 -0300 Subject: [PATCH 24/31] lib: implement legacy prefix list behaviour Some tests expect that a prefix list structure is gone after all its entries are removed, so lets keep that behaviour. NOTE: users using YANG/northbound directly without CLI won't be affected. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index b3d038bec3..a7d6b7b6e4 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -1230,6 +1230,39 @@ void access_list_remark_show(struct vty *vty, struct lyd_node *dnode, /* * Prefix lists. */ + +/** + * Remove main data structure prefix list if there are no more entries or + * remark. This fixes compatibility with old CLI and tests. + */ +static int plist_remove_if_empty(struct vty *vty, const char *iptype, + const char *name) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='%s'][name='%s']/remark", + iptype, name); + /* List is not empty if there is a remark, check that: */ + if (yang_dnode_exists(vty->candidate_config->dnode, xpath)) + return CMD_SUCCESS; + + /* Check if we have any entries: */ + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype, + name); + /* + * NOTE: if the list is empty it will return the first sequence + * number: 5. + */ + if (acl_get_seq(vty, xpath) != 5) + return CMD_SUCCESS; + + /* Nobody is using this list, lets remove it. */ + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); +} + static int plist_remove(struct vty *vty, const char *iptype, const char *name, const char *seq, const char *action, struct prefix *p, long ge, long le) @@ -1240,6 +1273,7 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, struct lyd_node *dnode; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 32]; + int rv; /* If the user provided sequence number, then just go for it. */ if (seq != NULL) { @@ -1248,7 +1282,12 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%s']", iptype, name, seq); nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - return nb_cli_apply_changes(vty, NULL); + + rv = nb_cli_apply_changes(vty, NULL); + if (rv == CMD_SUCCESS) + return plist_remove_if_empty(vty, iptype, name); + + return rv; } /* Otherwise, to keep compatibility, we need to figure it out. */ @@ -1277,7 +1316,11 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); - return nb_cli_apply_changes(vty, NULL); + rv = nb_cli_apply_changes(vty, NULL); + if (rv == CMD_SUCCESS) + return plist_remove_if_empty(vty, iptype, name); + + return rv; } DEFPY( From fb7f5aa8d6437458e6aa53fdd4298ffb8e435452 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 4 May 2020 18:56:56 -0300 Subject: [PATCH 25/31] *: integrate remaining daemons with filter Don't crash when trying to `show running-config` because of missing filter northbound integration. Signed-off-by: Rafael Zalamena --- babeld/babel_main.c | 1 + ldpd/ldpd.c | 1 + nhrpd/nhrp_main.c | 2 ++ pbrd/pbr_main.c | 1 + pimd/pim_main.c | 1 + sharpd/sharp_main.c | 1 + vrrpd/vrrp_main.c | 1 + 7 files changed, 8 insertions(+) diff --git a/babeld/babel_main.c b/babeld/babel_main.c index e7ba29ed06..14e583a35c 100644 --- a/babeld/babel_main.c +++ b/babeld/babel_main.c @@ -137,6 +137,7 @@ struct option longopts[] = }; static const struct frr_yang_module_info *const babeld_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_vrf_info, }; diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index c6126b9396..56734a4f76 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -180,6 +180,7 @@ static struct quagga_signal_t ldp_signals[] = }; static const struct frr_yang_module_info *const ldpd_yang_modules[] = { + &frr_filter_info, &frr_vrf_info, }; diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index b58fe776ab..9fc13761c8 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -23,6 +23,7 @@ #include "memory.h" #include "command.h" #include "libfrr.h" +#include "filter.h" #include "nhrpd.h" #include "netlink.h" @@ -116,6 +117,7 @@ static struct quagga_signal_t sighandlers[] = { }; static const struct frr_yang_module_info *const nhrpd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, }; diff --git a/pbrd/pbr_main.c b/pbrd/pbr_main.c index b228847f06..57338738f6 100644 --- a/pbrd/pbr_main.c +++ b/pbrd/pbr_main.c @@ -113,6 +113,7 @@ struct quagga_signal_t pbr_signals[] = { #define PBR_VTY_PORT 2615 static const struct frr_yang_module_info *const pbrd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, }; diff --git a/pimd/pim_main.c b/pimd/pim_main.c index 5c4c7151a5..132d913f68 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -73,6 +73,7 @@ struct zebra_privs_t pimd_privs = { .cap_num_i = 0}; static const struct frr_yang_module_info *const pimd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c index 120d704918..db65836388 100644 --- a/sharpd/sharp_main.c +++ b/sharpd/sharp_main.c @@ -112,6 +112,7 @@ struct quagga_signal_t sharp_signals[] = { #define SHARP_VTY_PORT 2614 static const struct frr_yang_module_info *const sharpd_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_route_map_info, &frr_vrf_info, diff --git a/vrrpd/vrrp_main.c b/vrrpd/vrrp_main.c index 95b3cfad8f..d8c35dd2a3 100644 --- a/vrrpd/vrrp_main.c +++ b/vrrpd/vrrp_main.c @@ -111,6 +111,7 @@ struct quagga_signal_t vrrp_signals[] = { }; static const struct frr_yang_module_info *const vrrp_yang_modules[] = { + &frr_filter_info, &frr_interface_info, &frr_vrrpd_info, }; From be96651c937848aa4f8a1fae14090788becdbc11 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 15:05:34 -0300 Subject: [PATCH 26/31] lib: add YANG model enumerations for filter Avoid magic numbers by using enumerations. Signed-off-by: Rafael Zalamena --- lib/filter.h | 18 ++++++++++++++++++ lib/filter_cli.c | 20 ++++++++++---------- lib/filter_nb.c | 24 ++++++++++++------------ 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/lib/filter.h b/lib/filter.h index f4bd62e40d..76e992bf8e 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -148,6 +148,24 @@ struct filter *filter_lookup_zebra(struct access_list *access, extern const struct frr_yang_module_info frr_filter_info; + +/* filter_nb.c */ +enum yang_access_list_type { + YALT_IPV4 = 0, + YALT_IPV6 = 1, + YALT_MAC = 2, +}; + +enum yang_prefix_list_type { + YPLT_IPV4 = 0, + YPLT_IPV6 = 1, +}; + +enum yang_prefix_list_action { + YPLA_DENY = 0, + YPLA_PERMIT = 1, +}; + /* filter_cli.c */ struct lyd_node; struct vty; diff --git a/lib/filter_cli.c b/lib/filter_cli.c index a7d6b7b6e4..7800db6e0f 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -1161,14 +1161,14 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode, is_any = yang_dnode_exists(dnode, "./any"); switch (type) { - case 0: /* ipv4 */ + case YALT_IPV4: if (is_any) break; yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); is_exact = yang_dnode_get_bool(dnode, "./ipv4-exact-match"); break; - case 1: /* ipv6 */ + case YALT_IPV6: /* ipv6 */ vty_out(vty, "ipv6 "); if (is_any) break; @@ -1176,7 +1176,7 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_prefix(&p, dnode, "./ipv6-prefix"); is_exact = yang_dnode_get_bool(dnode, "./ipv6-exact-match"); break; - case 2: /* mac */ + case YALT_MAC: /* mac */ vty_out(vty, "mac "); if (is_any) break; @@ -1212,12 +1212,12 @@ void access_list_remark_show(struct vty *vty, struct lyd_node *dnode, int type = yang_dnode_get_enum(dnode, "../type"); switch (type) { - case 0: /* ipv4 */ + case YALT_IPV4: break; - case 1: /* ipv6 */ + case YALT_IPV6: vty_out(vty, "ipv6 "); break; - case 2: /* mac */ + case YALT_MAC: vty_out(vty, "mac "); break; } @@ -1693,7 +1693,7 @@ void prefix_list_show(struct vty *vty, struct lyd_node *dnode, is_any = yang_dnode_exists(dnode, "./any"); switch (type) { - case 0: /* ipv4 */ + case YPLT_IPV4: if (!is_any) yang_dnode_get_prefix(&p, dnode, "./ipv4-prefix"); if (yang_dnode_exists(dnode, @@ -1707,7 +1707,7 @@ void prefix_list_show(struct vty *vty, struct lyd_node *dnode, vty_out(vty, "ip "); break; - case 1: /* ipv6 */ + case YPLT_IPV6: if (!is_any) yang_dnode_get_prefix(&p, dnode, "ipv6-prefix"); if (yang_dnode_exists(dnode, @@ -1748,10 +1748,10 @@ void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode, int type = yang_dnode_get_enum(dnode, "../type"); switch (type) { - case 0: /* ipv4 */ + case YPLT_IPV4: vty_out(vty, "ip "); break; - case 1: /* ipv6 */ + case YPLT_IPV6: vty_out(vty, "ipv6 "); break; } diff --git a/lib/filter_nb.c b/lib/filter_nb.c index f2f334d9f4..1daefa8f10 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -47,7 +47,7 @@ prefix_list_length_validate(const struct lyd_node *dnode) struct prefix p; uint8_t le, ge; - if (type == 0 /* ipv4 */) { + if (type == YPLT_IPV4) { yang_dnode_get_prefix(&p, dnode, "../ipv4-prefix"); xpath_le = "../ipv4-prefix-length-lesser-or-equal"; xpath_ge = "../ipv4-prefix-length-greater-or-equal"; @@ -498,13 +498,13 @@ static int lib_access_list_create(struct nb_cb_create_args *args) acl_name = yang_dnode_get_string(args->dnode, "./name"); switch (type) { - case 0: /* ipv4 */ + case YALT_IPV4: acl = access_list_get(AFI_IP, acl_name); break; - case 1: /* ipv6 */ + case YALT_IPV6: acl = access_list_get(AFI_IP6, acl_name); break; - case 2: /* mac */ + case YALT_MAC: acl = access_list_get(AFI_L2VPN, acl_name); break; } @@ -723,13 +723,13 @@ static int lib_access_list_entry_any_create(struct nb_cb_create_args *args) type = yang_dnode_get_enum(args->dnode, "../../type"); switch (type) { - case 0: /* ipv4 */ + case YALT_IPV4: fz->prefix.family = AF_INET; break; - case 1: /* ipv6 */ + case YALT_IPV6: fz->prefix.family = AF_INET6; break; - case 2: /* mac */ + case YALT_MAC: fz->prefix.family = AF_ETHERNET; break; } @@ -876,7 +876,7 @@ static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args) static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) { struct prefix_list_entry *ple; - const char *action_str; + int action_type; if (args->event != NB_EV_APPLY) return NB_OK; @@ -886,8 +886,8 @@ static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args) /* Start prefix entry update procedure. */ prefix_list_entry_update_start(ple); - action_str = yang_dnode_get_string(args->dnode, NULL); - if (strcmp(action_str, "permit") == 0) + action_type = yang_dnode_get_enum(args->dnode, NULL); + if (action_type == YPLA_PERMIT) ple->type = PREFIX_PERMIT; else ple->type = PREFIX_DENY; @@ -1137,12 +1137,12 @@ static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args) type = yang_dnode_get_enum(args->dnode, "../../type"); switch (type) { - case 0: /* ipv4 */ + case YPLT_IPV4: ple->prefix.family = AF_INET; ple->ge = 0; ple->le = IPV4_MAX_BITLEN; break; - case 1: /* ipv6 */ + case YPLT_IPV6: ple->prefix.family = AF_INET6; ple->ge = 0; ple->le = IPV6_MAX_BITLEN; From 5ba66296f7f1ed86d7cdf84ae7d9d7ef4f5d37b1 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 15:06:31 -0300 Subject: [PATCH 27/31] lib: don't set NULL after an XFREE Avoid two assignment operations by just letting XFREE do its thing. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 1daefa8f10..e728eda4f6 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -180,8 +180,6 @@ lib_access_list_legacy_remark_destroy(struct nb_cb_destroy_args *args) if (acl->remark) XFREE(MTYPE_TMP, acl->remark); - acl->remark = NULL; - return NB_OK; } @@ -825,8 +823,6 @@ static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args) if (pl->desc) XFREE(MTYPE_TMP, pl->desc); - pl->desc = NULL; - return NB_OK; } From a247b2b738fb1c1b908a3e38557968da15194b20 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 15:07:47 -0300 Subject: [PATCH 28/31] lib: remove filter northbound wrapper functions Lets just use them directly to avoid extra code and to be extra clear that we are using those callbacks. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 143 +++++------------------------------------------- 1 file changed, 15 insertions(+), 128 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index e728eda4f6..1d9bfc7596 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -530,19 +530,6 @@ static int lib_access_list_destroy(struct nb_cb_destroy_args *args) return NB_OK; } -/* - * XPath: /frr-filter:lib/access-list/remark - */ -static int lib_access_list_remark_modify(struct nb_cb_modify_args *args) -{ - return lib_access_list_legacy_remark_modify(args); -} - -static int lib_access_list_remark_destroy(struct nb_cb_destroy_args *args) -{ - return lib_access_list_legacy_remark_destroy(args); -} - /* * XPath: /frr-filter:lib/access-list/entry */ @@ -582,14 +569,6 @@ static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args) return NB_OK; } -/* - * XPath: /frr-filter:lib/access-list/entry/action - */ -static int lib_access_list_entry_action_modify(struct nb_cb_modify_args *args) -{ - return lib_access_list_legacy_entry_action_modify(args); -} - /* * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix */ @@ -660,49 +639,6 @@ lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args) return NB_OK; } -/* - * XPath: /frr-filter:lib/access-list/entry/ipv6-prefix - */ -static int -lib_access_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args) -{ - return lib_access_list_entry_ipv4_prefix_modify(args); -} - -static int -lib_access_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args) -{ - return lib_access_list_entry_ipv4_prefix_destroy(args); -} - -/* - * XPath: /frr-filter:lib/access-list/entry/ipv6-exact-match - */ -static int -lib_access_list_entry_ipv6_exact_match_modify(struct nb_cb_modify_args *args) -{ - return lib_access_list_entry_ipv4_exact_match_modify(args); -} - -static int -lib_access_list_entry_ipv6_exact_match_destroy(struct nb_cb_destroy_args *args) -{ - return lib_access_list_entry_ipv4_exact_match_destroy(args); -} - -/* - * XPath: /frr-filter:lib/access-list/entry/mac - */ -static int lib_access_list_entry_mac_modify(struct nb_cb_modify_args *args) -{ - return lib_access_list_entry_ipv4_prefix_modify(args); -} - -static int lib_access_list_entry_mac_destroy(struct nb_cb_destroy_args *args) -{ - return lib_access_list_entry_ipv4_prefix_destroy(args); -} - /* * XPath: /frr-filter:lib/access-list/entry/any */ @@ -1061,55 +997,6 @@ static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( return NB_OK; } -/* - * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix - */ -static int -lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_modify(args); -} - -static int -lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_destroy(args); -} - -/* - * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal - */ -static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify( - struct nb_cb_modify_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify( - args); -} - -static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy( - struct nb_cb_destroy_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy( - args); -} - -/* - * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal - */ -static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify( - struct nb_cb_modify_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify( - args); -} - -static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy( - struct nb_cb_destroy_args *args) -{ - return lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy( - args); -} - /* * XPath: /frr-filter:lib/prefix-list/entry/any */ @@ -1256,8 +1143,8 @@ const struct frr_yang_module_info frr_filter_info = { { .xpath = "/frr-filter:lib/access-list/remark", .cbs = { - .modify = lib_access_list_remark_modify, - .destroy = lib_access_list_remark_destroy, + .modify = lib_access_list_legacy_remark_modify, + .destroy = lib_access_list_legacy_remark_destroy, .cli_show = access_list_remark_show, } }, @@ -1272,7 +1159,7 @@ const struct frr_yang_module_info frr_filter_info = { { .xpath = "/frr-filter:lib/access-list/entry/action", .cbs = { - .modify = lib_access_list_entry_action_modify, + .modify = lib_access_list_legacy_entry_action_modify, } }, { @@ -1292,22 +1179,22 @@ const struct frr_yang_module_info frr_filter_info = { { .xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix", .cbs = { - .modify = lib_access_list_entry_ipv6_prefix_modify, - .destroy = lib_access_list_entry_ipv6_prefix_destroy, + .modify = lib_access_list_entry_ipv4_prefix_modify, + .destroy = lib_access_list_entry_ipv4_prefix_destroy, } }, { .xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match", .cbs = { - .modify = lib_access_list_entry_ipv6_exact_match_modify, - .destroy = lib_access_list_entry_ipv6_exact_match_destroy, + .modify = lib_access_list_entry_ipv4_exact_match_modify, + .destroy = lib_access_list_entry_ipv4_exact_match_destroy, } }, { .xpath = "/frr-filter:lib/access-list/entry/mac", .cbs = { - .modify = lib_access_list_entry_mac_modify, - .destroy = lib_access_list_entry_mac_destroy, + .modify = lib_access_list_entry_ipv4_prefix_modify, + .destroy = lib_access_list_entry_ipv4_prefix_destroy, } }, { @@ -1370,22 +1257,22 @@ const struct frr_yang_module_info frr_filter_info = { { .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix", .cbs = { - .modify = lib_prefix_list_entry_ipv6_prefix_modify, - .destroy = lib_prefix_list_entry_ipv6_prefix_destroy, + .modify = lib_prefix_list_entry_ipv4_prefix_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_destroy, } }, { .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal", .cbs = { - .modify = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify, - .destroy = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy, + .modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy, } }, { .xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal", .cbs = { - .modify = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify, - .destroy = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy, + .modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify, + .destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy, } }, { From 664ae7953a3b4395edbeb00b15f89612a9c32b29 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 15:11:03 -0300 Subject: [PATCH 29/31] lib: filter remove unused variable Remove variable that is not being used. Signed-off-by: Rafael Zalamena --- lib/filter_nb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 1d9bfc7596..83cf586ed3 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -769,13 +769,10 @@ static int lib_prefix_list_entry_create(struct nb_cb_create_args *args) { struct prefix_list_entry *ple; struct prefix_list *pl; - struct prefix p; if (args->event != NB_EV_APPLY) return NB_OK; - memset(&p, 0, sizeof(p)); - pl = nb_running_get_entry(args->dnode, NULL, true); ple = prefix_list_entry_new(); ple->pl = pl; From 84fdeb2015ffcf56c18c91217ab08f00e51e0114 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 15:31:34 -0300 Subject: [PATCH 30/31] lib: filter remove extra CLI transaction `acl_get_seq` should be able to get the sequence number from candidate configuration without needing to commit anything midway. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 7800db6e0f..b2cf6532ef 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -182,7 +182,6 @@ DEFPY( "Wildcard bits\n" "Any source host\n") { - int rv; int64_t sseq; char ipmask[64]; char xpath[XPATH_MAXLEN]; @@ -196,10 +195,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list-legacy[number='%s']", number_str); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -311,7 +306,6 @@ DEFPY( "Destination address to match\n" "Any destination host\n") { - int rv; int64_t sseq; char ipmask[64]; char xpath[XPATH_MAXLEN]; @@ -325,10 +319,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list-legacy[number='%s']", number_str); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -596,7 +586,6 @@ DEFPY( "Exact match of the prefixes\n" "Match any IPv4\n") { - int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; @@ -609,10 +598,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -784,7 +769,6 @@ DEFPY( "Exact match of the prefixes\n" "Match any IPv6\n") { - int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; @@ -797,10 +781,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -976,7 +956,6 @@ DEFPY( "MAC address\n" "Match any MAC address\n") { - int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; @@ -989,10 +968,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='mac'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -1338,7 +1313,6 @@ DEFPY( "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; @@ -1351,10 +1325,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); @@ -1518,7 +1488,6 @@ DEFPY( "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - int rv; int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; @@ -1531,10 +1500,6 @@ DEFPY( snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - rv = nb_cli_apply_changes(vty, NULL); - if (rv != CMD_SUCCESS) - return rv; - if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ sseq = acl_get_seq(vty, xpath); From 49e3e49d72b0b9631ffe8c58100ae94f5dd08762 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 5 Jun 2020 16:40:16 -0300 Subject: [PATCH 31/31] lib: use relative XPath to filter entry attributes We can avoid a big amount of `snprintf` by using relative XPath in `nb_cli_apply_changes`. Signed-off-by: Rafael Zalamena --- lib/filter_cli.c | 218 ++++++++++++++--------------------------------- 1 file changed, 66 insertions(+), 152 deletions(-) diff --git a/lib/filter_cli.c b/lib/filter_cli.c index b2cf6532ef..0091d8b03f 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -186,7 +186,6 @@ DEFPY( char ipmask[64]; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -206,25 +205,17 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (host_str != NULL && mask_str == NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/host", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, host_str); + nb_cli_enqueue_change(vty, "./host", NB_OP_MODIFY, host_str); } else if (host_str != NULL && mask_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/network", - xpath_entry); concat_addr_mask_v4(host_str, mask_str, ipmask, sizeof(ipmask)); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + nb_cli_enqueue_change(vty, "./network", NB_OP_MODIFY, ipmask); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -310,7 +301,6 @@ DEFPY( char ipmask[64]; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -330,42 +320,31 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (src_str != NULL && src_mask_str == NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/host", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, src_str); + nb_cli_enqueue_change(vty, "./host", NB_OP_MODIFY, src_str); } else if (src_str != NULL && src_mask_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/network", - xpath_entry); concat_addr_mask_v4(src_str, src_mask_str, ipmask, sizeof(ipmask)); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + nb_cli_enqueue_change(vty, "./network", NB_OP_MODIFY, ipmask); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } if (dst_str != NULL && dst_mask_str == NULL) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/destination-host", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, src_str); + nb_cli_enqueue_change(vty, "./destination-host", NB_OP_MODIFY, + src_str); } else if (dst_str != NULL && dst_mask_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/destination-network", xpath_entry); concat_addr_mask_v4(dst_str, dst_mask_str, ipmask, sizeof(ipmask)); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ipmask); + nb_cli_enqueue_change(vty, "./destination-network", + NB_OP_MODIFY, ipmask); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/destination-any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./destination-any", NB_OP_CREATE, + NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -522,16 +501,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list-legacy[number='%s']", number_str); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 3); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv; @@ -589,7 +566,6 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -609,26 +585,17 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (prefix_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/ipv4-prefix", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv4-prefix", NB_OP_MODIFY, prefix_str); - - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv4-exact-match", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv4-exact-match", NB_OP_MODIFY, exact ? "true" : "false"); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -715,16 +682,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 3); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv; @@ -772,7 +737,6 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -792,26 +756,17 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (prefix_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/ipv6-prefix", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv6-prefix", NB_OP_MODIFY, prefix_str); - - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv6-exact-match", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv6-exact-match", NB_OP_MODIFY, exact ? "true" : "false"); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -901,16 +856,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 4); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv; @@ -959,7 +912,6 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the access-list first, so we can generate sequence if @@ -979,20 +931,14 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (mac_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/mac", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, mac_str); + nb_cli_enqueue_change(vty, "./mac", NB_OP_MODIFY, mac_str); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -1081,16 +1027,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='mac'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 4); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv; @@ -1316,7 +1260,6 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the prefix-list first, so we can generate sequence if @@ -1336,36 +1279,24 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (prefix_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/ipv4-prefix", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv4-prefix", NB_OP_MODIFY, prefix_str); - if (ge_str) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv4-prefix-length-greater-or-equal", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - ge_str); - } - if (le_str) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv4-prefix-length-lesser-or-equal", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - le_str); - } + if (ge_str) + nb_cli_enqueue_change( + vty, "./ipv4-prefix-length-greater-or-equal", + NB_OP_MODIFY, ge_str); + if (le_str) + nb_cli_enqueue_change( + vty, "./ipv4-prefix-length-lesser-or-equal", + NB_OP_MODIFY, le_str); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -1429,16 +1360,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 4); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv; @@ -1491,7 +1420,6 @@ DEFPY( int64_t sseq; char xpath[XPATH_MAXLEN]; char xpath_entry[XPATH_MAXLEN + 128]; - char xpath_value[XPATH_MAXLEN + 256]; /* * Create the prefix-list first, so we can generate sequence if @@ -1511,36 +1439,24 @@ DEFPY( nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); - snprintf(xpath_value, sizeof(xpath_value), "%s/action", xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, action); - + nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); if (prefix_str != NULL) { - snprintf(xpath_value, sizeof(xpath_value), "%s/ipv6-prefix", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./ipv6-prefix", NB_OP_MODIFY, prefix_str); - if (ge_str) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv6-prefix-length-greater-or-equal", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - ge_str); - } - if (le_str) { - snprintf(xpath_value, sizeof(xpath_value), - "%s/ipv6-prefix-length-lesser-or-equal", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - le_str); - } + if (ge_str) + nb_cli_enqueue_change( + vty, "./ipv6-prefix-length-greater-or-equal", + NB_OP_MODIFY, ge_str); + if (le_str) + nb_cli_enqueue_change( + vty, "./ipv6-prefix-length-lesser-or-equal", + NB_OP_MODIFY, le_str); } else { - snprintf(xpath_value, sizeof(xpath_value), "%s/any", - xpath_entry); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL); } - return nb_cli_apply_changes(vty, NULL); + return nb_cli_apply_changes(vty, xpath_entry); } DEFPY( @@ -1604,16 +1520,14 @@ DEFPY( int rv; char *remark; char xpath[XPATH_MAXLEN]; - char xpath_remark[XPATH_MAXLEN + 32]; snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - snprintf(xpath_remark, sizeof(xpath_remark), "%s/remark", xpath); remark = argv_concat(argv, argc, 4); - nb_cli_enqueue_change(vty, xpath_remark, NB_OP_CREATE, remark); - rv = nb_cli_apply_changes(vty, NULL); + nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark); + rv = nb_cli_apply_changes(vty, xpath); XFREE(MTYPE_TMP, remark); return rv;