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