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