mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-20 02:45:22 +00:00

The specific code here needs to establish an absolute order of more specific to less specific possible matches in a prefix list. This is indirectly checked by an assert on insertion, because the "next best" entry is required to be consistent even when joining multiple chains of candidates. Unfortunately, trie_install_fn() would insert entries too far ahead in the chain if another entry with higher sequence number was seen. This breaks the trie and (rightfully) triggers the assertion failure on insert. Fixes: #937 Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
3252 lines
89 KiB
C
3252 lines
89 KiB
C
/* Prefix list functions.
|
|
* Copyright (C) 1999 Kunihiro Ishiguro
|
|
*
|
|
* This file is part of GNU Zebra.
|
|
*
|
|
* GNU Zebra 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, or (at your
|
|
* option) any later version.
|
|
*
|
|
* GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "prefix.h"
|
|
#include "command.h"
|
|
#include "memory.h"
|
|
#include "plist.h"
|
|
#include "sockunion.h"
|
|
#include "buffer.h"
|
|
#include "log.h"
|
|
#include "routemap.h"
|
|
#include "lib/json.h"
|
|
|
|
#include "plist_int.h"
|
|
|
|
DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST, "Prefix List")
|
|
DEFINE_MTYPE_STATIC(LIB, MPREFIX_LIST_STR, "Prefix List Str")
|
|
DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_ENTRY, "Prefix List Entry")
|
|
DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_TRIE, "Prefix List Trie Table")
|
|
|
|
/* not currently changeable, code assumes bytes further down */
|
|
#define PLC_BITS 8
|
|
#define PLC_LEN (1 << PLC_BITS)
|
|
#define PLC_MAXLEVELV4 2 /* /24 for IPv4 */
|
|
#define PLC_MAXLEVELV6 4 /* /48 for IPv6 */
|
|
#define PLC_MAXLEVEL 4 /* max(v4,v6) */
|
|
|
|
struct pltrie_entry {
|
|
union {
|
|
struct pltrie_table *next_table;
|
|
struct prefix_list_entry *final_chain;
|
|
};
|
|
|
|
struct prefix_list_entry *up_chain;
|
|
};
|
|
|
|
struct pltrie_table {
|
|
struct pltrie_entry entries[PLC_LEN];
|
|
};
|
|
|
|
/* List of struct prefix_list. */
|
|
struct prefix_list_list {
|
|
struct prefix_list *head;
|
|
struct prefix_list *tail;
|
|
};
|
|
|
|
/* Master structure of prefix_list. */
|
|
struct prefix_master {
|
|
/* List of prefix_list which name is number. */
|
|
struct prefix_list_list num;
|
|
|
|
/* List of prefix_list which name is string. */
|
|
struct prefix_list_list str;
|
|
|
|
/* Whether sequential number is used. */
|
|
int seqnum;
|
|
|
|
/* The latest update. */
|
|
struct prefix_list *recent;
|
|
|
|
/* Hook function which is executed when new prefix_list is added. */
|
|
void (*add_hook)(struct prefix_list *);
|
|
|
|
/* Hook function which is executed when prefix_list is deleted. */
|
|
void (*delete_hook)(struct prefix_list *);
|
|
|
|
/* number of bytes that have a trie level */
|
|
size_t trie_depth;
|
|
};
|
|
|
|
/* Static structure of IPv4 prefix_list's master. */
|
|
static struct prefix_master prefix_master_ipv4 = {
|
|
{NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
|
|
};
|
|
|
|
/* Static structure of IPv6 prefix-list's master. */
|
|
static struct prefix_master prefix_master_ipv6 = {
|
|
{NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
|
|
};
|
|
|
|
/* Static structure of BGP ORF prefix_list's master. */
|
|
static struct prefix_master prefix_master_orf_v4 = {
|
|
{NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
|
|
};
|
|
|
|
/* Static structure of BGP ORF prefix_list's master. */
|
|
static struct prefix_master prefix_master_orf_v6 = {
|
|
{NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
|
|
};
|
|
|
|
static struct prefix_master *prefix_master_get(afi_t afi, int orf)
|
|
{
|
|
if (afi == AFI_IP)
|
|
return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4;
|
|
if (afi == AFI_IP6)
|
|
return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6;
|
|
return NULL;
|
|
}
|
|
|
|
const char *prefix_list_name(struct prefix_list *plist)
|
|
{
|
|
return plist->name;
|
|
}
|
|
|
|
/* Lookup prefix_list from list of prefix_list by name. */
|
|
static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
|
|
const char *name)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_master *master;
|
|
|
|
if (name == NULL)
|
|
return NULL;
|
|
|
|
master = prefix_master_get(afi, orf);
|
|
if (master == NULL)
|
|
return NULL;
|
|
|
|
for (plist = master->num.head; plist; plist = plist->next)
|
|
if (strcmp(plist->name, name) == 0)
|
|
return plist;
|
|
|
|
for (plist = master->str.head; plist; plist = plist->next)
|
|
if (strcmp(plist->name, name) == 0)
|
|
return plist;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct prefix_list *prefix_list_lookup(afi_t afi, const char *name)
|
|
{
|
|
return prefix_list_lookup_do(afi, 0, name);
|
|
}
|
|
|
|
struct prefix_list *prefix_bgp_orf_lookup(afi_t afi, const char *name)
|
|
{
|
|
return prefix_list_lookup_do(afi, 1, name);
|
|
}
|
|
|
|
static struct prefix_list *prefix_list_new(void)
|
|
{
|
|
struct prefix_list *new;
|
|
|
|
new = XCALLOC(MTYPE_PREFIX_LIST, sizeof(struct prefix_list));
|
|
return new;
|
|
}
|
|
|
|
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 *new;
|
|
|
|
new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY,
|
|
sizeof(struct prefix_list_entry));
|
|
return new;
|
|
}
|
|
|
|
static void prefix_list_entry_free(struct prefix_list_entry *pentry)
|
|
{
|
|
XFREE(MTYPE_PREFIX_LIST_ENTRY, pentry);
|
|
}
|
|
|
|
/* Insert new prefix list to list of prefix_list. Each prefix_list
|
|
is sorted by the name. */
|
|
static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
|
|
const char *name)
|
|
{
|
|
unsigned int i;
|
|
long number;
|
|
struct prefix_list *plist;
|
|
struct prefix_list *point;
|
|
struct prefix_list_list *list;
|
|
struct prefix_master *master;
|
|
|
|
master = prefix_master_get(afi, orf);
|
|
if (master == NULL)
|
|
return NULL;
|
|
|
|
/* Allocate new prefix_list and copy given name. */
|
|
plist = prefix_list_new();
|
|
plist->name = XSTRDUP(MTYPE_MPREFIX_LIST_STR, name);
|
|
plist->master = master;
|
|
plist->trie =
|
|
XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table));
|
|
|
|
/* If name is made by all digit character. We treat it as
|
|
number. */
|
|
for (number = 0, i = 0; i < strlen(name); i++) {
|
|
if (isdigit((int)name[i]))
|
|
number = (number * 10) + (name[i] - '0');
|
|
else
|
|
break;
|
|
}
|
|
|
|
/* In case of name is all digit character */
|
|
if (i == strlen(name)) {
|
|
plist->type = PREFIX_TYPE_NUMBER;
|
|
|
|
/* Set prefix_list to number list. */
|
|
list = &master->num;
|
|
|
|
for (point = list->head; point; point = point->next)
|
|
if (atol(point->name) >= number)
|
|
break;
|
|
} else {
|
|
plist->type = PREFIX_TYPE_STRING;
|
|
|
|
/* Set prefix_list to string list. */
|
|
list = &master->str;
|
|
|
|
/* Set point to insertion point. */
|
|
for (point = list->head; point; point = point->next)
|
|
if (strcmp(point->name, name) >= 0)
|
|
break;
|
|
}
|
|
|
|
/* In case of this is the first element of master. */
|
|
if (list->head == NULL) {
|
|
list->head = list->tail = plist;
|
|
return plist;
|
|
}
|
|
|
|
/* In case of insertion is made at the tail of access_list. */
|
|
if (point == NULL) {
|
|
plist->prev = list->tail;
|
|
list->tail->next = plist;
|
|
list->tail = plist;
|
|
return plist;
|
|
}
|
|
|
|
/* In case of insertion is made at the head of access_list. */
|
|
if (point == list->head) {
|
|
plist->next = list->head;
|
|
list->head->prev = plist;
|
|
list->head = plist;
|
|
return plist;
|
|
}
|
|
|
|
/* Insertion is made at middle of the access_list. */
|
|
plist->next = point;
|
|
plist->prev = point->prev;
|
|
|
|
if (point->prev)
|
|
point->prev->next = plist;
|
|
point->prev = plist;
|
|
|
|
return plist;
|
|
}
|
|
|
|
static struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name)
|
|
{
|
|
struct prefix_list *plist;
|
|
|
|
plist = prefix_list_lookup_do(afi, orf, name);
|
|
|
|
if (plist == NULL)
|
|
plist = prefix_list_insert(afi, orf, name);
|
|
return plist;
|
|
}
|
|
|
|
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)
|
|
{
|
|
struct prefix_list_list *list;
|
|
struct prefix_master *master;
|
|
struct prefix_list_entry *pentry;
|
|
struct prefix_list_entry *next;
|
|
|
|
/* If prefix-list contain prefix_list_entry free all of it. */
|
|
for (pentry = plist->head; pentry; pentry = next) {
|
|
next = pentry->next;
|
|
prefix_list_trie_del(plist, pentry);
|
|
prefix_list_entry_free(pentry);
|
|
plist->count--;
|
|
}
|
|
|
|
master = plist->master;
|
|
|
|
if (plist->type == PREFIX_TYPE_NUMBER)
|
|
list = &master->num;
|
|
else
|
|
list = &master->str;
|
|
|
|
if (plist->next)
|
|
plist->next->prev = plist->prev;
|
|
else
|
|
list->tail = plist->prev;
|
|
|
|
if (plist->prev)
|
|
plist->prev->next = plist->next;
|
|
else
|
|
list->head = plist->next;
|
|
|
|
if (plist->desc)
|
|
XFREE(MTYPE_TMP, plist->desc);
|
|
|
|
/* Make sure master's recent changed prefix-list information is
|
|
cleared. */
|
|
master->recent = NULL;
|
|
|
|
route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED);
|
|
|
|
if (master->delete_hook)
|
|
(*master->delete_hook)(plist);
|
|
|
|
if (plist->name)
|
|
XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
|
|
|
|
XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie);
|
|
|
|
prefix_list_free(plist);
|
|
}
|
|
|
|
static struct prefix_list_entry *
|
|
prefix_list_entry_make(struct prefix *prefix, enum prefix_list_type type,
|
|
int seq, int le, int ge, int any)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
pentry = prefix_list_entry_new();
|
|
|
|
if (any)
|
|
pentry->any = 1;
|
|
|
|
prefix_copy(&pentry->prefix, prefix);
|
|
pentry->type = type;
|
|
pentry->seq = seq;
|
|
pentry->le = le;
|
|
pentry->ge = ge;
|
|
|
|
return pentry;
|
|
}
|
|
|
|
/* Add hook function. */
|
|
void prefix_list_add_hook(void (*func)(struct prefix_list *plist))
|
|
{
|
|
prefix_master_ipv4.add_hook = func;
|
|
prefix_master_ipv6.add_hook = func;
|
|
}
|
|
|
|
/* Delete hook function. */
|
|
void prefix_list_delete_hook(void (*func)(struct prefix_list *plist))
|
|
{
|
|
prefix_master_ipv4.delete_hook = func;
|
|
prefix_master_ipv6.delete_hook = func;
|
|
}
|
|
|
|
/* Calculate new sequential number. */
|
|
static int prefix_new_seq_get(struct prefix_list *plist)
|
|
{
|
|
int maxseq;
|
|
int newseq;
|
|
struct prefix_list_entry *pentry;
|
|
|
|
maxseq = newseq = 0;
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
if (maxseq < pentry->seq)
|
|
maxseq = pentry->seq;
|
|
}
|
|
|
|
newseq = ((maxseq / 5) * 5) + 5;
|
|
|
|
return newseq;
|
|
}
|
|
|
|
/* Return prefix list entry which has same seq number. */
|
|
static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist,
|
|
int seq)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next)
|
|
if (pentry->seq == seq)
|
|
return pentry;
|
|
return NULL;
|
|
}
|
|
|
|
static struct prefix_list_entry *
|
|
prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix,
|
|
enum prefix_list_type type, int seq, int le, int ge)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next)
|
|
if (prefix_same(&pentry->prefix, prefix)
|
|
&& pentry->type == type) {
|
|
if (seq >= 0 && pentry->seq != seq)
|
|
continue;
|
|
|
|
if (pentry->le != le)
|
|
continue;
|
|
if (pentry->ge != ge)
|
|
continue;
|
|
|
|
return pentry;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void trie_walk_affected(size_t validbits, struct pltrie_table *table,
|
|
uint8_t byte, struct prefix_list_entry *object,
|
|
void (*fn)(struct prefix_list_entry *object,
|
|
struct prefix_list_entry **updptr))
|
|
{
|
|
uint8_t mask;
|
|
uint16_t bwalk;
|
|
|
|
if (validbits > PLC_BITS) {
|
|
fn(object, &table->entries[byte].final_chain);
|
|
return;
|
|
}
|
|
|
|
mask = (1 << (8 - validbits)) - 1;
|
|
for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) {
|
|
fn(object, &table->entries[bwalk].up_chain);
|
|
}
|
|
}
|
|
|
|
static void trie_uninstall_fn(struct prefix_list_entry *object,
|
|
struct prefix_list_entry **updptr)
|
|
{
|
|
for (; *updptr; updptr = &(*updptr)->next_best)
|
|
if (*updptr == object) {
|
|
*updptr = object->next_best;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int trie_table_empty(struct pltrie_table *table)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < PLC_LEN; i++)
|
|
if (table->entries[i].next_table || table->entries[i].up_chain)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static void prefix_list_trie_del(struct prefix_list *plist,
|
|
struct prefix_list_entry *pentry)
|
|
{
|
|
size_t depth, maxdepth = plist->master->trie_depth;
|
|
uint8_t *bytes = &pentry->prefix.u.prefix;
|
|
size_t validbits = pentry->prefix.prefixlen;
|
|
struct pltrie_table *table, **tables[PLC_MAXLEVEL];
|
|
|
|
table = plist->trie;
|
|
for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
|
|
uint8_t byte = bytes[depth];
|
|
assert(table->entries[byte].next_table);
|
|
|
|
tables[depth + 1] = &table->entries[byte].next_table;
|
|
table = table->entries[byte].next_table;
|
|
|
|
validbits -= PLC_BITS;
|
|
}
|
|
|
|
trie_walk_affected(validbits, table, bytes[depth], pentry,
|
|
trie_uninstall_fn);
|
|
|
|
for (; depth > 0; depth--)
|
|
if (trie_table_empty(*tables[depth])) {
|
|
XFREE(MTYPE_PREFIX_LIST_TRIE, *tables[depth]);
|
|
*tables[depth] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static void prefix_list_entry_delete(struct prefix_list *plist,
|
|
struct prefix_list_entry *pentry,
|
|
int update_list)
|
|
{
|
|
if (plist == NULL || pentry == NULL)
|
|
return;
|
|
|
|
prefix_list_trie_del(plist, pentry);
|
|
|
|
if (pentry->prev)
|
|
pentry->prev->next = pentry->next;
|
|
else
|
|
plist->head = pentry->next;
|
|
if (pentry->next)
|
|
pentry->next->prev = pentry->prev;
|
|
else
|
|
plist->tail = pentry->prev;
|
|
|
|
prefix_list_entry_free(pentry);
|
|
|
|
plist->count--;
|
|
|
|
if (update_list) {
|
|
route_map_notify_dependencies(plist->name,
|
|
RMAP_EVENT_PLIST_DELETED);
|
|
if (plist->master->delete_hook)
|
|
(*plist->master->delete_hook)(plist);
|
|
|
|
if (plist->head == NULL && plist->tail == NULL
|
|
&& plist->desc == NULL)
|
|
prefix_list_delete(plist);
|
|
else
|
|
plist->master->recent = plist;
|
|
}
|
|
}
|
|
|
|
static void trie_install_fn(struct prefix_list_entry *object,
|
|
struct prefix_list_entry **updptr)
|
|
{
|
|
while (*updptr) {
|
|
if (*updptr == object)
|
|
return;
|
|
if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen)
|
|
break;
|
|
if ((*updptr)->prefix.prefixlen == object->prefix.prefixlen
|
|
&& (*updptr)->seq > object->seq)
|
|
break;
|
|
updptr = &(*updptr)->next_best;
|
|
}
|
|
|
|
if (!object->next_best)
|
|
object->next_best = *updptr;
|
|
else
|
|
assert(object->next_best == *updptr || !*updptr);
|
|
|
|
*updptr = object;
|
|
}
|
|
|
|
static void prefix_list_trie_add(struct prefix_list *plist,
|
|
struct prefix_list_entry *pentry)
|
|
{
|
|
size_t depth = plist->master->trie_depth;
|
|
uint8_t *bytes = &pentry->prefix.u.prefix;
|
|
size_t validbits = pentry->prefix.prefixlen;
|
|
struct pltrie_table *table;
|
|
|
|
table = plist->trie;
|
|
while (validbits > PLC_BITS && depth > 1) {
|
|
if (!table->entries[*bytes].next_table)
|
|
table->entries[*bytes].next_table =
|
|
XCALLOC(MTYPE_PREFIX_LIST_TRIE,
|
|
sizeof(struct pltrie_table));
|
|
table = table->entries[*bytes].next_table;
|
|
bytes++;
|
|
depth--;
|
|
validbits -= PLC_BITS;
|
|
}
|
|
|
|
trie_walk_affected(validbits, table, *bytes, pentry, trie_install_fn);
|
|
}
|
|
|
|
static void prefix_list_entry_add(struct prefix_list *plist,
|
|
struct prefix_list_entry *pentry)
|
|
{
|
|
struct prefix_list_entry *replace;
|
|
struct prefix_list_entry *point;
|
|
|
|
/* Automatic asignment of seq no. */
|
|
if (pentry->seq == -1)
|
|
pentry->seq = prefix_new_seq_get(plist);
|
|
|
|
if (plist->tail && pentry->seq > plist->tail->seq)
|
|
point = NULL;
|
|
else {
|
|
/* Is there any same seq prefix list entry? */
|
|
replace = prefix_seq_check(plist, pentry->seq);
|
|
if (replace)
|
|
prefix_list_entry_delete(plist, replace, 0);
|
|
|
|
/* Check insert point. */
|
|
for (point = plist->head; point; point = point->next)
|
|
if (point->seq >= pentry->seq)
|
|
break;
|
|
}
|
|
|
|
/* In case of this is the first element of the list. */
|
|
pentry->next = point;
|
|
|
|
if (point) {
|
|
if (point->prev)
|
|
point->prev->next = pentry;
|
|
else
|
|
plist->head = pentry;
|
|
|
|
pentry->prev = point->prev;
|
|
point->prev = pentry;
|
|
} else {
|
|
if (plist->tail)
|
|
plist->tail->next = pentry;
|
|
else
|
|
plist->head = pentry;
|
|
|
|
pentry->prev = plist->tail;
|
|
plist->tail = pentry;
|
|
}
|
|
|
|
prefix_list_trie_add(plist, pentry);
|
|
|
|
/* Increment count. */
|
|
plist->count++;
|
|
|
|
/* Run hook function. */
|
|
if (plist->master->add_hook)
|
|
(*plist->master->add_hook)(plist);
|
|
|
|
route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_ADDED);
|
|
plist->master->recent = plist;
|
|
}
|
|
|
|
/* Return string of prefix_list_type. */
|
|
static const char *prefix_list_type_str(struct prefix_list_entry *pentry)
|
|
{
|
|
switch (pentry->type) {
|
|
case PREFIX_PERMIT:
|
|
return "permit";
|
|
case PREFIX_DENY:
|
|
return "deny";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
static int prefix_list_entry_match(struct prefix_list_entry *pentry,
|
|
struct prefix *p)
|
|
{
|
|
int ret;
|
|
|
|
ret = prefix_match(&pentry->prefix, p);
|
|
if (!ret)
|
|
return 0;
|
|
|
|
/* In case of le nor ge is specified, exact match is performed. */
|
|
if (!pentry->le && !pentry->ge) {
|
|
if (pentry->prefix.prefixlen != p->prefixlen)
|
|
return 0;
|
|
} else {
|
|
if (pentry->le)
|
|
if (p->prefixlen > pentry->le)
|
|
return 0;
|
|
|
|
if (pentry->ge)
|
|
if (p->prefixlen < pentry->ge)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object)
|
|
{
|
|
struct prefix_list_entry *pentry, *pbest = NULL;
|
|
|
|
struct prefix *p = (struct prefix *)object;
|
|
uint8_t *byte = &p->u.prefix;
|
|
size_t depth;
|
|
size_t validbits = p->prefixlen;
|
|
struct pltrie_table *table;
|
|
|
|
if (plist == NULL)
|
|
return PREFIX_DENY;
|
|
|
|
if (plist->count == 0)
|
|
return PREFIX_PERMIT;
|
|
|
|
depth = plist->master->trie_depth;
|
|
table = plist->trie;
|
|
while (1) {
|
|
for (pentry = table->entries[*byte].up_chain; pentry;
|
|
pentry = pentry->next_best) {
|
|
if (pbest && pbest->seq < pentry->seq)
|
|
continue;
|
|
if (prefix_list_entry_match(pentry, p))
|
|
pbest = pentry;
|
|
}
|
|
|
|
if (validbits <= PLC_BITS)
|
|
break;
|
|
validbits -= PLC_BITS;
|
|
|
|
if (--depth) {
|
|
if (!table->entries[*byte].next_table)
|
|
break;
|
|
|
|
table = table->entries[*byte].next_table;
|
|
byte++;
|
|
continue;
|
|
}
|
|
|
|
for (pentry = table->entries[*byte].final_chain; pentry;
|
|
pentry = pentry->next_best) {
|
|
if (pbest && pbest->seq < pentry->seq)
|
|
continue;
|
|
if (prefix_list_entry_match(pentry, p))
|
|
pbest = pentry;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (pbest == NULL)
|
|
return PREFIX_DENY;
|
|
|
|
return pbest->type;
|
|
}
|
|
|
|
static void __attribute__((unused)) prefix_list_print(struct prefix_list *plist)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
if (plist == NULL)
|
|
return;
|
|
|
|
printf("ip prefix-list %s: %d entries\n", plist->name, plist->count);
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
if (pentry->any)
|
|
printf("any %s\n", prefix_list_type_str(pentry));
|
|
else {
|
|
struct prefix *p;
|
|
char buf[BUFSIZ];
|
|
|
|
p = &pentry->prefix;
|
|
|
|
printf(" seq %u %s %s/%d", pentry->seq,
|
|
prefix_list_type_str(pentry),
|
|
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
|
|
p->prefixlen);
|
|
if (pentry->ge)
|
|
printf(" ge %d", pentry->ge);
|
|
if (pentry->le)
|
|
printf(" le %d", pentry->le);
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Retrun 1 when plist already include pentry policy. */
|
|
static struct prefix_list_entry *
|
|
prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new)
|
|
{
|
|
size_t depth, maxdepth = plist->master->trie_depth;
|
|
uint8_t byte, *bytes = &new->prefix.u.prefix;
|
|
size_t validbits = new->prefix.prefixlen;
|
|
struct pltrie_table *table;
|
|
struct prefix_list_entry *pentry;
|
|
int seq = 0;
|
|
|
|
if (new->seq == -1)
|
|
seq = prefix_new_seq_get(plist);
|
|
else
|
|
seq = new->seq;
|
|
|
|
table = plist->trie;
|
|
for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
|
|
byte = bytes[depth];
|
|
if (!table->entries[byte].next_table)
|
|
return NULL;
|
|
|
|
table = table->entries[byte].next_table;
|
|
validbits -= PLC_BITS;
|
|
}
|
|
|
|
byte = bytes[depth];
|
|
if (validbits > PLC_BITS)
|
|
pentry = table->entries[byte].final_chain;
|
|
else
|
|
pentry = table->entries[byte].up_chain;
|
|
|
|
for (; pentry; pentry = pentry->next_best) {
|
|
if (prefix_same(&pentry->prefix, &new->prefix)
|
|
&& pentry->type == new->type && pentry->le == new->le
|
|
&& pentry->ge == new->ge && pentry->seq != seq)
|
|
return pentry;
|
|
}
|
|
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%s",
|
|
prefix, VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
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;
|
|
int any = 0;
|
|
int seqnum = -1;
|
|
int lenum = 0;
|
|
int genum = 0;
|
|
|
|
/* Sequential number. */
|
|
if (seq)
|
|
seqnum = atoi(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%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* "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 = 1;
|
|
} else
|
|
ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p);
|
|
|
|
if (ret <= 0) {
|
|
vty_out(vty, "%% Malformed IPv4 prefix%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* 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 = 1;
|
|
} else
|
|
ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p);
|
|
|
|
if (ret <= 0) {
|
|
vty_out(vty, "%% Malformed IPv6 prefix%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* 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)%s", afi, VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
break;
|
|
}
|
|
|
|
/* 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));
|
|
zlog_warn(
|
|
"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;
|
|
int 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%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* We must have, at a minimum, both the type and prefix here */
|
|
if ((typestr == NULL) || (prefix == NULL)) {
|
|
vty_out(vty, "%% Both prefix and type required%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* Check sequence number. */
|
|
if (seq)
|
|
seqnum = atoi(seq);
|
|
|
|
/* ge and le number */
|
|
if (ge)
|
|
genum = atoi(ge);
|
|
if (le)
|
|
lenum = atoi(le);
|
|
|
|
/* 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%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* "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%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
} 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%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
/* 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%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
/* 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%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (plist->desc) {
|
|
XFREE(MTYPE_TMP, plist->desc);
|
|
plist->desc = NULL;
|
|
}
|
|
|
|
if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL)
|
|
prefix_list_delete(plist);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
enum display_type {
|
|
normal_display,
|
|
summary_display,
|
|
detail_display,
|
|
sequential_display,
|
|
longer_display,
|
|
first_match_display
|
|
};
|
|
|
|
static void vty_show_prefix_entry(struct vty *vty, afi_t afi,
|
|
struct prefix_list *plist,
|
|
struct prefix_master *master,
|
|
enum display_type dtype, int seqnum)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
/* Print the name of the protocol */
|
|
vty_out(vty, "%s: ", zlog_protoname());
|
|
|
|
if (dtype == normal_display) {
|
|
vty_out(vty, "ip%s prefix-list %s: %d entries%s",
|
|
afi == AFI_IP ? "" : "v6", plist->name, plist->count,
|
|
VTY_NEWLINE);
|
|
if (plist->desc)
|
|
vty_out(vty, " Description: %s%s", plist->desc,
|
|
VTY_NEWLINE);
|
|
} else if (dtype == summary_display || dtype == detail_display) {
|
|
vty_out(vty, "ip%s prefix-list %s:%s",
|
|
afi == AFI_IP ? "" : "v6", plist->name, VTY_NEWLINE);
|
|
|
|
if (plist->desc)
|
|
vty_out(vty, " Description: %s%s", plist->desc,
|
|
VTY_NEWLINE);
|
|
|
|
vty_out(vty,
|
|
" count: %d, range entries: %d, sequences: %u - %u%s",
|
|
plist->count, plist->rangecount,
|
|
plist->head ? plist->head->seq : 0,
|
|
plist->tail ? plist->tail->seq : 0, VTY_NEWLINE);
|
|
}
|
|
|
|
if (dtype != summary_display) {
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
if (dtype == sequential_display
|
|
&& pentry->seq != seqnum)
|
|
continue;
|
|
|
|
vty_out(vty, " ");
|
|
|
|
if (master->seqnum)
|
|
vty_out(vty, "seq %u ", 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.prefix, buf,
|
|
BUFSIZ),
|
|
p->prefixlen);
|
|
|
|
if (pentry->ge)
|
|
vty_out(vty, " ge %d", pentry->ge);
|
|
if (pentry->le)
|
|
vty_out(vty, " le %d", pentry->le);
|
|
}
|
|
|
|
if (dtype == detail_display
|
|
|| dtype == sequential_display)
|
|
vty_out(vty, " (hit count: %ld, refcount: %ld)",
|
|
pentry->hitcnt, pentry->refcnt);
|
|
|
|
vty_out(vty, "%s", VTY_NEWLINE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
|
|
const char *seq, enum display_type dtype)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_master *master;
|
|
int seqnum = 0;
|
|
|
|
master = prefix_master_get(afi, 0);
|
|
if (master == NULL)
|
|
return CMD_WARNING;
|
|
|
|
if (seq)
|
|
seqnum = atoi(seq);
|
|
|
|
if (name) {
|
|
plist = prefix_list_lookup(afi, name);
|
|
if (!plist) {
|
|
vty_out(vty, "%% Can't find specified prefix-list%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
vty_show_prefix_entry(vty, afi, plist, master, dtype, seqnum);
|
|
} else {
|
|
if (dtype == detail_display || dtype == summary_display) {
|
|
if (master->recent)
|
|
vty_out(vty,
|
|
"Prefix-list with the last deletion/insertion: %s%s",
|
|
master->recent->name, VTY_NEWLINE);
|
|
}
|
|
|
|
for (plist = master->num.head; plist; plist = plist->next)
|
|
vty_show_prefix_entry(vty, afi, plist, master, dtype,
|
|
seqnum);
|
|
|
|
for (plist = master->str.head; plist; plist = plist->next)
|
|
vty_show_prefix_entry(vty, afi, plist, master, dtype,
|
|
seqnum);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
|
|
const char *name, const char *prefix,
|
|
enum display_type type)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_list_entry *pentry;
|
|
struct prefix p;
|
|
int ret;
|
|
int match;
|
|
|
|
plist = prefix_list_lookup(afi, name);
|
|
if (!plist) {
|
|
vty_out(vty, "%% Can't find specified prefix-list%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
ret = str2prefix(prefix, &p);
|
|
if (ret <= 0) {
|
|
vty_out(vty, "%% prefix is malformed%s", VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
match = 0;
|
|
|
|
if (type == normal_display || type == first_match_display)
|
|
if (prefix_same(&p, &pentry->prefix))
|
|
match = 1;
|
|
|
|
if (type == longer_display)
|
|
if (prefix_match(&p, &pentry->prefix))
|
|
match = 1;
|
|
|
|
if (match) {
|
|
vty_out(vty, " seq %u %s ", pentry->seq,
|
|
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.prefix, buf,
|
|
BUFSIZ),
|
|
p->prefixlen);
|
|
|
|
if (pentry->ge)
|
|
vty_out(vty, " ge %d", pentry->ge);
|
|
if (pentry->le)
|
|
vty_out(vty, " le %d", pentry->le);
|
|
}
|
|
|
|
if (type == normal_display
|
|
|| type == first_match_display)
|
|
vty_out(vty, " (hit count: %ld, refcount: %ld)",
|
|
pentry->hitcnt, pentry->refcnt);
|
|
|
|
vty_out(vty, "%s", VTY_NEWLINE);
|
|
|
|
if (type == first_match_display)
|
|
return CMD_SUCCESS;
|
|
}
|
|
}
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
|
|
const char *prefix)
|
|
{
|
|
struct prefix_master *master;
|
|
struct prefix_list *plist;
|
|
struct prefix_list_entry *pentry;
|
|
int ret;
|
|
struct prefix p;
|
|
|
|
master = prefix_master_get(afi, 0);
|
|
if (master == NULL)
|
|
return CMD_WARNING;
|
|
|
|
if (name == NULL && prefix == NULL) {
|
|
for (plist = master->num.head; plist; plist = plist->next)
|
|
for (pentry = plist->head; pentry;
|
|
pentry = pentry->next)
|
|
pentry->hitcnt = 0;
|
|
|
|
for (plist = master->str.head; plist; plist = plist->next)
|
|
for (pentry = plist->head; pentry;
|
|
pentry = pentry->next)
|
|
pentry->hitcnt = 0;
|
|
} else {
|
|
plist = prefix_list_lookup(afi, name);
|
|
if (!plist) {
|
|
vty_out(vty, "%% Can't find specified prefix-list%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
if (prefix) {
|
|
ret = str2prefix(prefix, &p);
|
|
if (ret <= 0) {
|
|
vty_out(vty, "%% prefix is malformed%s",
|
|
VTY_NEWLINE);
|
|
return CMD_WARNING;
|
|
}
|
|
}
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
if (prefix) {
|
|
if (prefix_match(&pentry->prefix, &p))
|
|
pentry->hitcnt = 0;
|
|
} else
|
|
pentry->hitcnt = 0;
|
|
}
|
|
}
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN (ip_prefix_list,
|
|
ip_prefix_list_cmd,
|
|
"ip prefix-list WORD <deny|permit> <A.B.C.D/M|any>",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Any prefix match. Same as \"0.0.0.0/0 le 32\"\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv4_any = 4;
|
|
return vty_prefix_list_install(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_ge,
|
|
ip_prefix_list_ge_cmd,
|
|
"ip prefix-list WORD <deny|permit> A.B.C.D/M ge (0-32)",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
int idx_number = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_ge_le,
|
|
ip_prefix_list_ge_le_cmd,
|
|
"ip prefix-list WORD <deny|permit> A.B.C.D/M ge (0-32) le (0-32)",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\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")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
int idx_number = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_le,
|
|
ip_prefix_list_le_cmd,
|
|
"ip prefix-list WORD <deny|permit> A.B.C.D/M le (0-32)",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
int idx_number = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg, NULL,
|
|
argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_le_ge,
|
|
ip_prefix_list_le_ge_cmd,
|
|
"ip prefix-list WORD <deny|permit> A.B.C.D/M le (0-32) ge (0-32)",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
int idx_number = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_seq,
|
|
ip_prefix_list_seq_cmd,
|
|
"ip prefix-list WORD seq (1-4294967295) <deny|permit> <A.B.C.D/M|any>",
|
|
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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Any prefix match. Same as \"0.0.0.0/0 le 32\"\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv4_any = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_seq_ge,
|
|
ip_prefix_list_seq_ge_cmd,
|
|
"ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M ge (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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv4_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_seq_ge_le,
|
|
ip_prefix_list_seq_ge_le_cmd,
|
|
"ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M 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"
|
|
"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")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv4_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
int idx_number_3 = 10;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number_3]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_seq_le,
|
|
ip_prefix_list_seq_le_cmd,
|
|
"ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M 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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv4_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg, NULL,
|
|
argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_seq_le_ge,
|
|
ip_prefix_list_seq_le_ge_cmd,
|
|
"ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M le (0-32) ge (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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv4_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
int idx_number_3 = 10;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_3]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list,
|
|
no_ip_prefix_list_cmd,
|
|
"no ip prefix-list WORD",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_prefix,
|
|
no_ip_prefix_list_prefix_cmd,
|
|
"no ip prefix-list WORD <deny|permit> <A.B.C.D/M|any>",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Any prefix match. Same as \"0.0.0.0/0 le 32\"\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv4_any = 5;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_ge,
|
|
no_ip_prefix_list_ge_cmd,
|
|
"no ip prefix-list WORD <deny|permit> A.B.C.D/M ge (0-32)",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv4_prefixlen = 5;
|
|
int idx_number = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_ge_le,
|
|
no_ip_prefix_list_ge_le_cmd,
|
|
"no ip prefix-list WORD <deny|permit> A.B.C.D/M ge (0-32) le (0-32)",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\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")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv4_prefixlen = 5;
|
|
int idx_number = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_le,
|
|
no_ip_prefix_list_le_cmd,
|
|
"no ip prefix-list WORD <deny|permit> A.B.C.D/M le (0-32)",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv4_prefixlen = 5;
|
|
int idx_number = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg, NULL,
|
|
argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_le_ge,
|
|
no_ip_prefix_list_le_ge_cmd,
|
|
"no ip prefix-list WORD <deny|permit> A.B.C.D/M le (0-32) ge (0-32)",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv4_prefixlen = 5;
|
|
int idx_number = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_seq,
|
|
no_ip_prefix_list_seq_cmd,
|
|
"no ip prefix-list WORD seq (1-4294967295) <deny|permit> <A.B.C.D/M|any>",
|
|
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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Any prefix match. Same as \"0.0.0.0/0 le 32\"\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv4_any = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv4_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_seq_ge,
|
|
no_ip_prefix_list_seq_ge_cmd,
|
|
"no ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M ge (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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv4_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_seq_ge_le,
|
|
no_ip_prefix_list_seq_ge_le_cmd,
|
|
"no ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M 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"
|
|
"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")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv4_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
int idx_number_3 = 11;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number_3]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_seq_le,
|
|
no_ip_prefix_list_seq_le_cmd,
|
|
"no ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M 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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv4_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg, NULL,
|
|
argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_seq_le_ge,
|
|
no_ip_prefix_list_seq_le_ge_cmd,
|
|
"no ip prefix-list WORD seq (1-4294967295) <deny|permit> A.B.C.D/M le (0-32) ge (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"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv4_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
int idx_number_3 = 11;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv4_prefixlen]->arg,
|
|
argv[idx_number_3]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ip_prefix_list_sequence_number,
|
|
ip_prefix_list_sequence_number_cmd,
|
|
"ip prefix-list sequence-number",
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Include/exclude sequence numbers in NVGEN\n")
|
|
{
|
|
prefix_master_ipv4.seqnum = 1;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN (no_ip_prefix_list_sequence_number,
|
|
no_ip_prefix_list_sequence_number_cmd,
|
|
"no ip prefix-list sequence-number",
|
|
NO_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Include/exclude sequence numbers in NVGEN\n")
|
|
{
|
|
prefix_master_ipv4.seqnum = 0;
|
|
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);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list,
|
|
show_ip_prefix_list_cmd,
|
|
"show ip prefix-list",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR)
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP, NULL, NULL, normal_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_name,
|
|
show_ip_prefix_list_name_cmd,
|
|
"show ip prefix-list WORD",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_show_prefix_list(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
normal_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_name_seq,
|
|
show_ip_prefix_list_name_seq_cmd,
|
|
"show ip prefix-list WORD seq (1-4294967295)",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"sequence number of an entry\n"
|
|
"Sequence number\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
return vty_show_prefix_list(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_number]->arg, sequential_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_prefix,
|
|
show_ip_prefix_list_prefix_cmd,
|
|
"show ip prefix-list WORD A.B.C.D/M",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg,
|
|
normal_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_prefix_longer,
|
|
show_ip_prefix_list_prefix_longer_cmd,
|
|
"show ip prefix-list WORD A.B.C.D/M longer",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"Lookup longer prefix\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg,
|
|
longer_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_prefix_first_match,
|
|
show_ip_prefix_list_prefix_first_match_cmd,
|
|
"show ip prefix-list WORD A.B.C.D/M first-match",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
|
"First matched prefix\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg,
|
|
first_match_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_summary,
|
|
show_ip_prefix_list_summary_cmd,
|
|
"show ip prefix-list summary",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Summary of prefix lists\n")
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP, NULL, NULL, summary_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_summary_name,
|
|
show_ip_prefix_list_summary_name_cmd,
|
|
"show ip prefix-list summary WORD",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Summary of prefix lists\n"
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 4;
|
|
return vty_show_prefix_list(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
summary_display);
|
|
}
|
|
|
|
|
|
DEFUN (show_ip_prefix_list_detail,
|
|
show_ip_prefix_list_detail_cmd,
|
|
"show ip prefix-list detail",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Detail of prefix lists\n")
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP, NULL, NULL, detail_display);
|
|
}
|
|
|
|
DEFUN (show_ip_prefix_list_detail_name,
|
|
show_ip_prefix_list_detail_name_cmd,
|
|
"show ip prefix-list detail WORD",
|
|
SHOW_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Detail of prefix lists\n"
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 4;
|
|
return vty_show_prefix_list(vty, AFI_IP, argv[idx_word]->arg, NULL,
|
|
detail_display);
|
|
}
|
|
|
|
DEFUN (clear_ip_prefix_list,
|
|
clear_ip_prefix_list_cmd,
|
|
"clear ip prefix-list",
|
|
CLEAR_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR)
|
|
{
|
|
return vty_clear_prefix_list(vty, AFI_IP, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (clear_ip_prefix_list_name,
|
|
clear_ip_prefix_list_name_cmd,
|
|
"clear ip prefix-list WORD",
|
|
CLEAR_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_clear_prefix_list(vty, AFI_IP, argv[idx_word]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (clear_ip_prefix_list_name_prefix,
|
|
clear_ip_prefix_list_name_prefix_cmd,
|
|
"clear ip prefix-list WORD A.B.C.D/M",
|
|
CLEAR_STR
|
|
IP_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv4_prefixlen = 4;
|
|
return vty_clear_prefix_list(vty, AFI_IP, argv[idx_word]->arg,
|
|
argv[idx_ipv4_prefixlen]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list,
|
|
ipv6_prefix_list_cmd,
|
|
"ipv6 prefix-list WORD <deny|permit> <X:X::X:X/M|any>",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Any prefix match. Same as \"::0/0 le 128\"\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv6_any = 4;
|
|
return vty_prefix_list_install(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_ge,
|
|
ipv6_prefix_list_ge_cmd,
|
|
"ipv6 prefix-list WORD <deny|permit> X:X::X:X/M ge (0-128)",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
int idx_number = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_ge_le,
|
|
ipv6_prefix_list_ge_le_cmd,
|
|
"ipv6 prefix-list WORD <deny|permit> X:X::X:X/M ge (0-128) le (0-128)",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
int idx_number = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_le,
|
|
ipv6_prefix_list_le_cmd,
|
|
"ipv6 prefix-list WORD <deny|permit> X:X::X:X/M le (0-128)",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
int idx_number = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg, NULL,
|
|
argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_le_ge,
|
|
ipv6_prefix_list_le_ge_cmd,
|
|
"ipv6 prefix-list WORD <deny|permit> X:X::X:X/M le (0-128) ge (0-128)",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\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")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_permit_deny = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
int idx_number = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_seq,
|
|
ipv6_prefix_list_seq_cmd,
|
|
"ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> <X:X::X:X/M|any>",
|
|
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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Any prefix match. Same as \"::0/0 le 128\"\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv6_any = 6;
|
|
return vty_prefix_list_install(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_seq_ge,
|
|
ipv6_prefix_list_seq_ge_cmd,
|
|
"ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M ge (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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv6_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_seq_ge_le,
|
|
ipv6_prefix_list_seq_ge_le_cmd,
|
|
"ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M 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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv6_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
int idx_number_3 = 10;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number_3]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_seq_le,
|
|
ipv6_prefix_list_seq_le_cmd,
|
|
"ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M 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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv6_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg, NULL,
|
|
argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_seq_le_ge,
|
|
ipv6_prefix_list_seq_le_ge_cmd,
|
|
"ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M le (0-128) ge (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"
|
|
"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")
|
|
{
|
|
int idx_word = 2;
|
|
int idx_number = 4;
|
|
int idx_permit_deny = 5;
|
|
int idx_ipv6_prefixlen = 6;
|
|
int idx_number_2 = 8;
|
|
int idx_number_3 = 10;
|
|
return vty_prefix_list_install(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_3]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list,
|
|
no_ipv6_prefix_list_cmd,
|
|
"no ipv6 prefix-list WORD",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP6, argv[idx_word]->arg,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_prefix,
|
|
no_ipv6_prefix_list_prefix_cmd,
|
|
"no ipv6 prefix-list WORD <deny|permit> <X:X::X:X/M|any>",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Any prefix match. Same as \"::0/0 le 128\"\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv6_any = 5;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP6, argv[idx_word]->arg,
|
|
NULL, argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_ge,
|
|
no_ipv6_prefix_list_ge_cmd,
|
|
"no ipv6 prefix-list WORD <deny|permit> X:X::X:X/M ge (0-128)",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv6_prefixlen = 5;
|
|
int idx_number = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP6, argv[idx_word]->arg,
|
|
NULL, argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_ge_le,
|
|
no_ipv6_prefix_list_ge_le_cmd,
|
|
"no ipv6 prefix-list WORD <deny|permit> X:X::X:X/M ge (0-128) le (0-128)",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv6_prefixlen = 5;
|
|
int idx_number = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_le,
|
|
no_ipv6_prefix_list_le_cmd,
|
|
"no ipv6 prefix-list WORD <deny|permit> X:X::X:X/M le (0-128)",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv6_prefixlen = 5;
|
|
int idx_number = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP6, argv[idx_word]->arg,
|
|
NULL, argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg, NULL,
|
|
argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_le_ge,
|
|
no_ipv6_prefix_list_le_ge_cmd,
|
|
"no ipv6 prefix-list WORD <deny|permit> X:X::X:X/M le (0-128) ge (0-128)",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"Specify packets to reject\n"
|
|
"Specify packets to forward\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")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_permit_deny = 4;
|
|
int idx_ipv6_prefixlen = 5;
|
|
int idx_number = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_seq,
|
|
no_ipv6_prefix_list_seq_cmd,
|
|
"no ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> <X:X::X:X/M|any>",
|
|
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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Any prefix match. Same as \"::0/0 le 128\"\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv6_any = 7;
|
|
return vty_prefix_list_uninstall(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg,
|
|
argv[idx_ipv6_any]->arg, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_seq_ge,
|
|
no_ipv6_prefix_list_seq_ge_cmd,
|
|
"no ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M ge (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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv6_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_seq_ge_le,
|
|
no_ipv6_prefix_list_seq_ge_le_cmd,
|
|
"no ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M 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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Minimum prefix length to be matched\n"
|
|
"Minimum prefix length\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv6_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
int idx_number_3 = 11;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_2]->arg, argv[idx_number_3]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_seq_le,
|
|
no_ipv6_prefix_list_seq_le_cmd,
|
|
"no ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M 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"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Maximum prefix length to be matched\n"
|
|
"Maximum prefix length\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv6_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg, NULL,
|
|
argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_seq_le_ge,
|
|
no_ipv6_prefix_list_seq_le_ge_cmd,
|
|
"no ipv6 prefix-list WORD seq (1-4294967295) <deny|permit> X:X::X:X/M le (0-128) ge (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"
|
|
"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")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
int idx_permit_deny = 6;
|
|
int idx_ipv6_prefixlen = 7;
|
|
int idx_number_2 = 9;
|
|
int idx_number_3 = 11;
|
|
return vty_prefix_list_uninstall(
|
|
vty, AFI_IP6, argv[idx_word]->arg, argv[idx_number]->arg,
|
|
argv[idx_permit_deny]->arg, argv[idx_ipv6_prefixlen]->arg,
|
|
argv[idx_number_3]->arg, argv[idx_number_2]->arg);
|
|
}
|
|
|
|
DEFUN (ipv6_prefix_list_sequence_number,
|
|
ipv6_prefix_list_sequence_number_cmd,
|
|
"ipv6 prefix-list sequence-number",
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Include/exclude sequence numbers in NVGEN\n")
|
|
{
|
|
prefix_master_ipv6.seqnum = 1;
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN (no_ipv6_prefix_list_sequence_number,
|
|
no_ipv6_prefix_list_sequence_number_cmd,
|
|
"no ipv6 prefix-list sequence-number",
|
|
NO_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Include/exclude sequence numbers in NVGEN\n")
|
|
{
|
|
prefix_master_ipv6.seqnum = 0;
|
|
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);
|
|
}
|
|
|
|
|
|
DEFUN (show_ipv6_prefix_list,
|
|
show_ipv6_prefix_list_cmd,
|
|
"show ipv6 prefix-list",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR)
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP6, NULL, NULL, normal_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_name,
|
|
show_ipv6_prefix_list_name_cmd,
|
|
"show ipv6 prefix-list WORD",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_show_prefix_list(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
normal_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_name_seq,
|
|
show_ipv6_prefix_list_name_seq_cmd,
|
|
"show ipv6 prefix-list WORD seq (1-4294967295)",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"sequence number of an entry\n"
|
|
"Sequence number\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_number = 5;
|
|
return vty_show_prefix_list(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_number]->arg, sequential_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_prefix,
|
|
show_ipv6_prefix_list_prefix_cmd,
|
|
"show ipv6 prefix-list WORD X:X::X:X/M",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg,
|
|
normal_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_prefix_longer,
|
|
show_ipv6_prefix_list_prefix_longer_cmd,
|
|
"show ipv6 prefix-list WORD X:X::X:X/M longer",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"Lookup longer prefix\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg,
|
|
longer_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_prefix_first_match,
|
|
show_ipv6_prefix_list_prefix_first_match_cmd,
|
|
"show ipv6 prefix-list WORD X:X::X:X/M first-match",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
|
|
"First matched prefix\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
return vty_show_prefix_list_prefix(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg,
|
|
first_match_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_summary,
|
|
show_ipv6_prefix_list_summary_cmd,
|
|
"show ipv6 prefix-list summary",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Summary of prefix lists\n")
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP6, NULL, NULL, summary_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_summary_name,
|
|
show_ipv6_prefix_list_summary_name_cmd,
|
|
"show ipv6 prefix-list summary WORD",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Summary of prefix lists\n"
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 4;
|
|
return vty_show_prefix_list(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
summary_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_detail,
|
|
show_ipv6_prefix_list_detail_cmd,
|
|
"show ipv6 prefix-list detail",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Detail of prefix lists\n")
|
|
{
|
|
return vty_show_prefix_list(vty, AFI_IP6, NULL, NULL, detail_display);
|
|
}
|
|
|
|
DEFUN (show_ipv6_prefix_list_detail_name,
|
|
show_ipv6_prefix_list_detail_name_cmd,
|
|
"show ipv6 prefix-list detail WORD",
|
|
SHOW_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Detail of prefix lists\n"
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 4;
|
|
return vty_show_prefix_list(vty, AFI_IP6, argv[idx_word]->arg, NULL,
|
|
detail_display);
|
|
}
|
|
|
|
DEFUN (clear_ipv6_prefix_list,
|
|
clear_ipv6_prefix_list_cmd,
|
|
"clear ipv6 prefix-list",
|
|
CLEAR_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR)
|
|
{
|
|
return vty_clear_prefix_list(vty, AFI_IP6, NULL, NULL);
|
|
}
|
|
|
|
DEFUN (clear_ipv6_prefix_list_name,
|
|
clear_ipv6_prefix_list_name_cmd,
|
|
"clear ipv6 prefix-list WORD",
|
|
CLEAR_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n")
|
|
{
|
|
int idx_word = 3;
|
|
return vty_clear_prefix_list(vty, AFI_IP6, argv[idx_word]->arg, NULL);
|
|
}
|
|
|
|
DEFUN (clear_ipv6_prefix_list_name_prefix,
|
|
clear_ipv6_prefix_list_name_prefix_cmd,
|
|
"clear ipv6 prefix-list WORD X:X::X:X/M",
|
|
CLEAR_STR
|
|
IPV6_STR
|
|
PREFIX_LIST_STR
|
|
"Name of a prefix list\n"
|
|
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
|
|
{
|
|
int idx_word = 3;
|
|
int idx_ipv6_prefixlen = 4;
|
|
return vty_clear_prefix_list(vty, AFI_IP6, argv[idx_word]->arg,
|
|
argv[idx_ipv6_prefixlen]->arg);
|
|
}
|
|
|
|
/* 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%s",
|
|
afi == AFI_IP ? "" : "v6", VTY_NEWLINE);
|
|
vty_out(vty, "!%s", VTY_NEWLINE);
|
|
}
|
|
|
|
for (plist = master->num.head; plist; plist = plist->next) {
|
|
if (plist->desc) {
|
|
vty_out(vty, "ip%s prefix-list %s description %s%s",
|
|
afi == AFI_IP ? "" : "v6", plist->name,
|
|
plist->desc, VTY_NEWLINE);
|
|
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 %u ", 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.prefix, 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, "%s", VTY_NEWLINE);
|
|
write++;
|
|
}
|
|
/* vty_out (vty, "!%s", VTY_NEWLINE); */
|
|
}
|
|
|
|
for (plist = master->str.head; plist; plist = plist->next) {
|
|
if (plist->desc) {
|
|
vty_out(vty, "ip%s prefix-list %s description %s%s",
|
|
afi == AFI_IP ? "" : "v6", plist->name,
|
|
plist->desc, VTY_NEWLINE);
|
|
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 %u ", 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.prefix, 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, "%s", VTY_NEWLINE);
|
|
write++;
|
|
}
|
|
}
|
|
|
|
return write;
|
|
}
|
|
|
|
struct stream *prefix_bgp_orf_entry(struct stream *s, struct prefix_list *plist,
|
|
u_char init_flag, u_char permit_flag,
|
|
u_char deny_flag)
|
|
{
|
|
struct prefix_list_entry *pentry;
|
|
|
|
if (!plist)
|
|
return s;
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
u_char flag = init_flag;
|
|
struct prefix *p = &pentry->prefix;
|
|
|
|
flag |= (pentry->type == PREFIX_PERMIT ? permit_flag
|
|
: deny_flag);
|
|
stream_putc(s, flag);
|
|
stream_putl(s, (u_int32_t)pentry->seq);
|
|
stream_putc(s, (u_char)pentry->ge);
|
|
stream_putc(s, (u_char)pentry->le);
|
|
stream_put_prefix(s, p);
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
int prefix_bgp_orf_set(char *name, afi_t afi, struct orf_prefix *orfp,
|
|
int permit, int set)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_list_entry *pentry;
|
|
|
|
/* ge and le value check */
|
|
if (orfp->ge && orfp->ge <= orfp->p.prefixlen)
|
|
return CMD_WARNING;
|
|
if (orfp->le && orfp->le <= orfp->p.prefixlen)
|
|
return CMD_WARNING;
|
|
if (orfp->le && orfp->ge > orfp->le)
|
|
return CMD_WARNING;
|
|
|
|
if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128))
|
|
orfp->le = 0;
|
|
|
|
plist = prefix_list_get(afi, 1, name);
|
|
if (!plist)
|
|
return CMD_WARNING;
|
|
|
|
if (set) {
|
|
pentry = prefix_list_entry_make(
|
|
&orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
|
|
orfp->seq, orfp->le, orfp->ge, 0);
|
|
|
|
if (prefix_entry_dup_check(plist, pentry)) {
|
|
prefix_list_entry_free(pentry);
|
|
return CMD_WARNING;
|
|
}
|
|
|
|
prefix_list_entry_add(plist, pentry);
|
|
} else {
|
|
pentry = prefix_list_entry_lookup(
|
|
plist, &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
|
|
orfp->seq, orfp->le, orfp->ge);
|
|
|
|
if (!pentry)
|
|
return CMD_WARNING;
|
|
|
|
prefix_list_entry_delete(plist, pentry, 1);
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
void prefix_bgp_orf_remove_all(afi_t afi, char *name)
|
|
{
|
|
struct prefix_list *plist;
|
|
|
|
plist = prefix_bgp_orf_lookup(afi, name);
|
|
if (plist)
|
|
prefix_list_delete(plist);
|
|
}
|
|
|
|
/* return prefix count */
|
|
int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name,
|
|
u_char use_json)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_list_entry *pentry;
|
|
json_object *json = NULL;
|
|
json_object *json_prefix = NULL;
|
|
json_object *json_list = NULL;
|
|
|
|
plist = prefix_bgp_orf_lookup(afi, name);
|
|
if (!plist)
|
|
return 0;
|
|
|
|
if (!vty)
|
|
return plist->count;
|
|
|
|
if (use_json) {
|
|
json = json_object_new_object();
|
|
json_prefix = json_object_new_object();
|
|
json_list = json_object_new_object();
|
|
|
|
json_object_int_add(json_prefix, "prefixListCounter",
|
|
plist->count);
|
|
json_object_string_add(json_prefix, "prefixListName",
|
|
plist->name);
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
struct prefix *p = &pentry->prefix;
|
|
char buf_a[BUFSIZ];
|
|
char buf_b[BUFSIZ];
|
|
|
|
sprintf(buf_a, "%s/%d",
|
|
inet_ntop(p->family, &p->u.prefix, buf_b,
|
|
BUFSIZ),
|
|
p->prefixlen);
|
|
|
|
json_object_int_add(json_list, "seq", pentry->seq);
|
|
json_object_string_add(json_list, "seqPrefixListType",
|
|
prefix_list_type_str(pentry));
|
|
|
|
if (pentry->ge)
|
|
json_object_int_add(json_list, "ge",
|
|
pentry->ge);
|
|
if (pentry->le)
|
|
json_object_int_add(json_list, "le",
|
|
pentry->le);
|
|
|
|
json_object_object_add(json_prefix, buf_a, json_list);
|
|
}
|
|
if (afi == AFI_IP)
|
|
json_object_object_add(json, "ipPrefixList",
|
|
json_prefix);
|
|
else
|
|
json_object_object_add(json, "ipv6PrefixList",
|
|
json_prefix);
|
|
|
|
vty_out(vty, "%s%s", json_object_to_json_string_ext(
|
|
json, JSON_C_TO_STRING_PRETTY),
|
|
VTY_NEWLINE);
|
|
json_object_free(json);
|
|
} else {
|
|
vty_out(vty, "ip%s prefix-list %s: %d entries%s",
|
|
afi == AFI_IP ? "" : "v6", plist->name, plist->count,
|
|
VTY_NEWLINE);
|
|
|
|
for (pentry = plist->head; pentry; pentry = pentry->next) {
|
|
struct prefix *p = &pentry->prefix;
|
|
char buf[BUFSIZ];
|
|
|
|
vty_out(vty, " seq %u %s %s/%d", pentry->seq,
|
|
prefix_list_type_str(pentry),
|
|
inet_ntop(p->family, &p->u.prefix, 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, "%s", VTY_NEWLINE);
|
|
}
|
|
}
|
|
return plist->count;
|
|
}
|
|
|
|
static void prefix_list_reset_afi(afi_t afi, int orf)
|
|
{
|
|
struct prefix_list *plist;
|
|
struct prefix_list *next;
|
|
struct prefix_master *master;
|
|
|
|
master = prefix_master_get(afi, orf);
|
|
if (master == NULL)
|
|
return;
|
|
|
|
for (plist = master->num.head; plist; plist = next) {
|
|
next = plist->next;
|
|
prefix_list_delete(plist);
|
|
}
|
|
for (plist = master->str.head; plist; plist = next) {
|
|
next = plist->next;
|
|
prefix_list_delete(plist);
|
|
}
|
|
|
|
assert(master->num.head == NULL);
|
|
assert(master->num.tail == NULL);
|
|
|
|
assert(master->str.head == NULL);
|
|
assert(master->str.tail == NULL);
|
|
|
|
master->seqnum = 1;
|
|
master->recent = NULL;
|
|
}
|
|
|
|
|
|
/* Prefix-list node. */
|
|
static struct cmd_node prefix_node = {PREFIX_NODE,
|
|
"", /* Prefix list has no interface. */
|
|
1};
|
|
|
|
static int config_write_prefix_ipv4(struct vty *vty)
|
|
{
|
|
return config_write_prefix_afi(AFI_IP, vty);
|
|
}
|
|
|
|
static void prefix_list_init_ipv4(void)
|
|
{
|
|
install_node(&prefix_node, config_write_prefix_ipv4);
|
|
|
|
install_element(CONFIG_NODE, &ip_prefix_list_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_ge_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_le_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_le_ge_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_seq_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_seq_ge_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_seq_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_seq_le_cmd);
|
|
install_element(CONFIG_NODE, &ip_prefix_list_seq_le_ge_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_prefix_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_le_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_seq_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_seq_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_seq_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_seq_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ip_prefix_list_seq_le_ge_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(CONFIG_NODE, &no_ip_prefix_list_sequence_number_cmd);
|
|
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_name_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_name_seq_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_prefix_longer_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_prefix_first_match_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_summary_name_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
|
|
install_element(VIEW_NODE, &show_ip_prefix_list_detail_name_cmd);
|
|
|
|
install_element(ENABLE_NODE, &clear_ip_prefix_list_cmd);
|
|
install_element(ENABLE_NODE, &clear_ip_prefix_list_name_cmd);
|
|
install_element(ENABLE_NODE, &clear_ip_prefix_list_name_prefix_cmd);
|
|
}
|
|
|
|
/* Prefix-list node. */
|
|
static struct cmd_node prefix_ipv6_node = {
|
|
PREFIX_IPV6_NODE, "", /* Prefix list has no interface. */
|
|
1};
|
|
|
|
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, config_write_prefix_ipv6);
|
|
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_ge_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_le_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_le_ge_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_seq_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_seq_ge_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_seq_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_seq_le_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_prefix_list_seq_le_ge_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_prefix_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_le_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_ge_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_ge_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_le_cmd);
|
|
install_element(CONFIG_NODE, &no_ipv6_prefix_list_seq_le_ge_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(CONFIG_NODE, &no_ipv6_prefix_list_sequence_number_cmd);
|
|
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_name_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_name_seq_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_longer_cmd);
|
|
install_element(VIEW_NODE,
|
|
&show_ipv6_prefix_list_prefix_first_match_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_name_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
|
|
install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_name_cmd);
|
|
|
|
install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd);
|
|
install_element(ENABLE_NODE, &clear_ipv6_prefix_list_name_cmd);
|
|
install_element(ENABLE_NODE, &clear_ipv6_prefix_list_name_prefix_cmd);
|
|
}
|
|
|
|
void prefix_list_init()
|
|
{
|
|
prefix_list_init_ipv4();
|
|
prefix_list_init_ipv6();
|
|
}
|
|
|
|
void prefix_list_reset()
|
|
{
|
|
prefix_list_reset_afi(AFI_IP, 0);
|
|
prefix_list_reset_afi(AFI_IP6, 0);
|
|
prefix_list_reset_afi(AFI_IP, 1);
|
|
prefix_list_reset_afi(AFI_IP6, 1);
|
|
}
|