]> git.proxmox.com Git - mirror_frr.git/blame - lib/plist.c
lib: terminate capabilities only if initialized
[mirror_frr.git] / lib / plist.c
CommitLineData
718e3744 1/* Prefix list functions.
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "command.h"
25#include "memory.h"
26#include "plist.h"
27#include "sockunion.h"
28#include "buffer.h"
fbf5d033 29#include "log.h"
518f0eb1 30#include "routemap.h"
6f1ccc12 31#include "lib/json.h"
b85120bc 32#include "libfrr.h"
718e3744 33
a38401b6 34#include "plist_int.h"
718e3744 35
d62a17ae 36DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST, "Prefix List")
37DEFINE_MTYPE_STATIC(LIB, MPREFIX_LIST_STR, "Prefix List Str")
4a1ab8e4 38DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_ENTRY, "Prefix List Entry")
d62a17ae 39DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_TRIE, "Prefix List Trie Table")
4a1ab8e4 40
7e111b6b
DL
41/* not currently changeable, code assumes bytes further down */
42#define PLC_BITS 8
43#define PLC_LEN (1 << PLC_BITS)
44#define PLC_MAXLEVELV4 2 /* /24 for IPv4 */
45#define PLC_MAXLEVELV6 4 /* /48 for IPv6 */
46#define PLC_MAXLEVEL 4 /* max(v4,v6) */
47
48struct pltrie_entry {
49 union {
50 struct pltrie_table *next_table;
51 struct prefix_list_entry *final_chain;
52 };
53
54 struct prefix_list_entry *up_chain;
55};
56
57struct pltrie_table {
58 struct pltrie_entry entries[PLC_LEN];
59};
60
718e3744 61/* List of struct prefix_list. */
d62a17ae 62struct prefix_list_list {
63 struct prefix_list *head;
64 struct prefix_list *tail;
718e3744 65};
66
67/* Master structure of prefix_list. */
d62a17ae 68struct prefix_master {
69 /* List of prefix_list which name is number. */
70 struct prefix_list_list num;
718e3744 71
d62a17ae 72 /* List of prefix_list which name is string. */
73 struct prefix_list_list str;
718e3744 74
d62a17ae 75 /* Whether sequential number is used. */
76 int seqnum;
718e3744 77
d62a17ae 78 /* The latest update. */
79 struct prefix_list *recent;
718e3744 80
d62a17ae 81 /* Hook function which is executed when new prefix_list is added. */
82 void (*add_hook)(struct prefix_list *);
718e3744 83
d62a17ae 84 /* Hook function which is executed when prefix_list is deleted. */
85 void (*delete_hook)(struct prefix_list *);
7e111b6b 86
d62a17ae 87 /* number of bytes that have a trie level */
88 size_t trie_depth;
718e3744 89};
90
91/* Static structure of IPv4 prefix_list's master. */
d62a17ae 92static struct prefix_master prefix_master_ipv4 = {
93 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
718e3744 94};
95
718e3744 96/* Static structure of IPv6 prefix-list's master. */
d62a17ae 97static struct prefix_master prefix_master_ipv6 = {
98 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
718e3744 99};
718e3744 100
101/* Static structure of BGP ORF prefix_list's master. */
d62a17ae 102static struct prefix_master prefix_master_orf_v4 = {
103 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
c7da3d50
DL
104};
105
106/* Static structure of BGP ORF prefix_list's master. */
d62a17ae 107static struct prefix_master prefix_master_orf_v6 = {
108 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
718e3744 109};
6b0655a2 110
d62a17ae 111static struct prefix_master *prefix_master_get(afi_t afi, int orf)
718e3744 112{
d62a17ae 113 if (afi == AFI_IP)
114 return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4;
115 if (afi == AFI_IP6)
116 return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6;
117 return NULL;
718e3744 118}
119
d62a17ae 120const char *prefix_list_name(struct prefix_list *plist)
a38401b6 121{
d62a17ae 122 return plist->name;
a38401b6
DL
123}
124
718e3744 125/* Lookup prefix_list from list of prefix_list by name. */
d62a17ae 126static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
127 const char *name)
718e3744 128{
d62a17ae 129 struct prefix_list *plist;
130 struct prefix_master *master;
718e3744 131
d62a17ae 132 if (name == NULL)
133 return NULL;
718e3744 134
d62a17ae 135 master = prefix_master_get(afi, orf);
136 if (master == NULL)
137 return NULL;
718e3744 138
d62a17ae 139 for (plist = master->num.head; plist; plist = plist->next)
140 if (strcmp(plist->name, name) == 0)
141 return plist;
718e3744 142
d62a17ae 143 for (plist = master->str.head; plist; plist = plist->next)
144 if (strcmp(plist->name, name) == 0)
145 return plist;
718e3744 146
d62a17ae 147 return NULL;
718e3744 148}
149
d62a17ae 150struct prefix_list *prefix_list_lookup(afi_t afi, const char *name)
c7da3d50 151{
d62a17ae 152 return prefix_list_lookup_do(afi, 0, name);
c7da3d50
DL
153}
154
d62a17ae 155struct prefix_list *prefix_bgp_orf_lookup(afi_t afi, const char *name)
c7da3d50 156{
d62a17ae 157 return prefix_list_lookup_do(afi, 1, name);
c7da3d50
DL
158}
159
d62a17ae 160static struct prefix_list *prefix_list_new(void)
718e3744 161{
d62a17ae 162 struct prefix_list *new;
718e3744 163
d62a17ae 164 new = XCALLOC(MTYPE_PREFIX_LIST, sizeof(struct prefix_list));
165 return new;
718e3744 166}
167
d62a17ae 168static void prefix_list_free(struct prefix_list *plist)
718e3744 169{
d62a17ae 170 XFREE(MTYPE_PREFIX_LIST, plist);
718e3744 171}
172
d62a17ae 173static struct prefix_list_entry *prefix_list_entry_new(void)
718e3744 174{
d62a17ae 175 struct prefix_list_entry *new;
718e3744 176
d62a17ae 177 new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY,
178 sizeof(struct prefix_list_entry));
179 return new;
718e3744 180}
181
d62a17ae 182static void prefix_list_entry_free(struct prefix_list_entry *pentry)
718e3744 183{
d62a17ae 184 XFREE(MTYPE_PREFIX_LIST_ENTRY, pentry);
718e3744 185}
186
187/* Insert new prefix list to list of prefix_list. Each prefix_list
188 is sorted by the name. */
d62a17ae 189static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
190 const char *name)
191{
192 unsigned int i;
193 long number;
194 struct prefix_list *plist;
195 struct prefix_list *point;
196 struct prefix_list_list *list;
197 struct prefix_master *master;
198
199 master = prefix_master_get(afi, orf);
200 if (master == NULL)
201 return NULL;
202
203 /* Allocate new prefix_list and copy given name. */
204 plist = prefix_list_new();
205 plist->name = XSTRDUP(MTYPE_MPREFIX_LIST_STR, name);
206 plist->master = master;
207 plist->trie =
208 XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table));
209
210 /* If name is made by all digit character. We treat it as
211 number. */
212 for (number = 0, i = 0; i < strlen(name); i++) {
213 if (isdigit((int)name[i]))
214 number = (number * 10) + (name[i] - '0');
215 else
216 break;
217 }
98645ada 218
d62a17ae 219 /* In case of name is all digit character */
220 if (i == strlen(name)) {
221 plist->type = PREFIX_TYPE_NUMBER;
222
223 /* Set prefix_list to number list. */
224 list = &master->num;
225
226 for (point = list->head; point; point = point->next)
227 if (atol(point->name) >= number)
228 break;
229 } else {
230 plist->type = PREFIX_TYPE_STRING;
231
232 /* Set prefix_list to string list. */
233 list = &master->str;
234
235 /* Set point to insertion point. */
236 for (point = list->head; point; point = point->next)
237 if (strcmp(point->name, name) >= 0)
238 break;
239 }
240
241 /* In case of this is the first element of master. */
242 if (list->head == NULL) {
243 list->head = list->tail = plist;
244 return plist;
245 }
246
247 /* In case of insertion is made at the tail of access_list. */
248 if (point == NULL) {
249 plist->prev = list->tail;
250 list->tail->next = plist;
251 list->tail = plist;
252 return plist;
253 }
254
255 /* In case of insertion is made at the head of access_list. */
256 if (point == list->head) {
257 plist->next = list->head;
258 list->head->prev = plist;
259 list->head = plist;
260 return plist;
261 }
262
263 /* Insertion is made at middle of the access_list. */
264 plist->next = point;
265 plist->prev = point->prev;
266
267 if (point->prev)
268 point->prev->next = plist;
269 point->prev = plist;
270
271 return plist;
272}
273
274static struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name)
718e3744 275{
d62a17ae 276 struct prefix_list *plist;
277
278 plist = prefix_list_lookup_do(afi, orf, name);
718e3744 279
d62a17ae 280 if (plist == NULL)
281 plist = prefix_list_insert(afi, orf, name);
282 return plist;
283}
718e3744 284
d62a17ae 285static void prefix_list_trie_del(struct prefix_list *plist,
286 struct prefix_list_entry *pentry);
287
288/* Delete prefix-list from prefix_list_master and free it. */
289static void prefix_list_delete(struct prefix_list *plist)
290{
291 struct prefix_list_list *list;
292 struct prefix_master *master;
293 struct prefix_list_entry *pentry;
294 struct prefix_list_entry *next;
295
296 /* If prefix-list contain prefix_list_entry free all of it. */
297 for (pentry = plist->head; pentry; pentry = next) {
298 next = pentry->next;
299 prefix_list_trie_del(plist, pentry);
300 prefix_list_entry_free(pentry);
301 plist->count--;
302 }
718e3744 303
d62a17ae 304 master = plist->master;
718e3744 305
d62a17ae 306 if (plist->type == PREFIX_TYPE_NUMBER)
307 list = &master->num;
308 else
309 list = &master->str;
718e3744 310
d62a17ae 311 if (plist->next)
312 plist->next->prev = plist->prev;
313 else
314 list->tail = plist->prev;
718e3744 315
d62a17ae 316 if (plist->prev)
317 plist->prev->next = plist->next;
318 else
319 list->head = plist->next;
718e3744 320
d62a17ae 321 if (plist->desc)
322 XFREE(MTYPE_TMP, plist->desc);
718e3744 323
d62a17ae 324 /* Make sure master's recent changed prefix-list information is
325 cleared. */
326 master->recent = NULL;
518f0eb1 327
d62a17ae 328 route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED);
518f0eb1 329
d62a17ae 330 if (master->delete_hook)
331 (*master->delete_hook)(plist);
518f0eb1 332
d62a17ae 333 if (plist->name)
334 XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
7e111b6b 335
d62a17ae 336 XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie);
518f0eb1 337
d62a17ae 338 prefix_list_free(plist);
718e3744 339}
340
02ff83c5 341static struct prefix_list_entry *
d62a17ae 342prefix_list_entry_make(struct prefix *prefix, enum prefix_list_type type,
343 int seq, int le, int ge, int any)
718e3744 344{
d62a17ae 345 struct prefix_list_entry *pentry;
718e3744 346
d62a17ae 347 pentry = prefix_list_entry_new();
718e3744 348
d62a17ae 349 if (any)
350 pentry->any = 1;
718e3744 351
d62a17ae 352 prefix_copy(&pentry->prefix, prefix);
353 pentry->type = type;
354 pentry->seq = seq;
355 pentry->le = le;
356 pentry->ge = ge;
718e3744 357
d62a17ae 358 return pentry;
718e3744 359}
360
361/* Add hook function. */
d62a17ae 362void prefix_list_add_hook(void (*func)(struct prefix_list *plist))
718e3744 363{
d62a17ae 364 prefix_master_ipv4.add_hook = func;
365 prefix_master_ipv6.add_hook = func;
718e3744 366}
367
368/* Delete hook function. */
d62a17ae 369void prefix_list_delete_hook(void (*func)(struct prefix_list *plist))
718e3744 370{
d62a17ae 371 prefix_master_ipv4.delete_hook = func;
372 prefix_master_ipv6.delete_hook = func;
718e3744 373}
374
375/* Calculate new sequential number. */
d62a17ae 376static int prefix_new_seq_get(struct prefix_list *plist)
718e3744 377{
d62a17ae 378 int maxseq;
379 int newseq;
380 struct prefix_list_entry *pentry;
718e3744 381
d62a17ae 382 maxseq = newseq = 0;
718e3744 383
d62a17ae 384 for (pentry = plist->head; pentry; pentry = pentry->next) {
385 if (maxseq < pentry->seq)
386 maxseq = pentry->seq;
387 }
718e3744 388
d62a17ae 389 newseq = ((maxseq / 5) * 5) + 5;
390
391 return newseq;
718e3744 392}
393
394/* Return prefix list entry which has same seq number. */
d62a17ae 395static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist,
396 int seq)
718e3744 397{
d62a17ae 398 struct prefix_list_entry *pentry;
718e3744 399
d62a17ae 400 for (pentry = plist->head; pentry; pentry = pentry->next)
401 if (pentry->seq == seq)
402 return pentry;
403 return NULL;
718e3744 404}
405
02ff83c5 406static struct prefix_list_entry *
d62a17ae 407prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix,
408 enum prefix_list_type type, int seq, int le, int ge)
718e3744 409{
d62a17ae 410 struct prefix_list_entry *pentry;
718e3744 411
d62a17ae 412 for (pentry = plist->head; pentry; pentry = pentry->next)
413 if (prefix_same(&pentry->prefix, prefix)
414 && pentry->type == type) {
415 if (seq >= 0 && pentry->seq != seq)
416 continue;
718e3744 417
d62a17ae 418 if (pentry->le != le)
419 continue;
420 if (pentry->ge != ge)
421 continue;
718e3744 422
d62a17ae 423 return pentry;
424 }
718e3744 425
d62a17ae 426 return NULL;
718e3744 427}
428
d62a17ae 429static void trie_walk_affected(size_t validbits, struct pltrie_table *table,
430 uint8_t byte, struct prefix_list_entry *object,
431 void (*fn)(struct prefix_list_entry *object,
432 struct prefix_list_entry **updptr))
7e111b6b 433{
d62a17ae 434 uint8_t mask;
435 uint16_t bwalk;
7e111b6b 436
d62a17ae 437 if (validbits > PLC_BITS) {
438 fn(object, &table->entries[byte].final_chain);
439 return;
440 }
7e111b6b 441
d62a17ae 442 mask = (1 << (8 - validbits)) - 1;
443 for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) {
444 fn(object, &table->entries[bwalk].up_chain);
445 }
7e111b6b
DL
446}
447
d62a17ae 448static void trie_uninstall_fn(struct prefix_list_entry *object,
449 struct prefix_list_entry **updptr)
7e111b6b 450{
d62a17ae 451 for (; *updptr; updptr = &(*updptr)->next_best)
452 if (*updptr == object) {
453 *updptr = object->next_best;
454 break;
455 }
7e111b6b
DL
456}
457
d62a17ae 458static int trie_table_empty(struct pltrie_table *table)
7e111b6b 459{
d62a17ae 460 size_t i;
461 for (i = 0; i < PLC_LEN; i++)
462 if (table->entries[i].next_table || table->entries[i].up_chain)
463 return 0;
464 return 1;
465}
466
467static void prefix_list_trie_del(struct prefix_list *plist,
468 struct prefix_list_entry *pentry)
469{
470 size_t depth, maxdepth = plist->master->trie_depth;
471 uint8_t *bytes = &pentry->prefix.u.prefix;
472 size_t validbits = pentry->prefix.prefixlen;
473 struct pltrie_table *table, **tables[PLC_MAXLEVEL];
474
475 table = plist->trie;
476 for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
477 uint8_t byte = bytes[depth];
478 assert(table->entries[byte].next_table);
479
480 tables[depth + 1] = &table->entries[byte].next_table;
481 table = table->entries[byte].next_table;
482
483 validbits -= PLC_BITS;
484 }
485
486 trie_walk_affected(validbits, table, bytes[depth], pentry,
487 trie_uninstall_fn);
488
489 for (; depth > 0; depth--)
490 if (trie_table_empty(*tables[depth])) {
491 XFREE(MTYPE_PREFIX_LIST_TRIE, *tables[depth]);
492 *tables[depth] = NULL;
493 }
7e111b6b
DL
494}
495
d62a17ae 496
497static void prefix_list_entry_delete(struct prefix_list *plist,
498 struct prefix_list_entry *pentry,
499 int update_list)
7e111b6b 500{
d62a17ae 501 if (plist == NULL || pentry == NULL)
502 return;
503
504 prefix_list_trie_del(plist, pentry);
7e111b6b 505
d62a17ae 506 if (pentry->prev)
507 pentry->prev->next = pentry->next;
508 else
509 plist->head = pentry->next;
510 if (pentry->next)
511 pentry->next->prev = pentry->prev;
512 else
513 plist->tail = pentry->prev;
7e111b6b 514
d62a17ae 515 prefix_list_entry_free(pentry);
7e111b6b 516
d62a17ae 517 plist->count--;
7e111b6b 518
d62a17ae 519 if (update_list) {
520 route_map_notify_dependencies(plist->name,
521 RMAP_EVENT_PLIST_DELETED);
522 if (plist->master->delete_hook)
523 (*plist->master->delete_hook)(plist);
7e111b6b 524
d62a17ae 525 if (plist->head == NULL && plist->tail == NULL
526 && plist->desc == NULL)
527 prefix_list_delete(plist);
528 else
529 plist->master->recent = plist;
530 }
7e111b6b
DL
531}
532
d62a17ae 533static void trie_install_fn(struct prefix_list_entry *object,
534 struct prefix_list_entry **updptr)
535{
536 while (*updptr) {
537 if (*updptr == object)
538 return;
539 if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen)
540 break;
b4e55fc5
DL
541 if ((*updptr)->prefix.prefixlen == object->prefix.prefixlen
542 && (*updptr)->seq > object->seq)
d62a17ae 543 break;
544 updptr = &(*updptr)->next_best;
545 }
546
547 if (!object->next_best)
548 object->next_best = *updptr;
549 else
550 assert(object->next_best == *updptr || !*updptr);
551
552 *updptr = object;
553}
7e111b6b 554
d62a17ae 555static void prefix_list_trie_add(struct prefix_list *plist,
556 struct prefix_list_entry *pentry)
718e3744 557{
d62a17ae 558 size_t depth = plist->master->trie_depth;
559 uint8_t *bytes = &pentry->prefix.u.prefix;
560 size_t validbits = pentry->prefix.prefixlen;
561 struct pltrie_table *table;
562
563 table = plist->trie;
564 while (validbits > PLC_BITS && depth > 1) {
565 if (!table->entries[*bytes].next_table)
566 table->entries[*bytes].next_table =
567 XCALLOC(MTYPE_PREFIX_LIST_TRIE,
568 sizeof(struct pltrie_table));
569 table = table->entries[*bytes].next_table;
570 bytes++;
571 depth--;
572 validbits -= PLC_BITS;
573 }
a31ff449 574
d62a17ae 575 trie_walk_affected(validbits, table, *bytes, pentry, trie_install_fn);
576}
a31ff449 577
d62a17ae 578static void prefix_list_entry_add(struct prefix_list *plist,
579 struct prefix_list_entry *pentry)
580{
581 struct prefix_list_entry *replace;
582 struct prefix_list_entry *point;
718e3744 583
d62a17ae 584 /* Automatic asignment of seq no. */
585 if (pentry->seq == -1)
586 pentry->seq = prefix_new_seq_get(plist);
718e3744 587
d62a17ae 588 if (plist->tail && pentry->seq > plist->tail->seq)
589 point = NULL;
590 else {
591 /* Is there any same seq prefix list entry? */
592 replace = prefix_seq_check(plist, pentry->seq);
593 if (replace)
594 prefix_list_entry_delete(plist, replace, 0);
718e3744 595
d62a17ae 596 /* Check insert point. */
597 for (point = plist->head; point; point = point->next)
598 if (point->seq >= pentry->seq)
599 break;
600 }
601
602 /* In case of this is the first element of the list. */
603 pentry->next = point;
604
605 if (point) {
606 if (point->prev)
607 point->prev->next = pentry;
608 else
609 plist->head = pentry;
610
611 pentry->prev = point->prev;
612 point->prev = pentry;
613 } else {
614 if (plist->tail)
615 plist->tail->next = pentry;
616 else
617 plist->head = pentry;
618
619 pentry->prev = plist->tail;
620 plist->tail = pentry;
621 }
718e3744 622
d62a17ae 623 prefix_list_trie_add(plist, pentry);
624
625 /* Increment count. */
626 plist->count++;
627
628 /* Run hook function. */
629 if (plist->master->add_hook)
630 (*plist->master->add_hook)(plist);
631
632 route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_ADDED);
718e3744 633 plist->master->recent = plist;
718e3744 634}
635
636/* Return string of prefix_list_type. */
d62a17ae 637static const char *prefix_list_type_str(struct prefix_list_entry *pentry)
638{
639 switch (pentry->type) {
640 case PREFIX_PERMIT:
641 return "permit";
642 case PREFIX_DENY:
643 return "deny";
644 default:
645 return "";
646 }
647}
648
649static int prefix_list_entry_match(struct prefix_list_entry *pentry,
650 struct prefix *p)
651{
652 int ret;
653
654 ret = prefix_match(&pentry->prefix, p);
655 if (!ret)
656 return 0;
657
658 /* In case of le nor ge is specified, exact match is performed. */
659 if (!pentry->le && !pentry->ge) {
660 if (pentry->prefix.prefixlen != p->prefixlen)
661 return 0;
662 } else {
663 if (pentry->le)
664 if (p->prefixlen > pentry->le)
665 return 0;
666
667 if (pentry->ge)
668 if (p->prefixlen < pentry->ge)
669 return 0;
670 }
671 return 1;
672}
673
674enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object)
675{
676 struct prefix_list_entry *pentry, *pbest = NULL;
677
678 struct prefix *p = (struct prefix *)object;
679 uint8_t *byte = &p->u.prefix;
680 size_t depth;
681 size_t validbits = p->prefixlen;
682 struct pltrie_table *table;
683
684 if (plist == NULL)
685 return PREFIX_DENY;
686
687 if (plist->count == 0)
688 return PREFIX_PERMIT;
689
690 depth = plist->master->trie_depth;
691 table = plist->trie;
692 while (1) {
693 for (pentry = table->entries[*byte].up_chain; pentry;
694 pentry = pentry->next_best) {
695 if (pbest && pbest->seq < pentry->seq)
696 continue;
697 if (prefix_list_entry_match(pentry, p))
698 pbest = pentry;
699 }
700
701 if (validbits <= PLC_BITS)
702 break;
703 validbits -= PLC_BITS;
704
705 if (--depth) {
706 if (!table->entries[*byte].next_table)
707 break;
708
709 table = table->entries[*byte].next_table;
710 byte++;
711 continue;
712 }
713
714 for (pentry = table->entries[*byte].final_chain; pentry;
715 pentry = pentry->next_best) {
716 if (pbest && pbest->seq < pentry->seq)
717 continue;
718 if (prefix_list_entry_match(pentry, p))
719 pbest = pentry;
720 }
721 break;
722 }
723
724 if (pbest == NULL)
725 return PREFIX_DENY;
726
727 return pbest->type;
728}
729
730static void __attribute__((unused)) prefix_list_print(struct prefix_list *plist)
731{
732 struct prefix_list_entry *pentry;
733
734 if (plist == NULL)
735 return;
736
737 printf("ip prefix-list %s: %d entries\n", plist->name, plist->count);
738
739 for (pentry = plist->head; pentry; pentry = pentry->next) {
740 if (pentry->any)
741 printf("any %s\n", prefix_list_type_str(pentry));
742 else {
743 struct prefix *p;
744 char buf[BUFSIZ];
745
746 p = &pentry->prefix;
747
748 printf(" seq %u %s %s/%d", pentry->seq,
749 prefix_list_type_str(pentry),
750 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
751 p->prefixlen);
752 if (pentry->ge)
753 printf(" ge %d", pentry->ge);
754 if (pentry->le)
755 printf(" le %d", pentry->le);
756 printf("\n");
757 }
718e3744 758 }
718e3744 759}
6b0655a2 760
718e3744 761/* Retrun 1 when plist already include pentry policy. */
02ff83c5 762static struct prefix_list_entry *
d62a17ae 763prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new)
764{
765 size_t depth, maxdepth = plist->master->trie_depth;
766 uint8_t byte, *bytes = &new->prefix.u.prefix;
767 size_t validbits = new->prefix.prefixlen;
768 struct pltrie_table *table;
769 struct prefix_list_entry *pentry;
770 int seq = 0;
771
772 if (new->seq == -1)
773 seq = prefix_new_seq_get(plist);
774 else
775 seq = new->seq;
776
777 table = plist->trie;
778 for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
779 byte = bytes[depth];
780 if (!table->entries[byte].next_table)
781 return NULL;
782
783 table = table->entries[byte].next_table;
784 validbits -= PLC_BITS;
718e3744 785 }
718e3744 786
d62a17ae 787 byte = bytes[depth];
788 if (validbits > PLC_BITS)
789 pentry = table->entries[byte].final_chain;
790 else
791 pentry = table->entries[byte].up_chain;
792
793 for (; pentry; pentry = pentry->next_best) {
794 if (prefix_same(&pentry->prefix, &new->prefix)
795 && pentry->type == new->type && pentry->le == new->le
796 && pentry->ge == new->ge && pentry->seq != seq)
797 return pentry;
798 }
799 return NULL;
800}
801
802static int vty_invalid_prefix_range(struct vty *vty, const char *prefix)
803{
804 vty_out(vty,
805 "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n",
806 prefix);
807 return CMD_WARNING_CONFIG_FAILED;
808}
809
810static int vty_prefix_list_install(struct vty *vty, afi_t afi, const char *name,
811 const char *seq, const char *typestr,
812 const char *prefix, const char *ge,
813 const char *le)
814{
815 int ret;
816 enum prefix_list_type type;
817 struct prefix_list *plist;
818 struct prefix_list_entry *pentry;
819 struct prefix_list_entry *dup;
820 struct prefix p, p_tmp;
821 int any = 0;
822 int seqnum = -1;
823 int lenum = 0;
824 int genum = 0;
825
826 /* Sequential number. */
827 if (seq)
828 seqnum = atoi(seq);
829
830 /* ge and le number */
831 if (ge)
832 genum = atoi(ge);
833 if (le)
834 lenum = atoi(le);
835
836 /* Check filter type. */
837 if (strncmp("permit", typestr, 1) == 0)
838 type = PREFIX_PERMIT;
839 else if (strncmp("deny", typestr, 1) == 0)
840 type = PREFIX_DENY;
841 else {
842 vty_out(vty, "%% prefix type must be permit or deny\n");
843 return CMD_WARNING_CONFIG_FAILED;
718e3744 844 }
ddb13fd3 845
d62a17ae 846 /* "any" is special token for matching any IPv4 addresses. */
847 switch (afi) {
848 case AFI_IP:
849 if (strncmp("any", prefix, strlen(prefix)) == 0) {
850 ret = str2prefix_ipv4("0.0.0.0/0",
851 (struct prefix_ipv4 *)&p);
852 genum = 0;
853 lenum = IPV4_MAX_BITLEN;
854 any = 1;
855 } else
856 ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p);
857
858 if (ret <= 0) {
859 vty_out(vty, "%% Malformed IPv4 prefix\n");
860 return CMD_WARNING_CONFIG_FAILED;
861 }
862
863 /* make a copy to verify prefix matches mask length */
864 prefix_copy(&p_tmp, &p);
865 apply_mask_ipv4((struct prefix_ipv4 *)&p_tmp);
866
867 break;
868 case AFI_IP6:
869 if (strncmp("any", prefix, strlen(prefix)) == 0) {
870 ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p);
871 genum = 0;
872 lenum = IPV6_MAX_BITLEN;
873 any = 1;
874 } else
875 ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p);
876
877 if (ret <= 0) {
878 vty_out(vty, "%% Malformed IPv6 prefix\n");
879 return CMD_WARNING_CONFIG_FAILED;
880 }
881
882 /* make a copy to verify prefix matches mask length */
883 prefix_copy(&p_tmp, &p);
884 apply_mask_ipv6((struct prefix_ipv6 *)&p_tmp);
885
886 break;
887 case AFI_L2VPN:
888 default:
889 vty_out(vty, "%% Unrecognized AFI (%d)\n", afi);
890 return CMD_WARNING_CONFIG_FAILED;
891 break;
718e3744 892 }
718e3744 893
d62a17ae 894 /* If prefix has bits not under the mask, adjust it to fit */
895 if (!prefix_same(&p_tmp, &p)) {
896 char buf[PREFIX2STR_BUFFER];
897 char buf_tmp[PREFIX2STR_BUFFER];
898 prefix2str(&p, buf, sizeof(buf));
899 prefix2str(&p_tmp, buf_tmp, sizeof(buf_tmp));
900 zlog_warn(
901 "Prefix-list %s prefix changed from %s to %s to match length",
902 name, buf, buf_tmp);
903 p = p_tmp;
718e3744 904 }
ddb13fd3 905
d62a17ae 906 /* ge and le check. */
907 if (genum && (genum <= p.prefixlen))
908 return vty_invalid_prefix_range(vty, prefix);
909
910 if (lenum && (lenum <= p.prefixlen))
911 return vty_invalid_prefix_range(vty, prefix);
912
913 if (lenum && (genum > lenum))
914 return vty_invalid_prefix_range(vty, prefix);
915
916 if (genum && (lenum == (afi == AFI_IP ? 32 : 128)))
917 lenum = 0;
918
919 /* Get prefix_list with name. */
920 plist = prefix_list_get(afi, 0, name);
921
922 /* Make prefix entry. */
923 pentry = prefix_list_entry_make(&p, type, seqnum, lenum, genum, any);
924
925 /* Check same policy. */
926 dup = prefix_entry_dup_check(plist, pentry);
927
928 if (dup) {
929 prefix_list_entry_free(pentry);
930 return CMD_SUCCESS;
718e3744 931 }
718e3744 932
d62a17ae 933 /* Install new filter to the access_list. */
934 prefix_list_entry_add(plist, pentry);
935
936 return CMD_SUCCESS;
937}
938
939static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi,
940 const char *name, const char *seq,
941 const char *typestr, const char *prefix,
942 const char *ge, const char *le)
943{
944 int ret;
945 enum prefix_list_type type;
946 struct prefix_list *plist;
947 struct prefix_list_entry *pentry;
948 struct prefix p;
949 int seqnum = -1;
950 int lenum = 0;
951 int genum = 0;
952
953 /* Check prefix list name. */
954 plist = prefix_list_lookup(afi, name);
955 if (!plist) {
956 vty_out(vty, "%% Can't find specified prefix-list\n");
957 return CMD_WARNING_CONFIG_FAILED;
718e3744 958 }
d62a17ae 959
960 /* Only prefix-list name specified, delete the entire prefix-list. */
961 if (seq == NULL && typestr == NULL && prefix == NULL && ge == NULL
962 && le == NULL) {
963 prefix_list_delete(plist);
964 return CMD_SUCCESS;
718e3744 965 }
718e3744 966
d62a17ae 967 /* We must have, at a minimum, both the type and prefix here */
968 if ((typestr == NULL) || (prefix == NULL)) {
969 vty_out(vty, "%% Both prefix and type required\n");
970 return CMD_WARNING_CONFIG_FAILED;
718e3744 971 }
718e3744 972
d62a17ae 973 /* Check sequence number. */
974 if (seq)
975 seqnum = atoi(seq);
976
977 /* ge and le number */
978 if (ge)
979 genum = atoi(ge);
980 if (le)
981 lenum = atoi(le);
982
983 /* Check of filter type. */
984 if (strncmp("permit", typestr, 1) == 0)
985 type = PREFIX_PERMIT;
986 else if (strncmp("deny", typestr, 1) == 0)
987 type = PREFIX_DENY;
988 else {
989 vty_out(vty, "%% prefix type must be permit or deny\n");
990 return CMD_WARNING_CONFIG_FAILED;
991 }
718e3744 992
d62a17ae 993 /* "any" is special token for matching any IPv4 addresses. */
994 if (afi == AFI_IP) {
995 if (strncmp("any", prefix, strlen(prefix)) == 0) {
996 ret = str2prefix_ipv4("0.0.0.0/0",
997 (struct prefix_ipv4 *)&p);
998 genum = 0;
999 lenum = IPV4_MAX_BITLEN;
1000 } else
1001 ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p);
1002
1003 if (ret <= 0) {
1004 vty_out(vty, "%% Malformed IPv4 prefix\n");
1005 return CMD_WARNING_CONFIG_FAILED;
1006 }
1007 } else if (afi == AFI_IP6) {
1008 if (strncmp("any", prefix, strlen(prefix)) == 0) {
1009 ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p);
1010 genum = 0;
1011 lenum = IPV6_MAX_BITLEN;
1012 } else
1013 ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p);
1014
1015 if (ret <= 0) {
1016 vty_out(vty, "%% Malformed IPv6 prefix\n");
1017 return CMD_WARNING_CONFIG_FAILED;
1018 }
1019 }
718e3744 1020
d62a17ae 1021 /* Lookup prefix entry. */
1022 pentry =
1023 prefix_list_entry_lookup(plist, &p, type, seqnum, lenum, genum);
718e3744 1024
d62a17ae 1025 if (pentry == NULL) {
1026 vty_out(vty, "%% Can't find specified prefix-list\n");
1027 return CMD_WARNING_CONFIG_FAILED;
1028 }
1029
1030 /* Install new filter to the access_list. */
1031 prefix_list_entry_delete(plist, pentry, 1);
1032
1033 return CMD_SUCCESS;
718e3744 1034}
1035
d62a17ae 1036static int vty_prefix_list_desc_unset(struct vty *vty, afi_t afi,
1037 const char *name)
718e3744 1038{
d62a17ae 1039 struct prefix_list *plist;
718e3744 1040
d62a17ae 1041 plist = prefix_list_lookup(afi, name);
1042 if (!plist) {
1043 vty_out(vty, "%% Can't find specified prefix-list\n");
1044 return CMD_WARNING_CONFIG_FAILED;
1045 }
718e3744 1046
d62a17ae 1047 if (plist->desc) {
1048 XFREE(MTYPE_TMP, plist->desc);
1049 plist->desc = NULL;
1050 }
718e3744 1051
d62a17ae 1052 if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL)
1053 prefix_list_delete(plist);
718e3744 1054
d62a17ae 1055 return CMD_SUCCESS;
718e3744 1056}
1057
d62a17ae 1058enum display_type {
1059 normal_display,
1060 summary_display,
1061 detail_display,
1062 sequential_display,
1063 longer_display,
1064 first_match_display
718e3744 1065};
1066
d62a17ae 1067static void vty_show_prefix_entry(struct vty *vty, afi_t afi,
1068 struct prefix_list *plist,
1069 struct prefix_master *master,
1070 enum display_type dtype, int seqnum)
1071{
1072 struct prefix_list_entry *pentry;
1073
1074 /* Print the name of the protocol */
1075 vty_out(vty, "%s: ", frr_protoname);
1076
1077 if (dtype == normal_display) {
1078 vty_out(vty, "ip%s prefix-list %s: %d entries\n",
1079 afi == AFI_IP ? "" : "v6", plist->name, plist->count);
1080 if (plist->desc)
1081 vty_out(vty, " Description: %s\n", plist->desc);
1082 } else if (dtype == summary_display || dtype == detail_display) {
1083 vty_out(vty, "ip%s prefix-list %s:\n",
1084 afi == AFI_IP ? "" : "v6", plist->name);
1085
1086 if (plist->desc)
1087 vty_out(vty, " Description: %s\n", plist->desc);
1088
1089 vty_out(vty,
1090 " count: %d, range entries: %d, sequences: %u - %u\n",
1091 plist->count, plist->rangecount,
1092 plist->head ? plist->head->seq : 0,
1093 plist->tail ? plist->tail->seq : 0);
718e3744 1094 }
718e3744 1095
d62a17ae 1096 if (dtype != summary_display) {
1097 for (pentry = plist->head; pentry; pentry = pentry->next) {
1098 if (dtype == sequential_display
1099 && pentry->seq != seqnum)
1100 continue;
718e3744 1101
d62a17ae 1102 vty_out(vty, " ");
718e3744 1103
d62a17ae 1104 if (master->seqnum)
1105 vty_out(vty, "seq %u ", pentry->seq);
718e3744 1106
d62a17ae 1107 vty_out(vty, "%s ", prefix_list_type_str(pentry));
718e3744 1108
d62a17ae 1109 if (pentry->any)
1110 vty_out(vty, "any");
1111 else {
1112 struct prefix *p = &pentry->prefix;
1113 char buf[BUFSIZ];
1114
1115 vty_out(vty, "%s/%d",
1116 inet_ntop(p->family, &p->u.prefix, buf,
1117 BUFSIZ),
1118 p->prefixlen);
1119
1120 if (pentry->ge)
1121 vty_out(vty, " ge %d", pentry->ge);
1122 if (pentry->le)
1123 vty_out(vty, " le %d", pentry->le);
1124 }
1125
1126 if (dtype == detail_display
1127 || dtype == sequential_display)
1128 vty_out(vty, " (hit count: %ld, refcount: %ld)",
1129 pentry->hitcnt, pentry->refcnt);
1130
1131 vty_out(vty, "\n");
1132 }
718e3744 1133 }
718e3744 1134}
1135
d62a17ae 1136static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
1137 const char *seq, enum display_type dtype)
1138{
1139 struct prefix_list *plist;
1140 struct prefix_master *master;
1141 int seqnum = 0;
1142
1143 master = prefix_master_get(afi, 0);
1144 if (master == NULL)
1145 return CMD_WARNING;
1146
1147 if (seq)
1148 seqnum = atoi(seq);
1149
1150 if (name) {
1151 plist = prefix_list_lookup(afi, name);
1152 if (!plist) {
1153 vty_out(vty, "%% Can't find specified prefix-list\n");
1154 return CMD_WARNING;
1155 }
1156 vty_show_prefix_entry(vty, afi, plist, master, dtype, seqnum);
1157 } else {
1158 if (dtype == detail_display || dtype == summary_display) {
1159 if (master->recent)
1160 vty_out(vty,
1161 "Prefix-list with the last deletion/insertion: %s\n",
1162 master->recent->name);
1163 }
1164
1165 for (plist = master->num.head; plist; plist = plist->next)
1166 vty_show_prefix_entry(vty, afi, plist, master, dtype,
1167 seqnum);
1168
1169 for (plist = master->str.head; plist; plist = plist->next)
1170 vty_show_prefix_entry(vty, afi, plist, master, dtype,
1171 seqnum);
1172 }
718e3744 1173
d62a17ae 1174 return CMD_SUCCESS;
1175}
718e3744 1176
d62a17ae 1177static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
1178 const char *name, const char *prefix,
1179 enum display_type type)
1180{
1181 struct prefix_list *plist;
1182 struct prefix_list_entry *pentry;
1183 struct prefix p;
1184 int ret;
1185 int match;
718e3744 1186
d62a17ae 1187 plist = prefix_list_lookup(afi, name);
1188 if (!plist) {
1189 vty_out(vty, "%% Can't find specified prefix-list\n");
1190 return CMD_WARNING;
718e3744 1191 }
1192
d62a17ae 1193 ret = str2prefix(prefix, &p);
1194 if (ret <= 0) {
1195 vty_out(vty, "%% prefix is malformed\n");
1196 return CMD_WARNING;
718e3744 1197 }
1198
d62a17ae 1199 for (pentry = plist->head; pentry; pentry = pentry->next) {
1200 match = 0;
1201
1202 if (type == normal_display || type == first_match_display)
1203 if (prefix_same(&p, &pentry->prefix))
1204 match = 1;
1205
1206 if (type == longer_display)
1207 if (prefix_match(&p, &pentry->prefix))
1208 match = 1;
1209
1210 if (match) {
1211 vty_out(vty, " seq %u %s ", pentry->seq,
1212 prefix_list_type_str(pentry));
1213
1214 if (pentry->any)
1215 vty_out(vty, "any");
1216 else {
1217 struct prefix *p = &pentry->prefix;
1218 char buf[BUFSIZ];
1219
1220 vty_out(vty, "%s/%d",
1221 inet_ntop(p->family, &p->u.prefix, buf,
1222 BUFSIZ),
1223 p->prefixlen);
1224
1225 if (pentry->ge)
1226 vty_out(vty, " ge %d", pentry->ge);
1227 if (pentry->le)
1228 vty_out(vty, " le %d", pentry->le);
1229 }
1230
1231 if (type == normal_display
1232 || type == first_match_display)
1233 vty_out(vty, " (hit count: %ld, refcount: %ld)",
1234 pentry->hitcnt, pentry->refcnt);
1235
1236 vty_out(vty, "\n");
1237
1238 if (type == first_match_display)
1239 return CMD_SUCCESS;
1240 }
718e3744 1241 }
d62a17ae 1242 return CMD_SUCCESS;
1243}
1244
1245static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
1246 const char *prefix)
1247{
1248 struct prefix_master *master;
1249 struct prefix_list *plist;
1250 struct prefix_list_entry *pentry;
1251 int ret;
1252 struct prefix p;
1253
1254 master = prefix_master_get(afi, 0);
1255 if (master == NULL)
1256 return CMD_WARNING;
1257
1258 if (name == NULL && prefix == NULL) {
1259 for (plist = master->num.head; plist; plist = plist->next)
1260 for (pentry = plist->head; pentry;
1261 pentry = pentry->next)
1262 pentry->hitcnt = 0;
1263
1264 for (plist = master->str.head; plist; plist = plist->next)
1265 for (pentry = plist->head; pentry;
1266 pentry = pentry->next)
1267 pentry->hitcnt = 0;
1268 } else {
1269 plist = prefix_list_lookup(afi, name);
1270 if (!plist) {
1271 vty_out(vty, "%% Can't find specified prefix-list\n");
1272 return CMD_WARNING;
1273 }
1274
1275 if (prefix) {
1276 ret = str2prefix(prefix, &p);
1277 if (ret <= 0) {
1278 vty_out(vty, "%% prefix is malformed\n");
1279 return CMD_WARNING;
1280 }
1281 }
1282
1283 for (pentry = plist->head; pentry; pentry = pentry->next) {
1284 if (prefix) {
1285 if (prefix_match(&pentry->prefix, &p))
1286 pentry->hitcnt = 0;
1287 } else
1288 pentry->hitcnt = 0;
1289 }
1290 }
1291 return CMD_SUCCESS;
718e3744 1292}
6b0655a2 1293
6cdff321
DL
1294#ifndef VTYSH_EXTRACT_PL
1295#include "plist_clippy.c"
1296#endif
1297
1298DEFPY (ip_prefix_list,
1299 ip_prefix_list_cmd,
1300 "ip prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
1301 IP_STR
718e3744 1302 PREFIX_LIST_STR
1303 "Name of a prefix list\n"
1304 "sequence number of an entry\n"
1305 "Sequence number\n"
1306 "Specify packets to reject\n"
1307 "Specify packets to forward\n"
6cdff321
DL
1308 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1309 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1310 "Minimum prefix length to be matched\n"
1311 "Minimum prefix length\n"
718e3744 1312 "Maximum prefix length to be matched\n"
1313 "Maximum prefix length\n")
1314{
d62a17ae 1315 return vty_prefix_list_install(vty, AFI_IP, prefix_list, seq_str,
1316 action, dest, ge_str, le_str);
718e3744 1317}
1318
6cdff321
DL
1319DEFPY (no_ip_prefix_list,
1320 no_ip_prefix_list_cmd,
1321 "no ip prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
1322 NO_STR
1323 IP_STR
718e3744 1324 PREFIX_LIST_STR
1325 "Name of a prefix list\n"
1326 "sequence number of an entry\n"
1327 "Sequence number\n"
1328 "Specify packets to reject\n"
1329 "Specify packets to forward\n"
6cdff321
DL
1330 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1331 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
718e3744 1332 "Minimum prefix length to be matched\n"
6cdff321
DL
1333 "Minimum prefix length\n"
1334 "Maximum prefix length to be matched\n"
1335 "Maximum prefix length\n")
718e3744 1336{
d62a17ae 1337 return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, seq_str,
1338 action, dest, ge_str, le_str);
718e3744 1339}
1340
6cdff321
DL
1341DEFPY (no_ip_prefix_list_all,
1342 no_ip_prefix_list_all_cmd,
1343 "no ip prefix-list WORD",
718e3744 1344 NO_STR
6cdff321 1345 IP_STR
718e3744 1346 PREFIX_LIST_STR
1347 "Name of a prefix list\n")
1348{
d62a17ae 1349 return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, NULL, NULL,
1350 NULL, NULL, NULL);
718e3744 1351}
1352
6cdff321
DL
1353DEFPY (ip_prefix_list_sequence_number,
1354 ip_prefix_list_sequence_number_cmd,
1355 "[no] ip prefix-list sequence-number",
718e3744 1356 NO_STR
6cdff321 1357 IP_STR
718e3744 1358 PREFIX_LIST_STR
6cdff321 1359 "Include/exclude sequence numbers in NVGEN\n")
718e3744 1360{
d62a17ae 1361 prefix_master_ipv4.seqnum = no ? 0 : 1;
1362 return CMD_SUCCESS;
718e3744 1363}
1364
6cdff321
DL
1365DEFUN (ip_prefix_list_description,
1366 ip_prefix_list_description_cmd,
1367 "ip prefix-list WORD description LINE...",
1368 IP_STR
718e3744 1369 PREFIX_LIST_STR
1370 "Name of a prefix list\n"
6cdff321
DL
1371 "Prefix-list specific description\n"
1372 "Up to 80 characters describing this prefix-list\n")
718e3744 1373{
d62a17ae 1374 int idx_word = 2;
1375 int idx_line = 4;
1376 struct prefix_list *plist;
1377
1378 plist = prefix_list_get(AFI_IP, 0, argv[idx_word]->arg);
6cdff321 1379
d62a17ae 1380 if (plist->desc) {
1381 XFREE(MTYPE_TMP, plist->desc);
1382 plist->desc = NULL;
1383 }
1384 plist->desc = argv_concat(argv, argc, idx_line);
6cdff321 1385
d62a17ae 1386 return CMD_SUCCESS;
718e3744 1387}
1388
6cdff321
DL
1389DEFUN (no_ip_prefix_list_description,
1390 no_ip_prefix_list_description_cmd,
1391 "no ip prefix-list WORD description",
718e3744 1392 NO_STR
6cdff321 1393 IP_STR
718e3744 1394 PREFIX_LIST_STR
1395 "Name of a prefix list\n"
6cdff321 1396 "Prefix-list specific description\n")
718e3744 1397{
d62a17ae 1398 int idx_word = 3;
1399 return vty_prefix_list_desc_unset(vty, AFI_IP, argv[idx_word]->arg);
718e3744 1400}
1401
6cdff321
DL
1402/* ALIAS_FIXME */
1403DEFUN (no_ip_prefix_list_description_comment,
1404 no_ip_prefix_list_description_comment_cmd,
1405 "no ip prefix-list WORD description LINE...",
718e3744 1406 NO_STR
6cdff321 1407 IP_STR
718e3744 1408 PREFIX_LIST_STR
1409 "Name of a prefix list\n"
6cdff321
DL
1410 "Prefix-list specific description\n"
1411 "Up to 80 characters describing this prefix-list\n")
718e3744 1412{
d62a17ae 1413 return no_ip_prefix_list_description(self, vty, argc, argv);
718e3744 1414}
1415
6cdff321
DL
1416DEFPY (show_ip_prefix_list,
1417 show_ip_prefix_list_cmd,
1418 "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1419 SHOW_STR
1420 IP_STR
718e3744 1421 PREFIX_LIST_STR
1422 "Name of a prefix list\n"
6cdff321
DL
1423 "sequence number of an entry\n"
1424 "Sequence number\n")
718e3744 1425{
d62a17ae 1426 enum display_type dtype = normal_display;
1427 if (dseq)
1428 dtype = sequential_display;
6cdff321 1429
d62a17ae 1430 return vty_show_prefix_list(vty, AFI_IP, prefix_list, arg_str, dtype);
718e3744 1431}
1432
6cdff321
DL
1433DEFPY (show_ip_prefix_list_prefix,
1434 show_ip_prefix_list_prefix_cmd,
1435 "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
1436 SHOW_STR
1437 IP_STR
718e3744 1438 PREFIX_LIST_STR
1439 "Name of a prefix list\n"
6cdff321
DL
1440 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1441 "Lookup longer prefix\n"
1442 "First matched prefix\n")
718e3744 1443{
d62a17ae 1444 enum display_type dtype = normal_display;
1445 if (dl)
1446 dtype = longer_display;
1447 else if (dfm)
1448 dtype = first_match_display;
6cdff321 1449
d62a17ae 1450 return vty_show_prefix_list_prefix(vty, AFI_IP, prefix_list, prefix_str,
1451 dtype);
718e3744 1452}
1453
6cdff321
DL
1454DEFPY (show_ip_prefix_list_summary,
1455 show_ip_prefix_list_summary_cmd,
1456 "show ip prefix-list summary [WORD$prefix_list]",
1457 SHOW_STR
1458 IP_STR
718e3744 1459 PREFIX_LIST_STR
6cdff321
DL
1460 "Summary of prefix lists\n"
1461 "Name of a prefix list\n")
718e3744 1462{
d62a17ae 1463 return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
1464 summary_display);
718e3744 1465}
1466
6cdff321
DL
1467DEFPY (show_ip_prefix_list_detail,
1468 show_ip_prefix_list_detail_cmd,
1469 "show ip prefix-list detail [WORD$prefix_list]",
1470 SHOW_STR
1471 IP_STR
1472 PREFIX_LIST_STR
1473 "Detail of prefix lists\n"
1474 "Name of a prefix list\n")
1475{
d62a17ae 1476 return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
1477 detail_display);
6cdff321
DL
1478}
1479
1480DEFPY (clear_ip_prefix_list,
1481 clear_ip_prefix_list_cmd,
1482 "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
1483 CLEAR_STR
1484 IP_STR
718e3744 1485 PREFIX_LIST_STR
1486 "Name of a prefix list\n"
6cdff321 1487 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
718e3744 1488{
d62a17ae 1489 return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str);
6cdff321
DL
1490}
1491
1492DEFPY (ipv6_prefix_list,
1493 ipv6_prefix_list_cmd,
1494 "ipv6 prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
718e3744 1495 IPV6_STR
1496 PREFIX_LIST_STR
1497 "Name of a prefix list\n"
1498 "sequence number of an entry\n"
1499 "Sequence number\n"
1500 "Specify packets to reject\n"
1501 "Specify packets to forward\n"
6cdff321 1502 "Any prefix match. Same as \"::0/0 le 128\"\n"
718e3744 1503 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1504 "Maximum prefix length to be matched\n"
6cdff321
DL
1505 "Maximum prefix length\n"
1506 "Minimum prefix length to be matched\n"
1507 "Minimum prefix length\n")
718e3744 1508{
d62a17ae 1509 return vty_prefix_list_install(vty, AFI_IP6, prefix_list, seq_str,
1510 action, dest, ge_str, le_str);
718e3744 1511}
1512
6cdff321
DL
1513DEFPY (no_ipv6_prefix_list,
1514 no_ipv6_prefix_list_cmd,
1515 "no ipv6 prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
718e3744 1516 NO_STR
1517 IPV6_STR
1518 PREFIX_LIST_STR
1519 "Name of a prefix list\n"
1520 "sequence number of an entry\n"
1521 "Sequence number\n"
1522 "Specify packets to reject\n"
1523 "Specify packets to forward\n"
6cdff321 1524 "Any prefix match. Same as \"::0/0 le 128\"\n"
718e3744 1525 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1526 "Maximum prefix length to be matched\n"
1527 "Maximum prefix length\n"
1528 "Minimum prefix length to be matched\n"
1529 "Minimum prefix length\n")
1530{
d62a17ae 1531 return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, seq_str,
1532 action, dest, ge_str, le_str);
718e3744 1533}
1534
6cdff321
DL
1535DEFPY (no_ipv6_prefix_list_all,
1536 no_ipv6_prefix_list_all_cmd,
1537 "no ipv6 prefix-list WORD",
1538 NO_STR
718e3744 1539 IPV6_STR
1540 PREFIX_LIST_STR
6cdff321 1541 "Name of a prefix list\n")
718e3744 1542{
d62a17ae 1543 return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, NULL, NULL,
1544 NULL, NULL, NULL);
718e3744 1545}
1546
6cdff321
DL
1547DEFPY (ipv6_prefix_list_sequence_number,
1548 ipv6_prefix_list_sequence_number_cmd,
1549 "[no] ipv6 prefix-list sequence-number",
718e3744 1550 NO_STR
1551 IPV6_STR
1552 PREFIX_LIST_STR
1553 "Include/exclude sequence numbers in NVGEN\n")
1554{
d62a17ae 1555 prefix_master_ipv6.seqnum = no ? 0 : 1;
1556 return CMD_SUCCESS;
718e3744 1557}
1558
1559DEFUN (ipv6_prefix_list_description,
1560 ipv6_prefix_list_description_cmd,
e961923c 1561 "ipv6 prefix-list WORD description LINE...",
718e3744 1562 IPV6_STR
1563 PREFIX_LIST_STR
1564 "Name of a prefix list\n"
1565 "Prefix-list specific description\n"
1566 "Up to 80 characters describing this prefix-list\n")
1567{
d62a17ae 1568 int idx_word = 2;
1569 int iddx_line = 4;
1570 struct prefix_list *plist;
718e3744 1571
d62a17ae 1572 plist = prefix_list_get(AFI_IP6, 0, argv[idx_word]->arg);
1573
1574 if (plist->desc) {
1575 XFREE(MTYPE_TMP, plist->desc);
1576 plist->desc = NULL;
1577 }
1578 plist->desc = argv_concat(argv, argc, iddx_line);
718e3744 1579
d62a17ae 1580 return CMD_SUCCESS;
c349116d 1581}
718e3744 1582
1583DEFUN (no_ipv6_prefix_list_description,
1584 no_ipv6_prefix_list_description_cmd,
1585 "no ipv6 prefix-list WORD description",
1586 NO_STR
1587 IPV6_STR
1588 PREFIX_LIST_STR
1589 "Name of a prefix list\n"
1590 "Prefix-list specific description\n")
1591{
d62a17ae 1592 int idx_word = 3;
1593 return vty_prefix_list_desc_unset(vty, AFI_IP6, argv[idx_word]->arg);
718e3744 1594}
1595
d862bffb
QY
1596/* ALIAS_FIXME */
1597DEFUN (no_ipv6_prefix_list_description_comment,
1598 no_ipv6_prefix_list_description_comment_cmd,
1599 "no ipv6 prefix-list WORD description LINE...",
1600 NO_STR
1601 IPV6_STR
1602 PREFIX_LIST_STR
1603 "Name of a prefix list\n"
1604 "Prefix-list specific description\n"
1605 "Up to 80 characters describing this prefix-list\n")
1606{
d62a17ae 1607 return no_ipv6_prefix_list_description(self, vty, argc, argv);
d862bffb
QY
1608}
1609
718e3744 1610
6cdff321 1611DEFPY (show_ipv6_prefix_list,
718e3744 1612 show_ipv6_prefix_list_cmd,
6cdff321 1613 "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
718e3744 1614 SHOW_STR
1615 IPV6_STR
1616 PREFIX_LIST_STR
1617 "Name of a prefix list\n"
1618 "sequence number of an entry\n"
7111c1a0 1619 "Sequence number\n")
718e3744 1620{
d62a17ae 1621 enum display_type dtype = normal_display;
1622 if (dseq)
1623 dtype = sequential_display;
718e3744 1624
d62a17ae 1625 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, arg_str, dtype);
718e3744 1626}
1627
6cdff321
DL
1628DEFPY (show_ipv6_prefix_list_prefix,
1629 show_ipv6_prefix_list_prefix_cmd,
1630 "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
718e3744 1631 SHOW_STR
1632 IPV6_STR
1633 PREFIX_LIST_STR
1634 "Name of a prefix list\n"
1635 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
6cdff321 1636 "Lookup longer prefix\n"
718e3744 1637 "First matched prefix\n")
1638{
d62a17ae 1639 enum display_type dtype = normal_display;
1640 if (dl)
1641 dtype = longer_display;
1642 else if (dfm)
1643 dtype = first_match_display;
718e3744 1644
d62a17ae 1645 return vty_show_prefix_list_prefix(vty, AFI_IP6, prefix_list,
1646 prefix_str, dtype);
718e3744 1647}
1648
6cdff321
DL
1649DEFPY (show_ipv6_prefix_list_summary,
1650 show_ipv6_prefix_list_summary_cmd,
1651 "show ipv6 prefix-list summary [WORD$prefix-list]",
718e3744 1652 SHOW_STR
1653 IPV6_STR
1654 PREFIX_LIST_STR
1655 "Summary of prefix lists\n"
1656 "Name of a prefix list\n")
1657{
d62a17ae 1658 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
1659 summary_display);
718e3744 1660}
1661
6cdff321 1662DEFPY (show_ipv6_prefix_list_detail,
718e3744 1663 show_ipv6_prefix_list_detail_cmd,
6cdff321 1664 "show ipv6 prefix-list detail [WORD$prefix-list]",
718e3744 1665 SHOW_STR
1666 IPV6_STR
1667 PREFIX_LIST_STR
1668 "Detail of prefix lists\n"
1669 "Name of a prefix list\n")
1670{
d62a17ae 1671 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
1672 detail_display);
718e3744 1673}
1674
6cdff321 1675DEFPY (clear_ipv6_prefix_list,
718e3744 1676 clear_ipv6_prefix_list_cmd,
6cdff321 1677 "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
718e3744 1678 CLEAR_STR
1679 IPV6_STR
1680 PREFIX_LIST_STR
1681 "Name of a prefix list\n"
1682 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
1683{
d62a17ae 1684 return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str);
718e3744 1685}
6b0655a2 1686
718e3744 1687/* Configuration write function. */
d62a17ae 1688static int config_write_prefix_afi(afi_t afi, struct vty *vty)
1689{
1690 struct prefix_list *plist;
1691 struct prefix_list_entry *pentry;
1692 struct prefix_master *master;
1693 int write = 0;
1694
1695 master = prefix_master_get(afi, 0);
1696 if (master == NULL)
1697 return 0;
718e3744 1698
d62a17ae 1699 if (!master->seqnum) {
1700 vty_out(vty, "no ip%s prefix-list sequence-number\n",
1701 afi == AFI_IP ? "" : "v6");
1702 vty_out(vty, "!\n");
718e3744 1703 }
d62a17ae 1704
1705 for (plist = master->num.head; plist; plist = plist->next) {
1706 if (plist->desc) {
1707 vty_out(vty, "ip%s prefix-list %s description %s\n",
1708 afi == AFI_IP ? "" : "v6", plist->name,
1709 plist->desc);
1710 write++;
1711 }
1712
1713 for (pentry = plist->head; pentry; pentry = pentry->next) {
1714 vty_out(vty, "ip%s prefix-list %s ",
1715 afi == AFI_IP ? "" : "v6", plist->name);
1716
1717 if (master->seqnum)
1718 vty_out(vty, "seq %u ", pentry->seq);
1719
1720 vty_out(vty, "%s ", prefix_list_type_str(pentry));
1721
1722 if (pentry->any)
1723 vty_out(vty, "any");
1724 else {
1725 struct prefix *p = &pentry->prefix;
1726 char buf[BUFSIZ];
1727
1728 vty_out(vty, "%s/%d",
1729 inet_ntop(p->family, &p->u.prefix, buf,
1730 BUFSIZ),
1731 p->prefixlen);
1732
1733 if (pentry->ge)
1734 vty_out(vty, " ge %d", pentry->ge);
1735 if (pentry->le)
1736 vty_out(vty, " le %d", pentry->le);
1737 }
1738 vty_out(vty, "\n");
1739 write++;
1740 }
1741 /* vty_out (vty, "!\n"); */
718e3744 1742 }
1743
d62a17ae 1744 for (plist = master->str.head; plist; plist = plist->next) {
1745 if (plist->desc) {
1746 vty_out(vty, "ip%s prefix-list %s description %s\n",
1747 afi == AFI_IP ? "" : "v6", plist->name,
1748 plist->desc);
1749 write++;
1750 }
1751
1752 for (pentry = plist->head; pentry; pentry = pentry->next) {
1753 vty_out(vty, "ip%s prefix-list %s ",
1754 afi == AFI_IP ? "" : "v6", plist->name);
1755
1756 if (master->seqnum)
1757 vty_out(vty, "seq %u ", pentry->seq);
1758
1759 vty_out(vty, "%s", prefix_list_type_str(pentry));
1760
1761 if (pentry->any)
1762 vty_out(vty, " any");
1763 else {
1764 struct prefix *p = &pentry->prefix;
1765 char buf[BUFSIZ];
1766
1767 vty_out(vty, " %s/%d",
1768 inet_ntop(p->family, &p->u.prefix, buf,
1769 BUFSIZ),
1770 p->prefixlen);
1771
1772 if (pentry->ge)
1773 vty_out(vty, " ge %d", pentry->ge);
1774 if (pentry->le)
1775 vty_out(vty, " le %d", pentry->le);
1776 }
1777 vty_out(vty, "\n");
1778 write++;
1779 }
718e3744 1780 }
d62a17ae 1781
1782 return write;
718e3744 1783}
1784
d62a17ae 1785struct stream *prefix_bgp_orf_entry(struct stream *s, struct prefix_list *plist,
1786 u_char init_flag, u_char permit_flag,
1787 u_char deny_flag)
718e3744 1788{
d62a17ae 1789 struct prefix_list_entry *pentry;
718e3744 1790
d62a17ae 1791 if (!plist)
1792 return s;
718e3744 1793
d62a17ae 1794 for (pentry = plist->head; pentry; pentry = pentry->next) {
1795 u_char flag = init_flag;
1796 struct prefix *p = &pentry->prefix;
718e3744 1797
d62a17ae 1798 flag |= (pentry->type == PREFIX_PERMIT ? permit_flag
1799 : deny_flag);
1800 stream_putc(s, flag);
1801 stream_putl(s, (u_int32_t)pentry->seq);
1802 stream_putc(s, (u_char)pentry->ge);
1803 stream_putc(s, (u_char)pentry->le);
1804 stream_put_prefix(s, p);
1805 }
718e3744 1806
d62a17ae 1807 return s;
718e3744 1808}
1809
d62a17ae 1810int prefix_bgp_orf_set(char *name, afi_t afi, struct orf_prefix *orfp,
1811 int permit, int set)
718e3744 1812{
d62a17ae 1813 struct prefix_list *plist;
1814 struct prefix_list_entry *pentry;
718e3744 1815
d62a17ae 1816 /* ge and le value check */
1817 if (orfp->ge && orfp->ge <= orfp->p.prefixlen)
1818 return CMD_WARNING_CONFIG_FAILED;
1819 if (orfp->le && orfp->le <= orfp->p.prefixlen)
1820 return CMD_WARNING_CONFIG_FAILED;
1821 if (orfp->le && orfp->ge > orfp->le)
1822 return CMD_WARNING_CONFIG_FAILED;
718e3744 1823
d62a17ae 1824 if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128))
1825 orfp->le = 0;
718e3744 1826
d62a17ae 1827 plist = prefix_list_get(afi, 1, name);
1828 if (!plist)
1829 return CMD_WARNING_CONFIG_FAILED;
718e3744 1830
d62a17ae 1831 if (set) {
1832 pentry = prefix_list_entry_make(
1833 &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
1834 orfp->seq, orfp->le, orfp->ge, 0);
718e3744 1835
d62a17ae 1836 if (prefix_entry_dup_check(plist, pentry)) {
1837 prefix_list_entry_free(pentry);
1838 return CMD_WARNING_CONFIG_FAILED;
1839 }
718e3744 1840
d62a17ae 1841 prefix_list_entry_add(plist, pentry);
1842 } else {
1843 pentry = prefix_list_entry_lookup(
1844 plist, &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
1845 orfp->seq, orfp->le, orfp->ge);
718e3744 1846
d62a17ae 1847 if (!pentry)
1848 return CMD_WARNING_CONFIG_FAILED;
718e3744 1849
d62a17ae 1850 prefix_list_entry_delete(plist, pentry, 1);
1851 }
718e3744 1852
d62a17ae 1853 return CMD_SUCCESS;
718e3744 1854}
1855
d62a17ae 1856void prefix_bgp_orf_remove_all(afi_t afi, char *name)
718e3744 1857{
d62a17ae 1858 struct prefix_list *plist;
718e3744 1859
d62a17ae 1860 plist = prefix_bgp_orf_lookup(afi, name);
1861 if (plist)
1862 prefix_list_delete(plist);
718e3744 1863}
1864
1865/* return prefix count */
d62a17ae 1866int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name,
1867 u_char use_json)
1868{
1869 struct prefix_list *plist;
1870 struct prefix_list_entry *pentry;
1871 json_object *json = NULL;
1872 json_object *json_prefix = NULL;
1873 json_object *json_list = NULL;
1874
1875 plist = prefix_bgp_orf_lookup(afi, name);
1876 if (!plist)
1877 return 0;
1878
1879 if (!vty)
1880 return plist->count;
1881
1882 if (use_json) {
1883 json = json_object_new_object();
1884 json_prefix = json_object_new_object();
1885 json_list = json_object_new_object();
1886
1887 json_object_int_add(json_prefix, "prefixListCounter",
1888 plist->count);
1889 json_object_string_add(json_prefix, "prefixListName",
1890 plist->name);
1891
1892 for (pentry = plist->head; pentry; pentry = pentry->next) {
1893 struct prefix *p = &pentry->prefix;
1894 char buf_a[BUFSIZ];
1895 char buf_b[BUFSIZ];
1896
1897 sprintf(buf_a, "%s/%d",
1898 inet_ntop(p->family, &p->u.prefix, buf_b,
1899 BUFSIZ),
1900 p->prefixlen);
1901
1902 json_object_int_add(json_list, "seq", pentry->seq);
1903 json_object_string_add(json_list, "seqPrefixListType",
1904 prefix_list_type_str(pentry));
1905
1906 if (pentry->ge)
1907 json_object_int_add(json_list, "ge",
1908 pentry->ge);
1909 if (pentry->le)
1910 json_object_int_add(json_list, "le",
1911 pentry->le);
1912
1913 json_object_object_add(json_prefix, buf_a, json_list);
1914 }
1915 if (afi == AFI_IP)
1916 json_object_object_add(json, "ipPrefixList",
1917 json_prefix);
1918 else
1919 json_object_object_add(json, "ipv6PrefixList",
1920 json_prefix);
1921
9d303b37
DL
1922 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1923 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 1924 json_object_free(json);
1925 } else {
1926 vty_out(vty, "ip%s prefix-list %s: %d entries\n",
1927 afi == AFI_IP ? "" : "v6", plist->name, plist->count);
1928
1929 for (pentry = plist->head; pentry; pentry = pentry->next) {
1930 struct prefix *p = &pentry->prefix;
1931 char buf[BUFSIZ];
1932
1933 vty_out(vty, " seq %u %s %s/%d", pentry->seq,
1934 prefix_list_type_str(pentry),
1935 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
1936 p->prefixlen);
1937
1938 if (pentry->ge)
1939 vty_out(vty, " ge %d", pentry->ge);
1940 if (pentry->le)
1941 vty_out(vty, " le %d", pentry->le);
1942
1943 vty_out(vty, "\n");
1944 }
1945 }
1946 return plist->count;
1947}
1948
1949static void prefix_list_reset_afi(afi_t afi, int orf)
1950{
1951 struct prefix_list *plist;
1952 struct prefix_list *next;
1953 struct prefix_master *master;
1954
1955 master = prefix_master_get(afi, orf);
1956 if (master == NULL)
1957 return;
1958
1959 for (plist = master->num.head; plist; plist = next) {
1960 next = plist->next;
1961 prefix_list_delete(plist);
1962 }
1963 for (plist = master->str.head; plist; plist = next) {
1964 next = plist->next;
1965 prefix_list_delete(plist);
1966 }
1967
1968 assert(master->num.head == NULL);
1969 assert(master->num.tail == NULL);
1970
1971 assert(master->str.head == NULL);
1972 assert(master->str.tail == NULL);
1973
1974 master->seqnum = 1;
1975 master->recent = NULL;
718e3744 1976}
1977
1978
1979/* Prefix-list node. */
d62a17ae 1980static struct cmd_node prefix_node = {PREFIX_NODE,
1981 "", /* Prefix list has no interface. */
1982 1};
718e3744 1983
d62a17ae 1984static int config_write_prefix_ipv4(struct vty *vty)
718e3744 1985{
d62a17ae 1986 return config_write_prefix_afi(AFI_IP, vty);
718e3744 1987}
1988
d62a17ae 1989static void plist_autocomplete_afi(afi_t afi, vector comps,
1990 struct cmd_token *token)
70d44c5c 1991{
d62a17ae 1992 struct prefix_list *plist;
1993 struct prefix_master *master;
70d44c5c 1994
d62a17ae 1995 master = prefix_master_get(afi, 0);
1996 if (master == NULL)
1997 return;
70d44c5c 1998
d62a17ae 1999 for (plist = master->str.head; plist; plist = plist->next)
2000 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
2001 for (plist = master->num.head; plist; plist = plist->next)
2002 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
70d44c5c
DL
2003}
2004
d62a17ae 2005static void plist_autocomplete(vector comps, struct cmd_token *token)
70d44c5c 2006{
d62a17ae 2007 plist_autocomplete_afi(AFI_IP, comps, token);
2008 plist_autocomplete_afi(AFI_IP6, comps, token);
70d44c5c
DL
2009}
2010
2011static const struct cmd_variable_handler plist_var_handlers[] = {
d62a17ae 2012 {/* "prefix-list WORD" */
2013 .varname = "prefix_list",
2014 .completions = plist_autocomplete},
2015 {.completions = NULL}};
70d44c5c
DL
2016
2017
d62a17ae 2018static void prefix_list_init_ipv4(void)
718e3744 2019{
d62a17ae 2020 install_node(&prefix_node, config_write_prefix_ipv4);
718e3744 2021
d62a17ae 2022 install_element(CONFIG_NODE, &ip_prefix_list_cmd);
2023 install_element(CONFIG_NODE, &no_ip_prefix_list_cmd);
2024 install_element(CONFIG_NODE, &no_ip_prefix_list_all_cmd);
718e3744 2025
d62a17ae 2026 install_element(CONFIG_NODE, &ip_prefix_list_description_cmd);
2027 install_element(CONFIG_NODE, &no_ip_prefix_list_description_cmd);
2028 install_element(CONFIG_NODE,
2029 &no_ip_prefix_list_description_comment_cmd);
718e3744 2030
d62a17ae 2031 install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd);
718e3744 2032
d62a17ae 2033 install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
2034 install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd);
2035 install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
2036 install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
718e3744 2037
d62a17ae 2038 install_element(ENABLE_NODE, &clear_ip_prefix_list_cmd);
718e3744 2039}
2040
718e3744 2041/* Prefix-list node. */
d62a17ae 2042static struct cmd_node prefix_ipv6_node = {
2043 PREFIX_IPV6_NODE, "", /* Prefix list has no interface. */
2044 1};
718e3744 2045
d62a17ae 2046static int config_write_prefix_ipv6(struct vty *vty)
718e3744 2047{
d62a17ae 2048 return config_write_prefix_afi(AFI_IP6, vty);
718e3744 2049}
2050
d62a17ae 2051static void prefix_list_init_ipv6(void)
718e3744 2052{
d62a17ae 2053 install_node(&prefix_ipv6_node, config_write_prefix_ipv6);
718e3744 2054
d62a17ae 2055 install_element(CONFIG_NODE, &ipv6_prefix_list_cmd);
2056 install_element(CONFIG_NODE, &no_ipv6_prefix_list_cmd);
2057 install_element(CONFIG_NODE, &no_ipv6_prefix_list_all_cmd);
718e3744 2058
d62a17ae 2059 install_element(CONFIG_NODE, &ipv6_prefix_list_description_cmd);
2060 install_element(CONFIG_NODE, &no_ipv6_prefix_list_description_cmd);
2061 install_element(CONFIG_NODE,
2062 &no_ipv6_prefix_list_description_comment_cmd);
718e3744 2063
d62a17ae 2064 install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd);
718e3744 2065
d62a17ae 2066 install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
2067 install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd);
2068 install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
2069 install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
718e3744 2070
d62a17ae 2071 install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd);
718e3744 2072}
718e3744 2073
d62a17ae 2074void prefix_list_init()
718e3744 2075{
d62a17ae 2076 cmd_variable_handler_register(plist_var_handlers);
70d44c5c 2077
d62a17ae 2078 prefix_list_init_ipv4();
2079 prefix_list_init_ipv6();
718e3744 2080}
2081
d62a17ae 2082void prefix_list_reset()
718e3744 2083{
d62a17ae 2084 prefix_list_reset_afi(AFI_IP, 0);
2085 prefix_list_reset_afi(AFI_IP6, 0);
2086 prefix_list_reset_afi(AFI_IP, 1);
2087 prefix_list_reset_afi(AFI_IP6, 1);
718e3744 2088}