lib: migrate prefix-list to use northbound

Implement all northbound CLI commands for prefix lists.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2019-11-11 20:25:20 -03:00
parent e0caeadd48
commit 89b7c834a5
2 changed files with 441 additions and 516 deletions

View File

@ -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] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)$ge|le (0-32)$le}]>",
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 <network>/<length>, 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] <deny|permit>$action <any|A.B.C.D/M$prefix [{ge (0-32)|le (0-32)}]>",
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 <network>/<length>, 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)] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
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 <network>/<length>, 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] <deny|permit>$action <any|X:X::X:X/M$prefix [{ge (0-128)$ge|le (0-128)$le}]>",
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 <network>/<length>, 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);
}

View File

@ -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)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
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 <network>/<length>, 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)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
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 <network>/<length>, 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)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
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 <network>/<length>, 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)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
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 <network>/<length>, 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);