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