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