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