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