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