1 /* Prefix list functions.
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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
27 #include "sockunion.h"
34 #include "plist_int.h"
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")
41 /* not currently changeable, code assumes bytes further down */
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) */
50 struct pltrie_table
*next_table
;
51 struct prefix_list_entry
*final_chain
;
54 struct prefix_list_entry
*up_chain
;
58 struct pltrie_entry entries
[PLC_LEN
];
61 /* List of struct prefix_list. */
62 struct prefix_list_list
{
63 struct prefix_list
*head
;
64 struct prefix_list
*tail
;
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
;
72 /* List of prefix_list which name is string. */
73 struct prefix_list_list str
;
75 /* Whether sequential number is used. */
78 /* The latest update. */
79 struct prefix_list
*recent
;
81 /* Hook function which is executed when new prefix_list is added. */
82 void (*add_hook
)(struct prefix_list
*);
84 /* Hook function which is executed when prefix_list is deleted. */
85 void (*delete_hook
)(struct prefix_list
*);
87 /* number of bytes that have a trie level */
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
,
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
,
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
,
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
,
111 static struct prefix_master
*prefix_master_get(afi_t afi
, int orf
)
114 return orf
? &prefix_master_orf_v4
: &prefix_master_ipv4
;
116 return orf
? &prefix_master_orf_v6
: &prefix_master_ipv6
;
120 const char *prefix_list_name(struct prefix_list
*plist
)
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
,
129 struct prefix_list
*plist
;
130 struct prefix_master
*master
;
135 master
= prefix_master_get(afi
, orf
);
139 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
140 if (strcmp(plist
->name
, name
) == 0)
143 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
144 if (strcmp(plist
->name
, name
) == 0)
150 struct prefix_list
*prefix_list_lookup(afi_t afi
, const char *name
)
152 return prefix_list_lookup_do(afi
, 0, name
);
155 struct prefix_list
*prefix_bgp_orf_lookup(afi_t afi
, const char *name
)
157 return prefix_list_lookup_do(afi
, 1, name
);
160 static struct prefix_list
*prefix_list_new(void)
162 struct prefix_list
*new;
164 new = XCALLOC(MTYPE_PREFIX_LIST
, sizeof(struct prefix_list
));
168 static void prefix_list_free(struct prefix_list
*plist
)
170 XFREE(MTYPE_PREFIX_LIST
, plist
);
173 static struct prefix_list_entry
*prefix_list_entry_new(void)
175 struct prefix_list_entry
*new;
177 new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY
,
178 sizeof(struct prefix_list_entry
));
182 static void prefix_list_entry_free(struct prefix_list_entry
*pentry
)
184 XFREE(MTYPE_PREFIX_LIST_ENTRY
, pentry
);
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
,
194 struct prefix_list
*plist
;
195 struct prefix_list
*point
;
196 struct prefix_list_list
*list
;
197 struct prefix_master
*master
;
199 master
= prefix_master_get(afi
, orf
);
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
;
208 XCALLOC(MTYPE_PREFIX_LIST_TRIE
, sizeof(struct pltrie_table
));
210 /* If name is made by all digit character. We treat it as
212 for (number
= 0, i
= 0; i
< strlen(name
); i
++) {
213 if (isdigit((int)name
[i
]))
214 number
= (number
* 10) + (name
[i
] - '0');
219 /* In case of name is all digit character */
220 if (i
== strlen(name
)) {
221 plist
->type
= PREFIX_TYPE_NUMBER
;
223 /* Set prefix_list to number list. */
226 for (point
= list
->head
; point
; point
= point
->next
)
227 if (atol(point
->name
) >= number
)
230 plist
->type
= PREFIX_TYPE_STRING
;
232 /* Set prefix_list to string list. */
235 /* Set point to insertion point. */
236 for (point
= list
->head
; point
; point
= point
->next
)
237 if (strcmp(point
->name
, name
) >= 0)
241 /* In case of this is the first element of master. */
242 if (list
->head
== NULL
) {
243 list
->head
= list
->tail
= plist
;
247 /* In case of insertion is made at the tail of access_list. */
249 plist
->prev
= list
->tail
;
250 list
->tail
->next
= plist
;
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
;
263 /* Insertion is made at middle of the access_list. */
265 plist
->prev
= point
->prev
;
268 point
->prev
->next
= plist
;
274 static struct prefix_list
*prefix_list_get(afi_t afi
, int orf
, const char *name
)
276 struct prefix_list
*plist
;
278 plist
= prefix_list_lookup_do(afi
, orf
, name
);
281 plist
= prefix_list_insert(afi
, orf
, name
);
285 static void prefix_list_trie_del(struct prefix_list
*plist
,
286 struct prefix_list_entry
*pentry
);
288 /* Delete prefix-list from prefix_list_master and free it. */
289 static void prefix_list_delete(struct prefix_list
*plist
)
291 struct prefix_list_list
*list
;
292 struct prefix_master
*master
;
293 struct prefix_list_entry
*pentry
;
294 struct prefix_list_entry
*next
;
296 /* If prefix-list contain prefix_list_entry free all of it. */
297 for (pentry
= plist
->head
; pentry
; pentry
= next
) {
299 prefix_list_trie_del(plist
, pentry
);
300 prefix_list_entry_free(pentry
);
304 master
= plist
->master
;
306 if (plist
->type
== PREFIX_TYPE_NUMBER
)
312 plist
->next
->prev
= plist
->prev
;
314 list
->tail
= plist
->prev
;
317 plist
->prev
->next
= plist
->next
;
319 list
->head
= plist
->next
;
322 XFREE(MTYPE_TMP
, plist
->desc
);
324 /* Make sure master's recent changed prefix-list information is
326 master
->recent
= NULL
;
328 route_map_notify_dependencies(plist
->name
, RMAP_EVENT_PLIST_DELETED
);
330 if (master
->delete_hook
)
331 (*master
->delete_hook
)(plist
);
334 XFREE(MTYPE_MPREFIX_LIST_STR
, plist
->name
);
336 XFREE(MTYPE_PREFIX_LIST_TRIE
, plist
->trie
);
338 prefix_list_free(plist
);
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
)
345 struct prefix_list_entry
*pentry
;
347 pentry
= prefix_list_entry_new();
352 prefix_copy(&pentry
->prefix
, prefix
);
361 /* Add hook function. */
362 void prefix_list_add_hook(void (*func
)(struct prefix_list
*plist
))
364 prefix_master_ipv4
.add_hook
= func
;
365 prefix_master_ipv6
.add_hook
= func
;
368 /* Delete hook function. */
369 void prefix_list_delete_hook(void (*func
)(struct prefix_list
*plist
))
371 prefix_master_ipv4
.delete_hook
= func
;
372 prefix_master_ipv6
.delete_hook
= func
;
375 /* Calculate new sequential number. */
376 static int prefix_new_seq_get(struct prefix_list
*plist
)
380 struct prefix_list_entry
*pentry
;
384 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
385 if (maxseq
< pentry
->seq
)
386 maxseq
= pentry
->seq
;
389 newseq
= ((maxseq
/ 5) * 5) + 5;
394 /* Return prefix list entry which has same seq number. */
395 static struct prefix_list_entry
*prefix_seq_check(struct prefix_list
*plist
,
398 struct prefix_list_entry
*pentry
;
400 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
)
401 if (pentry
->seq
== seq
)
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
)
410 struct prefix_list_entry
*pentry
;
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
)
418 if (pentry
->le
!= le
)
420 if (pentry
->ge
!= ge
)
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
))
437 if (validbits
> PLC_BITS
) {
438 fn(object
, &table
->entries
[byte
].final_chain
);
442 mask
= (1 << (8 - validbits
)) - 1;
443 for (bwalk
= byte
& ~mask
; bwalk
<= byte
+ mask
; bwalk
++) {
444 fn(object
, &table
->entries
[bwalk
].up_chain
);
448 static void trie_uninstall_fn(struct prefix_list_entry
*object
,
449 struct prefix_list_entry
**updptr
)
451 for (; *updptr
; updptr
= &(*updptr
)->next_best
)
452 if (*updptr
== object
) {
453 *updptr
= object
->next_best
;
458 static int trie_table_empty(struct pltrie_table
*table
)
461 for (i
= 0; i
< PLC_LEN
; i
++)
462 if (table
->entries
[i
].next_table
|| table
->entries
[i
].up_chain
)
467 static void prefix_list_trie_del(struct prefix_list
*plist
,
468 struct prefix_list_entry
*pentry
)
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
];
476 for (depth
= 0; validbits
> PLC_BITS
&& depth
< maxdepth
- 1; depth
++) {
477 uint8_t byte
= bytes
[depth
];
478 assert(table
->entries
[byte
].next_table
);
480 tables
[depth
+ 1] = &table
->entries
[byte
].next_table
;
481 table
= table
->entries
[byte
].next_table
;
483 validbits
-= PLC_BITS
;
486 trie_walk_affected(validbits
, table
, bytes
[depth
], pentry
,
489 for (; depth
> 0; depth
--)
490 if (trie_table_empty(*tables
[depth
])) {
491 XFREE(MTYPE_PREFIX_LIST_TRIE
, *tables
[depth
]);
492 *tables
[depth
] = NULL
;
497 static void prefix_list_entry_delete(struct prefix_list
*plist
,
498 struct prefix_list_entry
*pentry
,
501 if (plist
== NULL
|| pentry
== NULL
)
504 prefix_list_trie_del(plist
, pentry
);
507 pentry
->prev
->next
= pentry
->next
;
509 plist
->head
= pentry
->next
;
511 pentry
->next
->prev
= pentry
->prev
;
513 plist
->tail
= pentry
->prev
;
515 prefix_list_entry_free(pentry
);
520 route_map_notify_dependencies(plist
->name
,
521 RMAP_EVENT_PLIST_DELETED
);
522 if (plist
->master
->delete_hook
)
523 (*plist
->master
->delete_hook
)(plist
);
525 if (plist
->head
== NULL
&& plist
->tail
== NULL
526 && plist
->desc
== NULL
)
527 prefix_list_delete(plist
);
529 plist
->master
->recent
= plist
;
533 static void trie_install_fn(struct prefix_list_entry
*object
,
534 struct prefix_list_entry
**updptr
)
537 if (*updptr
== object
)
539 if ((*updptr
)->prefix
.prefixlen
< object
->prefix
.prefixlen
)
541 if ((*updptr
)->seq
> object
->seq
)
543 updptr
= &(*updptr
)->next_best
;
546 if (!object
->next_best
)
547 object
->next_best
= *updptr
;
549 assert(object
->next_best
== *updptr
|| !*updptr
);
554 static void prefix_list_trie_add(struct prefix_list
*plist
,
555 struct prefix_list_entry
*pentry
)
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
;
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
;
571 validbits
-= PLC_BITS
;
574 trie_walk_affected(validbits
, table
, *bytes
, pentry
, trie_install_fn
);
577 static void prefix_list_entry_add(struct prefix_list
*plist
,
578 struct prefix_list_entry
*pentry
)
580 struct prefix_list_entry
*replace
;
581 struct prefix_list_entry
*point
;
583 /* Automatic asignment of seq no. */
584 if (pentry
->seq
== -1)
585 pentry
->seq
= prefix_new_seq_get(plist
);
587 if (plist
->tail
&& pentry
->seq
> plist
->tail
->seq
)
590 /* Is there any same seq prefix list entry? */
591 replace
= prefix_seq_check(plist
, pentry
->seq
);
593 prefix_list_entry_delete(plist
, replace
, 0);
595 /* Check insert point. */
596 for (point
= plist
->head
; point
; point
= point
->next
)
597 if (point
->seq
>= pentry
->seq
)
601 /* In case of this is the first element of the list. */
602 pentry
->next
= point
;
606 point
->prev
->next
= pentry
;
608 plist
->head
= pentry
;
610 pentry
->prev
= point
->prev
;
611 point
->prev
= pentry
;
614 plist
->tail
->next
= pentry
;
616 plist
->head
= pentry
;
618 pentry
->prev
= plist
->tail
;
619 plist
->tail
= pentry
;
622 prefix_list_trie_add(plist
, pentry
);
624 /* Increment count. */
627 /* Run hook function. */
628 if (plist
->master
->add_hook
)
629 (*plist
->master
->add_hook
)(plist
);
631 route_map_notify_dependencies(plist
->name
, RMAP_EVENT_PLIST_ADDED
);
632 plist
->master
->recent
= plist
;
635 /* Return string of prefix_list_type. */
636 static const char *prefix_list_type_str(struct prefix_list_entry
*pentry
)
638 switch (pentry
->type
) {
648 static int prefix_list_entry_match(struct prefix_list_entry
*pentry
,
653 ret
= prefix_match(&pentry
->prefix
, p
);
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
)
663 if (p
->prefixlen
> pentry
->le
)
667 if (p
->prefixlen
< pentry
->ge
)
673 enum prefix_list_type
prefix_list_apply(struct prefix_list
*plist
, void *object
)
675 struct prefix_list_entry
*pentry
, *pbest
= NULL
;
677 struct prefix
*p
= (struct prefix
*)object
;
678 uint8_t *byte
= &p
->u
.prefix
;
680 size_t validbits
= p
->prefixlen
;
681 struct pltrie_table
*table
;
686 if (plist
->count
== 0)
687 return PREFIX_PERMIT
;
689 depth
= plist
->master
->trie_depth
;
692 for (pentry
= table
->entries
[*byte
].up_chain
; pentry
;
693 pentry
= pentry
->next_best
) {
694 if (pbest
&& pbest
->seq
< pentry
->seq
)
696 if (prefix_list_entry_match(pentry
, p
))
700 if (validbits
<= PLC_BITS
)
702 validbits
-= PLC_BITS
;
705 if (!table
->entries
[*byte
].next_table
)
708 table
= table
->entries
[*byte
].next_table
;
713 for (pentry
= table
->entries
[*byte
].final_chain
; pentry
;
714 pentry
= pentry
->next_best
) {
715 if (pbest
&& pbest
->seq
< pentry
->seq
)
717 if (prefix_list_entry_match(pentry
, p
))
729 static void __attribute__((unused
)) prefix_list_print(struct prefix_list
*plist
)
731 struct prefix_list_entry
*pentry
;
736 printf("ip prefix-list %s: %d entries\n", plist
->name
, plist
->count
);
738 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
740 printf("any %s\n", prefix_list_type_str(pentry
));
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
),
752 printf(" ge %d", pentry
->ge
);
754 printf(" le %d", pentry
->le
);
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)
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
;
772 seq
= prefix_new_seq_get(plist
);
777 for (depth
= 0; validbits
> PLC_BITS
&& depth
< maxdepth
- 1; depth
++) {
779 if (!table
->entries
[byte
].next_table
)
782 table
= table
->entries
[byte
].next_table
;
783 validbits
-= PLC_BITS
;
787 if (validbits
> PLC_BITS
)
788 pentry
= table
->entries
[byte
].final_chain
;
790 pentry
= table
->entries
[byte
].up_chain
;
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
)
801 static int vty_invalid_prefix_range(struct vty
*vty
, const char *prefix
)
804 "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n",
806 return CMD_WARNING_CONFIG_FAILED
;
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
,
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
;
825 /* Sequential number. */
829 /* ge and le number */
835 /* Check filter type. */
836 if (strncmp("permit", typestr
, 1) == 0)
837 type
= PREFIX_PERMIT
;
838 else if (strncmp("deny", typestr
, 1) == 0)
841 vty_out(vty
, "%% prefix type must be permit or deny\n");
842 return CMD_WARNING_CONFIG_FAILED
;
845 /* "any" is special token for matching any IPv4 addresses. */
848 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
849 ret
= str2prefix_ipv4("0.0.0.0/0",
850 (struct prefix_ipv4
*)&p
);
852 lenum
= IPV4_MAX_BITLEN
;
855 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
858 vty_out(vty
, "%% Malformed IPv4 prefix\n");
859 return CMD_WARNING_CONFIG_FAILED
;
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
);
868 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
869 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
871 lenum
= IPV6_MAX_BITLEN
;
874 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
877 vty_out(vty
, "%% Malformed IPv6 prefix\n");
878 return CMD_WARNING_CONFIG_FAILED
;
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
);
888 vty_out(vty
, "%% Unrecognized AFI (%d)\n", afi
);
889 return CMD_WARNING_CONFIG_FAILED
;
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
));
900 "Prefix-list %s prefix changed from %s to %s to match length",
905 /* ge and le check. */
906 if (genum
&& (genum
<= p
.prefixlen
))
907 return vty_invalid_prefix_range(vty
, prefix
);
909 if (lenum
&& (lenum
<= p
.prefixlen
))
910 return vty_invalid_prefix_range(vty
, prefix
);
912 if (lenum
&& (genum
> lenum
))
913 return vty_invalid_prefix_range(vty
, prefix
);
915 if (genum
&& (lenum
== (afi
== AFI_IP
? 32 : 128)))
918 /* Get prefix_list with name. */
919 plist
= prefix_list_get(afi
, 0, name
);
921 /* Make prefix entry. */
922 pentry
= prefix_list_entry_make(&p
, type
, seqnum
, lenum
, genum
, any
);
924 /* Check same policy. */
925 dup
= prefix_entry_dup_check(plist
, pentry
);
928 prefix_list_entry_free(pentry
);
932 /* Install new filter to the access_list. */
933 prefix_list_entry_add(plist
, pentry
);
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
)
944 enum prefix_list_type type
;
945 struct prefix_list
*plist
;
946 struct prefix_list_entry
*pentry
;
952 /* Check prefix list name. */
953 plist
= prefix_list_lookup(afi
, name
);
955 vty_out(vty
, "%% Can't find specified prefix-list\n");
956 return CMD_WARNING_CONFIG_FAILED
;
959 /* Only prefix-list name specified, delete the entire prefix-list. */
960 if (seq
== NULL
&& typestr
== NULL
&& prefix
== NULL
&& ge
== NULL
962 prefix_list_delete(plist
);
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
;
972 /* Check sequence number. */
976 /* ge and le number */
982 /* Check of filter type. */
983 if (strncmp("permit", typestr
, 1) == 0)
984 type
= PREFIX_PERMIT
;
985 else if (strncmp("deny", typestr
, 1) == 0)
988 vty_out(vty
, "%% prefix type must be permit or deny\n");
989 return CMD_WARNING_CONFIG_FAILED
;
992 /* "any" is special token for matching any IPv4 addresses. */
994 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
995 ret
= str2prefix_ipv4("0.0.0.0/0",
996 (struct prefix_ipv4
*)&p
);
998 lenum
= IPV4_MAX_BITLEN
;
1000 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
1003 vty_out(vty
, "%% Malformed IPv4 prefix\n");
1004 return CMD_WARNING_CONFIG_FAILED
;
1006 } else if (afi
== AFI_IP6
) {
1007 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
1008 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
1010 lenum
= IPV6_MAX_BITLEN
;
1012 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
1015 vty_out(vty
, "%% Malformed IPv6 prefix\n");
1016 return CMD_WARNING_CONFIG_FAILED
;
1020 /* Lookup prefix entry. */
1022 prefix_list_entry_lookup(plist
, &p
, type
, seqnum
, lenum
, genum
);
1024 if (pentry
== NULL
) {
1025 vty_out(vty
, "%% Can't find specified prefix-list\n");
1026 return CMD_WARNING_CONFIG_FAILED
;
1029 /* Install new filter to the access_list. */
1030 prefix_list_entry_delete(plist
, pentry
, 1);
1035 static int vty_prefix_list_desc_unset(struct vty
*vty
, afi_t afi
,
1038 struct prefix_list
*plist
;
1040 plist
= prefix_list_lookup(afi
, name
);
1042 vty_out(vty
, "%% Can't find specified prefix-list\n");
1043 return CMD_WARNING_CONFIG_FAILED
;
1047 XFREE(MTYPE_TMP
, plist
->desc
);
1051 if (plist
->head
== NULL
&& plist
->tail
== NULL
&& plist
->desc
== NULL
)
1052 prefix_list_delete(plist
);
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
)
1071 struct prefix_list_entry
*pentry
;
1073 /* Print the name of the protocol */
1074 vty_out(vty
, "%s: ", frr_protoname
);
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
);
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
);
1086 vty_out(vty
, " Description: %s\n", plist
->desc
);
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);
1095 if (dtype
!= summary_display
) {
1096 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1097 if (dtype
== sequential_display
1098 && pentry
->seq
!= seqnum
)
1104 vty_out(vty
, "seq %u ", pentry
->seq
);
1106 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1109 vty_out(vty
, "any");
1111 struct prefix
*p
= &pentry
->prefix
;
1114 vty_out(vty
, "%s/%d",
1115 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1120 vty_out(vty
, " ge %d", pentry
->ge
);
1122 vty_out(vty
, " le %d", pentry
->le
);
1125 if (dtype
== detail_display
1126 || dtype
== sequential_display
)
1127 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1128 pentry
->hitcnt
, pentry
->refcnt
);
1135 static int vty_show_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1136 const char *seq
, enum display_type dtype
)
1138 struct prefix_list
*plist
;
1139 struct prefix_master
*master
;
1142 master
= prefix_master_get(afi
, 0);
1150 plist
= prefix_list_lookup(afi
, name
);
1152 vty_out(vty
, "%% Can't find specified prefix-list\n");
1155 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
, seqnum
);
1157 if (dtype
== detail_display
|| dtype
== summary_display
) {
1160 "Prefix-list with the last deletion/insertion: %s\n",
1161 master
->recent
->name
);
1164 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
1165 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
1168 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1169 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
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
)
1180 struct prefix_list
*plist
;
1181 struct prefix_list_entry
*pentry
;
1186 plist
= prefix_list_lookup(afi
, name
);
1188 vty_out(vty
, "%% Can't find specified prefix-list\n");
1192 ret
= str2prefix(prefix
, &p
);
1194 vty_out(vty
, "%% prefix is malformed\n");
1198 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1201 if (type
== normal_display
|| type
== first_match_display
)
1202 if (prefix_same(&p
, &pentry
->prefix
))
1205 if (type
== longer_display
)
1206 if (prefix_match(&p
, &pentry
->prefix
))
1210 vty_out(vty
, " seq %u %s ", pentry
->seq
,
1211 prefix_list_type_str(pentry
));
1214 vty_out(vty
, "any");
1216 struct prefix
*p
= &pentry
->prefix
;
1219 vty_out(vty
, "%s/%d",
1220 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1225 vty_out(vty
, " ge %d", pentry
->ge
);
1227 vty_out(vty
, " le %d", pentry
->le
);
1230 if (type
== normal_display
1231 || type
== first_match_display
)
1232 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1233 pentry
->hitcnt
, pentry
->refcnt
);
1237 if (type
== first_match_display
)
1244 static int vty_clear_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1247 struct prefix_master
*master
;
1248 struct prefix_list
*plist
;
1249 struct prefix_list_entry
*pentry
;
1253 master
= prefix_master_get(afi
, 0);
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
)
1263 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1264 for (pentry
= plist
->head
; pentry
;
1265 pentry
= pentry
->next
)
1268 plist
= prefix_list_lookup(afi
, name
);
1270 vty_out(vty
, "%% Can't find specified prefix-list\n");
1275 ret
= str2prefix(prefix
, &p
);
1277 vty_out(vty
, "%% prefix is malformed\n");
1282 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1284 if (prefix_match(&pentry
->prefix
, &p
))
1293 #ifndef VTYSH_EXTRACT_PL
1294 #include "plist_clippy.c"
1297 DEFPY (ip_prefix_list
,
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)}]>",
1302 "Name of a prefix list\n"
1303 "sequence number of an entry\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")
1314 return vty_prefix_list_install(vty
, AFI_IP
, prefix_list
, seq_str
,
1315 action
, dest
, ge_str
, le_str
);
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)}]>",
1324 "Name of a prefix list\n"
1325 "sequence number of an entry\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")
1336 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, seq_str
,
1337 action
, dest
, ge_str
, le_str
);
1340 DEFPY (no_ip_prefix_list_all
,
1341 no_ip_prefix_list_all_cmd
,
1342 "no ip prefix-list WORD",
1346 "Name of a prefix list\n")
1348 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, NULL
, NULL
,
1352 DEFPY (ip_prefix_list_sequence_number
,
1353 ip_prefix_list_sequence_number_cmd
,
1354 "[no] ip prefix-list sequence-number",
1358 "Include/exclude sequence numbers in NVGEN\n")
1360 prefix_master_ipv4
.seqnum
= no
? 0 : 1;
1364 DEFUN (ip_prefix_list_description
,
1365 ip_prefix_list_description_cmd
,
1366 "ip prefix-list WORD description LINE...",
1369 "Name of a prefix list\n"
1370 "Prefix-list specific description\n"
1371 "Up to 80 characters describing this prefix-list\n")
1375 struct prefix_list
*plist
;
1377 plist
= prefix_list_get(AFI_IP
, 0, argv
[idx_word
]->arg
);
1380 XFREE(MTYPE_TMP
, plist
->desc
);
1383 plist
->desc
= argv_concat(argv
, argc
, idx_line
);
1388 DEFUN (no_ip_prefix_list_description
,
1389 no_ip_prefix_list_description_cmd
,
1390 "no ip prefix-list WORD description",
1394 "Name of a prefix list\n"
1395 "Prefix-list specific description\n")
1398 return vty_prefix_list_desc_unset(vty
, AFI_IP
, argv
[idx_word
]->arg
);
1402 DEFUN (no_ip_prefix_list_description_comment
,
1403 no_ip_prefix_list_description_comment_cmd
,
1404 "no ip prefix-list WORD description LINE...",
1408 "Name of a prefix list\n"
1409 "Prefix-list specific description\n"
1410 "Up to 80 characters describing this prefix-list\n")
1412 return no_ip_prefix_list_description(self
, vty
, argc
, argv
);
1415 DEFPY (show_ip_prefix_list
,
1416 show_ip_prefix_list_cmd
,
1417 "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1421 "Name of a prefix list\n"
1422 "sequence number of an entry\n"
1423 "Sequence number\n")
1425 enum display_type dtype
= normal_display
;
1427 dtype
= sequential_display
;
1429 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, arg_str
, dtype
);
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]",
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")
1443 enum display_type dtype
= normal_display
;
1445 dtype
= longer_display
;
1447 dtype
= first_match_display
;
1449 return vty_show_prefix_list_prefix(vty
, AFI_IP
, prefix_list
, prefix_str
,
1453 DEFPY (show_ip_prefix_list_summary
,
1454 show_ip_prefix_list_summary_cmd
,
1455 "show ip prefix-list summary [WORD$prefix_list]",
1459 "Summary of prefix lists\n"
1460 "Name of a prefix list\n")
1462 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1466 DEFPY (show_ip_prefix_list_detail
,
1467 show_ip_prefix_list_detail_cmd
,
1468 "show ip prefix-list detail [WORD$prefix_list]",
1472 "Detail of prefix lists\n"
1473 "Name of a prefix list\n")
1475 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1479 DEFPY (clear_ip_prefix_list
,
1480 clear_ip_prefix_list_cmd
,
1481 "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
1485 "Name of a prefix list\n"
1486 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1488 return vty_clear_prefix_list(vty
, AFI_IP
, prefix_list
, prefix_str
);
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)}]>",
1496 "Name of a prefix list\n"
1497 "sequence number of an entry\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")
1508 return vty_prefix_list_install(vty
, AFI_IP6
, prefix_list
, seq_str
,
1509 action
, dest
, ge_str
, le_str
);
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)}]>",
1518 "Name of a prefix list\n"
1519 "sequence number of an entry\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")
1530 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, seq_str
,
1531 action
, dest
, ge_str
, le_str
);
1534 DEFPY (no_ipv6_prefix_list_all
,
1535 no_ipv6_prefix_list_all_cmd
,
1536 "no ipv6 prefix-list WORD",
1540 "Name of a prefix list\n")
1542 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, NULL
, NULL
,
1546 DEFPY (ipv6_prefix_list_sequence_number
,
1547 ipv6_prefix_list_sequence_number_cmd
,
1548 "[no] ipv6 prefix-list sequence-number",
1552 "Include/exclude sequence numbers in NVGEN\n")
1554 prefix_master_ipv6
.seqnum
= no
? 0 : 1;
1558 DEFUN (ipv6_prefix_list_description
,
1559 ipv6_prefix_list_description_cmd
,
1560 "ipv6 prefix-list WORD description LINE...",
1563 "Name of a prefix list\n"
1564 "Prefix-list specific description\n"
1565 "Up to 80 characters describing this prefix-list\n")
1569 struct prefix_list
*plist
;
1571 plist
= prefix_list_get(AFI_IP6
, 0, argv
[idx_word
]->arg
);
1574 XFREE(MTYPE_TMP
, plist
->desc
);
1577 plist
->desc
= argv_concat(argv
, argc
, iddx_line
);
1582 DEFUN (no_ipv6_prefix_list_description
,
1583 no_ipv6_prefix_list_description_cmd
,
1584 "no ipv6 prefix-list WORD description",
1588 "Name of a prefix list\n"
1589 "Prefix-list specific description\n")
1592 return vty_prefix_list_desc_unset(vty
, AFI_IP6
, argv
[idx_word
]->arg
);
1596 DEFUN (no_ipv6_prefix_list_description_comment
,
1597 no_ipv6_prefix_list_description_comment_cmd
,
1598 "no ipv6 prefix-list WORD description LINE...",
1602 "Name of a prefix list\n"
1603 "Prefix-list specific description\n"
1604 "Up to 80 characters describing this prefix-list\n")
1606 return no_ipv6_prefix_list_description(self
, vty
, argc
, argv
);
1610 DEFPY (show_ipv6_prefix_list
,
1611 show_ipv6_prefix_list_cmd
,
1612 "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1616 "Name of a prefix list\n"
1617 "sequence number of an entry\n"
1618 "Sequence number\n")
1620 enum display_type dtype
= normal_display
;
1622 dtype
= sequential_display
;
1624 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, arg_str
, dtype
);
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]",
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")
1638 enum display_type dtype
= normal_display
;
1640 dtype
= longer_display
;
1642 dtype
= first_match_display
;
1644 return vty_show_prefix_list_prefix(vty
, AFI_IP6
, prefix_list
,
1648 DEFPY (show_ipv6_prefix_list_summary
,
1649 show_ipv6_prefix_list_summary_cmd
,
1650 "show ipv6 prefix-list summary [WORD$prefix-list]",
1654 "Summary of prefix lists\n"
1655 "Name of a prefix list\n")
1657 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1661 DEFPY (show_ipv6_prefix_list_detail
,
1662 show_ipv6_prefix_list_detail_cmd
,
1663 "show ipv6 prefix-list detail [WORD$prefix-list]",
1667 "Detail of prefix lists\n"
1668 "Name of a prefix list\n")
1670 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1674 DEFPY (clear_ipv6_prefix_list
,
1675 clear_ipv6_prefix_list_cmd
,
1676 "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
1680 "Name of a prefix list\n"
1681 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
1683 return vty_clear_prefix_list(vty
, AFI_IP6
, prefix_list
, prefix_str
);
1686 /* Configuration write function. */
1687 static int config_write_prefix_afi(afi_t afi
, struct vty
*vty
)
1689 struct prefix_list
*plist
;
1690 struct prefix_list_entry
*pentry
;
1691 struct prefix_master
*master
;
1694 master
= prefix_master_get(afi
, 0);
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");
1704 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
) {
1706 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1707 afi
== AFI_IP
? "" : "v6", plist
->name
,
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
);
1717 vty_out(vty
, "seq %u ", pentry
->seq
);
1719 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1722 vty_out(vty
, "any");
1724 struct prefix
*p
= &pentry
->prefix
;
1727 vty_out(vty
, "%s/%d",
1728 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1733 vty_out(vty
, " ge %d", pentry
->ge
);
1735 vty_out(vty
, " le %d", pentry
->le
);
1740 /* vty_out (vty, "!\n"); */
1743 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
) {
1745 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1746 afi
== AFI_IP
? "" : "v6", plist
->name
,
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
);
1756 vty_out(vty
, "seq %u ", pentry
->seq
);
1758 vty_out(vty
, "%s", prefix_list_type_str(pentry
));
1761 vty_out(vty
, " any");
1763 struct prefix
*p
= &pentry
->prefix
;
1766 vty_out(vty
, " %s/%d",
1767 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1772 vty_out(vty
, " ge %d", pentry
->ge
);
1774 vty_out(vty
, " le %d", pentry
->le
);
1784 struct stream
*prefix_bgp_orf_entry(struct stream
*s
, struct prefix_list
*plist
,
1785 u_char init_flag
, u_char permit_flag
,
1788 struct prefix_list_entry
*pentry
;
1793 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1794 u_char flag
= init_flag
;
1795 struct prefix
*p
= &pentry
->prefix
;
1797 flag
|= (pentry
->type
== PREFIX_PERMIT
? permit_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
);
1809 int prefix_bgp_orf_set(char *name
, afi_t afi
, struct orf_prefix
*orfp
,
1810 int permit
, int set
)
1812 struct prefix_list
*plist
;
1813 struct prefix_list_entry
*pentry
;
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
;
1823 if (orfp
->ge
&& orfp
->le
== (afi
== AFI_IP
? 32 : 128))
1826 plist
= prefix_list_get(afi
, 1, name
);
1828 return CMD_WARNING_CONFIG_FAILED
;
1831 pentry
= prefix_list_entry_make(
1832 &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1833 orfp
->seq
, orfp
->le
, orfp
->ge
, 0);
1835 if (prefix_entry_dup_check(plist
, pentry
)) {
1836 prefix_list_entry_free(pentry
);
1837 return CMD_WARNING_CONFIG_FAILED
;
1840 prefix_list_entry_add(plist
, pentry
);
1842 pentry
= prefix_list_entry_lookup(
1843 plist
, &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1844 orfp
->seq
, orfp
->le
, orfp
->ge
);
1847 return CMD_WARNING_CONFIG_FAILED
;
1849 prefix_list_entry_delete(plist
, pentry
, 1);
1855 void prefix_bgp_orf_remove_all(afi_t afi
, char *name
)
1857 struct prefix_list
*plist
;
1859 plist
= prefix_bgp_orf_lookup(afi
, name
);
1861 prefix_list_delete(plist
);
1864 /* return prefix count */
1865 int prefix_bgp_show_prefix_list(struct vty
*vty
, afi_t afi
, char *name
,
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
;
1874 plist
= prefix_bgp_orf_lookup(afi
, name
);
1879 return plist
->count
;
1882 json
= json_object_new_object();
1883 json_prefix
= json_object_new_object();
1884 json_list
= json_object_new_object();
1886 json_object_int_add(json_prefix
, "prefixListCounter",
1888 json_object_string_add(json_prefix
, "prefixListName",
1891 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1892 struct prefix
*p
= &pentry
->prefix
;
1896 sprintf(buf_a
, "%s/%d",
1897 inet_ntop(p
->family
, &p
->u
.prefix
, buf_b
,
1901 json_object_int_add(json_list
, "seq", pentry
->seq
);
1902 json_object_string_add(json_list
, "seqPrefixListType",
1903 prefix_list_type_str(pentry
));
1906 json_object_int_add(json_list
, "ge",
1909 json_object_int_add(json_list
, "le",
1912 json_object_object_add(json_prefix
, buf_a
, json_list
);
1915 json_object_object_add(json
, "ipPrefixList",
1918 json_object_object_add(json
, "ipv6PrefixList",
1921 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1922 json
, JSON_C_TO_STRING_PRETTY
));
1923 json_object_free(json
);
1925 vty_out(vty
, "ip%s prefix-list %s: %d entries\n",
1926 afi
== AFI_IP
? "" : "v6", plist
->name
, plist
->count
);
1928 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1929 struct prefix
*p
= &pentry
->prefix
;
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
),
1938 vty_out(vty
, " ge %d", pentry
->ge
);
1940 vty_out(vty
, " le %d", pentry
->le
);
1945 return plist
->count
;
1948 static void prefix_list_reset_afi(afi_t afi
, int orf
)
1950 struct prefix_list
*plist
;
1951 struct prefix_list
*next
;
1952 struct prefix_master
*master
;
1954 master
= prefix_master_get(afi
, orf
);
1958 for (plist
= master
->num
.head
; plist
; plist
= next
) {
1960 prefix_list_delete(plist
);
1962 for (plist
= master
->str
.head
; plist
; plist
= next
) {
1964 prefix_list_delete(plist
);
1967 assert(master
->num
.head
== NULL
);
1968 assert(master
->num
.tail
== NULL
);
1970 assert(master
->str
.head
== NULL
);
1971 assert(master
->str
.tail
== NULL
);
1974 master
->recent
= NULL
;
1978 /* Prefix-list node. */
1979 static struct cmd_node prefix_node
= {PREFIX_NODE
,
1980 "", /* Prefix list has no interface. */
1983 static int config_write_prefix_ipv4(struct vty
*vty
)
1985 return config_write_prefix_afi(AFI_IP
, vty
);
1988 static void plist_autocomplete_afi(afi_t afi
, vector comps
,
1989 struct cmd_token
*token
)
1991 struct prefix_list
*plist
;
1992 struct prefix_master
*master
;
1994 master
= prefix_master_get(afi
, 0);
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
));
2004 static void plist_autocomplete(vector comps
, struct cmd_token
*token
)
2006 plist_autocomplete_afi(AFI_IP
, comps
, token
);
2007 plist_autocomplete_afi(AFI_IP6
, comps
, token
);
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
}};
2017 static void prefix_list_init_ipv4(void)
2019 install_node(&prefix_node
, config_write_prefix_ipv4
);
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
);
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
);
2030 install_element(CONFIG_NODE
, &ip_prefix_list_sequence_number_cmd
);
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
);
2037 install_element(ENABLE_NODE
, &clear_ip_prefix_list_cmd
);
2040 /* Prefix-list node. */
2041 static struct cmd_node prefix_ipv6_node
= {
2042 PREFIX_IPV6_NODE
, "", /* Prefix list has no interface. */
2045 static int config_write_prefix_ipv6(struct vty
*vty
)
2047 return config_write_prefix_afi(AFI_IP6
, vty
);
2050 static void prefix_list_init_ipv6(void)
2052 install_node(&prefix_ipv6_node
, config_write_prefix_ipv6
);
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
);
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
);
2063 install_element(CONFIG_NODE
, &ipv6_prefix_list_sequence_number_cmd
);
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
);
2070 install_element(ENABLE_NODE
, &clear_ipv6_prefix_list_cmd
);
2073 void prefix_list_init()
2075 cmd_variable_handler_register(plist_var_handlers
);
2077 prefix_list_init_ipv4();
2078 prefix_list_init_ipv6();
2081 void prefix_list_reset()
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);