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