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