lib: add "json" option to "show ip[v6] access-list"

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2021-08-02 15:38:26 -03:00
parent b15e836067
commit 068ab9018b
2 changed files with 197 additions and 72 deletions

View File

@ -35,6 +35,18 @@ IP Access List
access-list filter permit 10.0.0.0/8 access-list filter permit 10.0.0.0/8
access-list filter seq 13 permit 10.0.0.0/7 access-list filter seq 13 permit 10.0.0.0/7
.. clicmd:: show <ip|ipv6> access-list [json]
Display all IPv4 or IPv6 access lists.
If the ``json`` option is specified, output is displayed in JSON format.
.. clicmd:: show <ip|ipv6> access-list WORD [json]
Display the specified IPv4 or IPv6 access list.
If the ``json`` option is specified, output is displayed in JSON format.
IP Prefix List IP Prefix List
============== ==============

View File

@ -30,6 +30,7 @@
#include "routemap.h" #include "routemap.h"
#include "libfrr.h" #include "libfrr.h"
#include "northbound_cli.h" #include "northbound_cli.h"
#include "json.h"
DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List"); DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List");
DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str"); DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str");
@ -443,71 +444,158 @@ void access_list_filter_add(struct access_list *access,
host A single host address host A single host address
*/ */
static void config_write_access_zebra(struct vty *, struct filter *); static void config_write_access_zebra(struct vty *, struct filter *,
static void config_write_access_cisco(struct vty *, struct filter *); json_object *);
static void config_write_access_cisco(struct vty *, struct filter *,
json_object *);
static const char *filter_type2str(struct filter *filter)
{
if (filter->cisco) {
if (filter->u.cfilter.extended)
return "Extended";
else
return "Standard";
} else
return "Zebra";
}
/* show access-list command. */ /* show access-list command. */
static int filter_show(struct vty *vty, const char *name, afi_t afi) static int filter_show(struct vty *vty, const char *name, afi_t afi,
bool use_json)
{ {
struct access_list *access; struct access_list *access;
struct access_master *master; struct access_master *master;
struct filter *mfilter; struct filter *mfilter;
struct filter_cisco *filter; struct filter_cisco *filter;
int write = 0; bool first;
json_object *json = NULL;
json_object *json_proto = NULL;
master = access_master_get(afi); master = access_master_get(afi);
if (master == NULL) if (master == NULL) {
if (use_json)
vty_out(vty, "{}\n");
return 0; return 0;
}
if (use_json)
json = json_object_new_object();
/* Print the name of the protocol */ /* Print the name of the protocol */
vty_out(vty, "%s:\n", frr_protoname); if (json) {
json_proto = json_object_new_object();
json_object_object_add(json, frr_protoname, json_proto);
} else
vty_out(vty, "%s:\n", frr_protoname);
for (access = master->str.head; access; access = access->next) { for (access = master->str.head; access; access = access->next) {
json_object *json_acl = NULL;
json_object *json_rules = NULL;
if (name && strcmp(access->name, name) != 0) if (name && strcmp(access->name, name) != 0)
continue; continue;
write = 1; first = true;
for (mfilter = access->head; mfilter; mfilter = mfilter->next) { for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
json_object *json_rule = NULL;
filter = &mfilter->u.cfilter; filter = &mfilter->u.cfilter;
if (write) { if (first) {
vty_out(vty, "%s %s access list %s\n", const char *type = filter_type2str(mfilter);
mfilter->cisco ? (filter->extended
? "Extended" if (json) {
: "Standard") json_acl = json_object_new_object();
: "Zebra", json_object_object_add(json_proto,
(afi == AFI_IP) access->name,
? ("IP") json_acl);
: ((afi == AFI_IP6) ? ("IPv6 ")
: ("MAC ")), json_object_string_add(json_acl, "type",
access->name); type);
write = 0; json_object_string_add(json_acl,
"addressFamily",
afi2str(afi));
json_rules = json_object_new_array();
json_object_object_add(
json_acl, "rules", json_rules);
} else {
vty_out(vty, "%s %s access list %s\n",
type,
(afi == AFI_IP)
? ("IP")
: ((afi == AFI_IP6)
? ("IPv6 ")
: ("MAC ")),
access->name);
}
first = false;
} }
vty_out(vty, " seq %" PRId64, mfilter->seq); if (json) {
vty_out(vty, " %s%s", filter_type_str(mfilter), json_rule = json_object_new_object();
mfilter->type == FILTER_DENY ? " " : ""); json_object_array_add(json_rules, json_rule);
json_object_int_add(json_rule, "sequenceNumber",
mfilter->seq);
json_object_string_add(
json_rule, "filterType",
filter_type_str(mfilter));
} else {
vty_out(vty, " seq %" PRId64, mfilter->seq);
vty_out(vty, " %s%s", filter_type_str(mfilter),
mfilter->type == FILTER_DENY ? " "
: "");
}
if (!mfilter->cisco) if (!mfilter->cisco)
config_write_access_zebra(vty, mfilter); config_write_access_zebra(vty, mfilter,
json_rule);
else if (filter->extended) else if (filter->extended)
config_write_access_cisco(vty, mfilter); config_write_access_cisco(vty, mfilter,
json_rule);
else { else {
if (filter->addr_mask.s_addr == 0xffffffff) if (json) {
vty_out(vty, " any\n"); char buf[BUFSIZ];
else {
vty_out(vty, " %pI4", &filter->addr); json_object_string_add(
json_rule, "address",
inet_ntop(AF_INET,
&filter->addr, buf,
sizeof(buf)));
json_object_string_add(
json_rule, "mask",
inet_ntop(AF_INET,
&filter->addr_mask,
buf, sizeof(buf)));
} else {
if (filter->addr_mask.s_addr if (filter->addr_mask.s_addr
!= INADDR_ANY) == 0xffffffff)
vty_out(vty, vty_out(vty, " any\n");
", wildcard bits %pI4", else {
&filter->addr_mask); vty_out(vty, " %pI4",
vty_out(vty, "\n"); &filter->addr);
if (filter->addr_mask.s_addr
!= INADDR_ANY)
vty_out(vty,
", wildcard bits %pI4",
&filter->addr_mask);
vty_out(vty, "\n");
}
} }
} }
} }
} }
if (json) {
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -519,7 +607,7 @@ DEFUN (show_mac_access_list,
"mac access lists\n" "mac access lists\n"
"List mac access lists\n") "List mac access lists\n")
{ {
return filter_show(vty, NULL, AFI_L2VPN); return filter_show(vty, NULL, AFI_L2VPN, false);
} }
DEFUN (show_mac_access_list_name, DEFUN (show_mac_access_list_name,
@ -530,22 +618,24 @@ DEFUN (show_mac_access_list_name,
"List mac access lists\n" "List mac access lists\n"
"mac address\n") "mac address\n")
{ {
return filter_show(vty, argv[3]->arg, AFI_L2VPN); return filter_show(vty, argv[3]->arg, AFI_L2VPN, false);
} }
DEFUN (show_ip_access_list, DEFUN (show_ip_access_list,
show_ip_access_list_cmd, show_ip_access_list_cmd,
"show ip access-list", "show ip access-list [json]",
SHOW_STR SHOW_STR
IP_STR IP_STR
"List IP access lists\n") "List IP access lists\n"
JSON_STR)
{ {
return filter_show(vty, NULL, AFI_IP); bool uj = use_json(argc, argv);
return filter_show(vty, NULL, AFI_IP, uj);
} }
DEFUN (show_ip_access_list_name, DEFUN (show_ip_access_list_name,
show_ip_access_list_name_cmd, show_ip_access_list_name_cmd,
"show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD>", "show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> [json]",
SHOW_STR SHOW_STR
IP_STR IP_STR
"List IP access lists\n" "List IP access lists\n"
@ -553,41 +643,64 @@ DEFUN (show_ip_access_list_name,
"IP extended access list\n" "IP extended access list\n"
"IP standard access list (expanded range)\n" "IP standard access list (expanded range)\n"
"IP extended access list (expanded range)\n" "IP extended access list (expanded range)\n"
"IP zebra access-list\n") "IP zebra access-list\n"
JSON_STR)
{ {
bool uj = use_json(argc, argv);
int idx_acl = 3; int idx_acl = 3;
return filter_show(vty, argv[idx_acl]->arg, AFI_IP); return filter_show(vty, argv[idx_acl]->arg, AFI_IP, uj);
} }
DEFUN (show_ipv6_access_list, DEFUN (show_ipv6_access_list,
show_ipv6_access_list_cmd, show_ipv6_access_list_cmd,
"show ipv6 access-list", "show ipv6 access-list [json]",
SHOW_STR SHOW_STR
IPV6_STR IPV6_STR
"List IPv6 access lists\n") "List IPv6 access lists\n"
JSON_STR)
{ {
return filter_show(vty, NULL, AFI_IP6); bool uj = use_json(argc, argv);
return filter_show(vty, NULL, AFI_IP6, uj);
} }
DEFUN (show_ipv6_access_list_name, DEFUN (show_ipv6_access_list_name,
show_ipv6_access_list_name_cmd, show_ipv6_access_list_name_cmd,
"show ipv6 access-list WORD", "show ipv6 access-list WORD [json]",
SHOW_STR SHOW_STR
IPV6_STR IPV6_STR
"List IPv6 access lists\n" "List IPv6 access lists\n"
"IPv6 zebra access-list\n") "IPv6 zebra access-list\n"
JSON_STR)
{ {
bool uj = use_json(argc, argv);
int idx_word = 3; int idx_word = 3;
return filter_show(vty, argv[idx_word]->arg, AFI_IP6); return filter_show(vty, argv[idx_word]->arg, AFI_IP6, uj);
} }
static void config_write_access_cisco(struct vty *vty, struct filter *mfilter) static void config_write_access_cisco(struct vty *vty, struct filter *mfilter,
json_object *json)
{ {
struct filter_cisco *filter; struct filter_cisco *filter;
filter = &mfilter->u.cfilter; filter = &mfilter->u.cfilter;
if (filter->extended) { if (json) {
char buf[BUFSIZ];
json_object_boolean_add(json, "extended", !!filter->extended);
json_object_string_add(
json, "sourceAddress",
inet_ntop(AF_INET, &filter->addr, buf, sizeof(buf)));
json_object_string_add(json, "sourceMask",
inet_ntop(AF_INET, &filter->addr_mask,
buf, sizeof(buf)));
json_object_string_add(
json, "destinationAddress",
inet_ntop(AF_INET, &filter->mask, buf, sizeof(buf)));
json_object_string_add(json, "destinationMask",
inet_ntop(AF_INET, &filter->mask_mask,
buf, sizeof(buf)));
} else {
vty_out(vty, " ip"); vty_out(vty, " ip");
if (filter->addr_mask.s_addr == 0xffffffff) if (filter->addr_mask.s_addr == 0xffffffff)
vty_out(vty, " any"); vty_out(vty, " any");
@ -607,19 +720,11 @@ static void config_write_access_cisco(struct vty *vty, struct filter *mfilter)
vty_out(vty, " %pI4", &filter->mask_mask); vty_out(vty, " %pI4", &filter->mask_mask);
} }
vty_out(vty, "\n"); vty_out(vty, "\n");
} else {
if (filter->addr_mask.s_addr == 0xffffffff)
vty_out(vty, " any\n");
else {
vty_out(vty, " %pI4", &filter->addr);
if (filter->addr_mask.s_addr != INADDR_ANY)
vty_out(vty, " %pI4", &filter->addr_mask);
vty_out(vty, "\n");
}
} }
} }
static void config_write_access_zebra(struct vty *vty, struct filter *mfilter) static void config_write_access_zebra(struct vty *vty, struct filter *mfilter,
json_object *json)
{ {
struct filter_zebra *filter; struct filter_zebra *filter;
struct prefix *p; struct prefix *p;
@ -628,21 +733,29 @@ static void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
filter = &mfilter->u.zfilter; filter = &mfilter->u.zfilter;
p = &filter->prefix; p = &filter->prefix;
if (p->prefixlen == 0 && !filter->exact) if (json) {
vty_out(vty, " any"); json_object_string_add(json, "prefix",
else if (p->family == AF_INET6 || p->family == AF_INET) prefix2str(p, buf, sizeof(buf)));
vty_out(vty, " %s/%d%s", json_object_boolean_add(json, "exact-match", !!filter->exact);
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), } else {
p->prefixlen, filter->exact ? " exact-match" : ""); if (p->prefixlen == 0 && !filter->exact)
else if (p->family == AF_ETHERNET) {
if (p->prefixlen == 0)
vty_out(vty, " any"); vty_out(vty, " any");
else else if (p->family == AF_INET6 || p->family == AF_INET)
vty_out(vty, " %s", prefix_mac2str(&(p->u.prefix_eth), vty_out(vty, " %s/%d%s",
buf, sizeof(buf))); inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
} p->prefixlen,
filter->exact ? " exact-match" : "");
else if (p->family == AF_ETHERNET) {
if (p->prefixlen == 0)
vty_out(vty, " any");
else
vty_out(vty, " %s",
prefix_mac2str(&(p->u.prefix_eth), buf,
sizeof(buf)));
}
vty_out(vty, "\n"); vty_out(vty, "\n");
}
} }
static struct cmd_node access_mac_node = { static struct cmd_node access_mac_node = {