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