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 afi_t
prefix_list_afi(struct prefix_list
*plist
)
127 if (plist
->master
== &prefix_master_ipv4
128 || plist
->master
== &prefix_master_orf_v4
)
133 /* Lookup prefix_list from list of prefix_list by name. */
134 static struct prefix_list
*prefix_list_lookup_do(afi_t afi
, int orf
,
137 struct prefix_list
*plist
;
138 struct prefix_master
*master
;
143 master
= prefix_master_get(afi
, orf
);
147 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
148 if (strcmp(plist
->name
, name
) == 0)
151 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
152 if (strcmp(plist
->name
, name
) == 0)
158 struct prefix_list
*prefix_list_lookup(afi_t afi
, const char *name
)
160 return prefix_list_lookup_do(afi
, 0, name
);
163 struct prefix_list
*prefix_bgp_orf_lookup(afi_t afi
, const char *name
)
165 return prefix_list_lookup_do(afi
, 1, name
);
168 static struct prefix_list
*prefix_list_new(void)
170 struct prefix_list
*new;
172 new = XCALLOC(MTYPE_PREFIX_LIST
, sizeof(struct prefix_list
));
176 static void prefix_list_free(struct prefix_list
*plist
)
178 XFREE(MTYPE_PREFIX_LIST
, plist
);
181 static struct prefix_list_entry
*prefix_list_entry_new(void)
183 struct prefix_list_entry
*new;
185 new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY
,
186 sizeof(struct prefix_list_entry
));
190 static void prefix_list_entry_free(struct prefix_list_entry
*pentry
)
192 XFREE(MTYPE_PREFIX_LIST_ENTRY
, pentry
);
195 /* Insert new prefix list to list of prefix_list. Each prefix_list
196 is sorted by the name. */
197 static struct prefix_list
*prefix_list_insert(afi_t afi
, int orf
,
202 struct prefix_list
*plist
;
203 struct prefix_list
*point
;
204 struct prefix_list_list
*list
;
205 struct prefix_master
*master
;
207 master
= prefix_master_get(afi
, orf
);
211 /* Allocate new prefix_list and copy given name. */
212 plist
= prefix_list_new();
213 plist
->name
= XSTRDUP(MTYPE_MPREFIX_LIST_STR
, name
);
214 plist
->master
= master
;
216 XCALLOC(MTYPE_PREFIX_LIST_TRIE
, sizeof(struct pltrie_table
));
218 /* If name is made by all digit character. We treat it as
220 for (number
= 0, i
= 0; i
< strlen(name
); i
++) {
221 if (isdigit((unsigned char)name
[i
]))
222 number
= (number
* 10) + (name
[i
] - '0');
227 /* In case of name is all digit character */
228 if (i
== strlen(name
)) {
229 plist
->type
= PREFIX_TYPE_NUMBER
;
231 /* Set prefix_list to number list. */
234 for (point
= list
->head
; point
; point
= point
->next
)
235 if (atol(point
->name
) >= number
)
238 plist
->type
= PREFIX_TYPE_STRING
;
240 /* Set prefix_list to string list. */
243 /* Set point to insertion point. */
244 for (point
= list
->head
; point
; point
= point
->next
)
245 if (strcmp(point
->name
, name
) >= 0)
249 /* In case of this is the first element of master. */
250 if (list
->head
== NULL
) {
251 list
->head
= list
->tail
= plist
;
255 /* In case of insertion is made at the tail of access_list. */
257 plist
->prev
= list
->tail
;
258 list
->tail
->next
= plist
;
263 /* In case of insertion is made at the head of access_list. */
264 if (point
== list
->head
) {
265 plist
->next
= list
->head
;
266 list
->head
->prev
= plist
;
271 /* Insertion is made at middle of the access_list. */
273 plist
->prev
= point
->prev
;
276 point
->prev
->next
= plist
;
282 static struct prefix_list
*prefix_list_get(afi_t afi
, int orf
, const char *name
)
284 struct prefix_list
*plist
;
286 plist
= prefix_list_lookup_do(afi
, orf
, name
);
289 plist
= prefix_list_insert(afi
, orf
, name
);
293 static void prefix_list_trie_del(struct prefix_list
*plist
,
294 struct prefix_list_entry
*pentry
);
296 /* Delete prefix-list from prefix_list_master and free it. */
297 static void prefix_list_delete(struct prefix_list
*plist
)
299 struct prefix_list_list
*list
;
300 struct prefix_master
*master
;
301 struct prefix_list_entry
*pentry
;
302 struct prefix_list_entry
*next
;
304 /* If prefix-list contain prefix_list_entry free all of it. */
305 for (pentry
= plist
->head
; pentry
; pentry
= next
) {
307 prefix_list_trie_del(plist
, pentry
);
308 prefix_list_entry_free(pentry
);
312 master
= plist
->master
;
314 if (plist
->type
== PREFIX_TYPE_NUMBER
)
320 plist
->next
->prev
= plist
->prev
;
322 list
->tail
= plist
->prev
;
325 plist
->prev
->next
= plist
->next
;
327 list
->head
= plist
->next
;
329 XFREE(MTYPE_TMP
, plist
->desc
);
331 /* Make sure master's recent changed prefix-list information is
333 master
->recent
= NULL
;
335 route_map_notify_dependencies(plist
->name
, RMAP_EVENT_PLIST_DELETED
);
337 if (master
->delete_hook
)
338 (*master
->delete_hook
)(plist
);
340 XFREE(MTYPE_MPREFIX_LIST_STR
, plist
->name
);
342 XFREE(MTYPE_PREFIX_LIST_TRIE
, plist
->trie
);
344 prefix_list_free(plist
);
347 static struct prefix_list_entry
*
348 prefix_list_entry_make(struct prefix
*prefix
, enum prefix_list_type type
,
349 int64_t seq
, int le
, int ge
, int any
)
351 struct prefix_list_entry
*pentry
;
353 pentry
= prefix_list_entry_new();
358 prefix_copy(&pentry
->prefix
, prefix
);
367 /* Add hook function. */
368 void prefix_list_add_hook(void (*func
)(struct prefix_list
*plist
))
370 prefix_master_ipv4
.add_hook
= func
;
371 prefix_master_ipv6
.add_hook
= func
;
374 /* Delete hook function. */
375 void prefix_list_delete_hook(void (*func
)(struct prefix_list
*plist
))
377 prefix_master_ipv4
.delete_hook
= func
;
378 prefix_master_ipv6
.delete_hook
= func
;
381 /* Calculate new sequential number. */
382 static int64_t prefix_new_seq_get(struct prefix_list
*plist
)
386 struct prefix_list_entry
*pentry
;
390 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
391 if (maxseq
< pentry
->seq
)
392 maxseq
= pentry
->seq
;
395 newseq
= ((maxseq
/ 5) * 5) + 5;
397 return (newseq
> UINT_MAX
) ? UINT_MAX
: newseq
;
400 /* Return prefix list entry which has same seq number. */
401 static struct prefix_list_entry
*prefix_seq_check(struct prefix_list
*plist
,
404 struct prefix_list_entry
*pentry
;
406 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
)
407 if (pentry
->seq
== seq
)
412 static struct prefix_list_entry
*
413 prefix_list_entry_lookup(struct prefix_list
*plist
, struct prefix
*prefix
,
414 enum prefix_list_type type
, int64_t seq
,
417 struct prefix_list_entry
*pentry
;
419 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
)
420 if (prefix_same(&pentry
->prefix
, prefix
)
421 && pentry
->type
== type
) {
422 if (seq
>= 0 && pentry
->seq
!= seq
)
425 if (pentry
->le
!= le
)
427 if (pentry
->ge
!= ge
)
436 static void trie_walk_affected(size_t validbits
, struct pltrie_table
*table
,
437 uint8_t byte
, struct prefix_list_entry
*object
,
438 void (*fn
)(struct prefix_list_entry
*object
,
439 struct prefix_list_entry
**updptr
))
444 if (validbits
> PLC_BITS
) {
445 fn(object
, &table
->entries
[byte
].final_chain
);
449 mask
= (1 << (8 - validbits
)) - 1;
450 for (bwalk
= byte
& ~mask
; bwalk
<= byte
+ mask
; bwalk
++) {
451 fn(object
, &table
->entries
[bwalk
].up_chain
);
455 static void trie_uninstall_fn(struct prefix_list_entry
*object
,
456 struct prefix_list_entry
**updptr
)
458 for (; *updptr
; updptr
= &(*updptr
)->next_best
)
459 if (*updptr
== object
) {
460 *updptr
= object
->next_best
;
465 static int trie_table_empty(struct pltrie_table
*table
)
468 for (i
= 0; i
< PLC_LEN
; i
++)
469 if (table
->entries
[i
].next_table
|| table
->entries
[i
].up_chain
)
474 static void prefix_list_trie_del(struct prefix_list
*plist
,
475 struct prefix_list_entry
*pentry
)
477 size_t depth
, maxdepth
= plist
->master
->trie_depth
;
478 uint8_t *bytes
= pentry
->prefix
.u
.val
;
479 size_t validbits
= pentry
->prefix
.prefixlen
;
480 struct pltrie_table
*table
, **tables
[PLC_MAXLEVEL
];
483 for (depth
= 0; validbits
> PLC_BITS
&& depth
< maxdepth
- 1; depth
++) {
484 uint8_t byte
= bytes
[depth
];
485 assert(table
->entries
[byte
].next_table
);
487 tables
[depth
+ 1] = &table
->entries
[byte
].next_table
;
488 table
= table
->entries
[byte
].next_table
;
490 validbits
-= PLC_BITS
;
493 trie_walk_affected(validbits
, table
, bytes
[depth
], pentry
,
496 for (; depth
> 0; depth
--)
497 if (trie_table_empty(*tables
[depth
])) {
498 XFREE(MTYPE_PREFIX_LIST_TRIE
, *tables
[depth
]);
503 static void prefix_list_entry_delete(struct prefix_list
*plist
,
504 struct prefix_list_entry
*pentry
,
507 if (plist
== NULL
|| pentry
== NULL
)
510 prefix_list_trie_del(plist
, pentry
);
513 pentry
->prev
->next
= pentry
->next
;
515 plist
->head
= pentry
->next
;
517 pentry
->next
->prev
= pentry
->prev
;
519 plist
->tail
= pentry
->prev
;
521 prefix_list_entry_free(pentry
);
526 route_map_notify_dependencies(plist
->name
,
527 RMAP_EVENT_PLIST_DELETED
);
528 if (plist
->master
->delete_hook
)
529 (*plist
->master
->delete_hook
)(plist
);
531 if (plist
->head
== NULL
&& plist
->tail
== NULL
532 && plist
->desc
== NULL
)
533 prefix_list_delete(plist
);
535 plist
->master
->recent
= plist
;
539 static void trie_install_fn(struct prefix_list_entry
*object
,
540 struct prefix_list_entry
**updptr
)
543 if (*updptr
== object
)
545 if ((*updptr
)->prefix
.prefixlen
< object
->prefix
.prefixlen
)
547 if ((*updptr
)->prefix
.prefixlen
== object
->prefix
.prefixlen
548 && (*updptr
)->seq
> object
->seq
)
550 updptr
= &(*updptr
)->next_best
;
553 if (!object
->next_best
)
554 object
->next_best
= *updptr
;
556 assert(object
->next_best
== *updptr
|| !*updptr
);
561 static void prefix_list_trie_add(struct prefix_list
*plist
,
562 struct prefix_list_entry
*pentry
)
564 size_t depth
= plist
->master
->trie_depth
;
565 uint8_t *bytes
= pentry
->prefix
.u
.val
;
566 size_t validbits
= pentry
->prefix
.prefixlen
;
567 struct pltrie_table
*table
;
570 while (validbits
> PLC_BITS
&& depth
> 1) {
571 if (!table
->entries
[*bytes
].next_table
)
572 table
->entries
[*bytes
].next_table
=
573 XCALLOC(MTYPE_PREFIX_LIST_TRIE
,
574 sizeof(struct pltrie_table
));
575 table
= table
->entries
[*bytes
].next_table
;
578 validbits
-= PLC_BITS
;
581 trie_walk_affected(validbits
, table
, *bytes
, pentry
, trie_install_fn
);
584 static void prefix_list_entry_add(struct prefix_list
*plist
,
585 struct prefix_list_entry
*pentry
)
587 struct prefix_list_entry
*replace
;
588 struct prefix_list_entry
*point
;
590 /* Automatic asignment of seq no. */
591 if (pentry
->seq
== -1)
592 pentry
->seq
= prefix_new_seq_get(plist
);
594 if (plist
->tail
&& pentry
->seq
> plist
->tail
->seq
)
597 /* Is there any same seq prefix list entry? */
598 replace
= prefix_seq_check(plist
, pentry
->seq
);
600 prefix_list_entry_delete(plist
, replace
, 0);
602 /* Check insert point. */
603 for (point
= plist
->head
; point
; point
= point
->next
)
604 if (point
->seq
>= pentry
->seq
)
608 /* In case of this is the first element of the list. */
609 pentry
->next
= point
;
613 point
->prev
->next
= pentry
;
615 plist
->head
= pentry
;
617 pentry
->prev
= point
->prev
;
618 point
->prev
= pentry
;
621 plist
->tail
->next
= pentry
;
623 plist
->head
= pentry
;
625 pentry
->prev
= plist
->tail
;
626 plist
->tail
= pentry
;
629 prefix_list_trie_add(plist
, pentry
);
631 /* Increment count. */
634 /* Run hook function. */
635 if (plist
->master
->add_hook
)
636 (*plist
->master
->add_hook
)(plist
);
638 route_map_notify_dependencies(plist
->name
, RMAP_EVENT_PLIST_ADDED
);
639 plist
->master
->recent
= plist
;
642 /* Return string of prefix_list_type. */
643 static const char *prefix_list_type_str(struct prefix_list_entry
*pentry
)
645 switch (pentry
->type
) {
655 static int prefix_list_entry_match(struct prefix_list_entry
*pentry
,
656 const struct prefix
*p
)
660 if (pentry
->prefix
.family
!= p
->family
)
663 ret
= prefix_match(&pentry
->prefix
, p
);
667 /* In case of le nor ge is specified, exact match is performed. */
668 if (!pentry
->le
&& !pentry
->ge
) {
669 if (pentry
->prefix
.prefixlen
!= p
->prefixlen
)
673 if (p
->prefixlen
> pentry
->le
)
677 if (p
->prefixlen
< pentry
->ge
)
683 enum prefix_list_type
prefix_list_apply_which_prefix(
684 struct prefix_list
*plist
,
685 const struct prefix
**which
,
688 struct prefix_list_entry
*pentry
, *pbest
= NULL
;
690 const struct prefix
*p
= (const struct prefix
*)object
;
691 const uint8_t *byte
= p
->u
.val
;
693 size_t validbits
= p
->prefixlen
;
694 struct pltrie_table
*table
;
702 if (plist
->count
== 0) {
705 return PREFIX_PERMIT
;
708 depth
= plist
->master
->trie_depth
;
711 for (pentry
= table
->entries
[*byte
].up_chain
; pentry
;
712 pentry
= pentry
->next_best
) {
713 if (pbest
&& pbest
->seq
< pentry
->seq
)
715 if (prefix_list_entry_match(pentry
, p
))
719 if (validbits
<= PLC_BITS
)
721 validbits
-= PLC_BITS
;
724 if (!table
->entries
[*byte
].next_table
)
727 table
= table
->entries
[*byte
].next_table
;
732 for (pentry
= table
->entries
[*byte
].final_chain
; pentry
;
733 pentry
= pentry
->next_best
) {
734 if (pbest
&& pbest
->seq
< pentry
->seq
)
736 if (prefix_list_entry_match(pentry
, p
))
744 *which
= &pbest
->prefix
;
756 static void __attribute__((unused
)) prefix_list_print(struct prefix_list
*plist
)
758 struct prefix_list_entry
*pentry
;
763 printf("ip prefix-list %s: %d entries\n", plist
->name
, plist
->count
);
765 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
767 printf("any %s\n", prefix_list_type_str(pentry
));
774 printf(" seq %" PRId64
" %s %s/%d", pentry
->seq
,
775 prefix_list_type_str(pentry
),
776 inet_ntop(p
->family
, p
->u
.val
, buf
, BUFSIZ
),
779 printf(" ge %d", pentry
->ge
);
781 printf(" le %d", pentry
->le
);
787 /* Retrun 1 when plist already include pentry policy. */
788 static struct prefix_list_entry
*
789 prefix_entry_dup_check(struct prefix_list
*plist
, struct prefix_list_entry
*new)
791 size_t depth
, maxdepth
= plist
->master
->trie_depth
;
792 uint8_t byte
, *bytes
= new->prefix
.u
.val
;
793 size_t validbits
= new->prefix
.prefixlen
;
794 struct pltrie_table
*table
;
795 struct prefix_list_entry
*pentry
;
799 seq
= prefix_new_seq_get(plist
);
804 for (depth
= 0; validbits
> PLC_BITS
&& depth
< maxdepth
- 1; depth
++) {
806 if (!table
->entries
[byte
].next_table
)
809 table
= table
->entries
[byte
].next_table
;
810 validbits
-= PLC_BITS
;
814 if (validbits
> PLC_BITS
)
815 pentry
= table
->entries
[byte
].final_chain
;
817 pentry
= table
->entries
[byte
].up_chain
;
819 for (; pentry
; pentry
= pentry
->next_best
) {
820 if (prefix_same(&pentry
->prefix
, &new->prefix
)
821 && pentry
->type
== new->type
&& pentry
->le
== new->le
822 && pentry
->ge
== new->ge
&& pentry
->seq
!= seq
)
828 static int vty_invalid_prefix_range(struct vty
*vty
, const char *prefix
)
831 "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n",
833 return CMD_WARNING_CONFIG_FAILED
;
836 static int vty_prefix_list_install(struct vty
*vty
, afi_t afi
, const char *name
,
837 const char *seq
, const char *typestr
,
838 const char *prefix
, const char *ge
,
842 enum prefix_list_type type
;
843 struct prefix_list
*plist
;
844 struct prefix_list_entry
*pentry
;
845 struct prefix_list_entry
*dup
;
846 struct prefix p
, p_tmp
;
852 if (name
== NULL
|| prefix
== NULL
|| typestr
== NULL
) {
853 vty_out(vty
, "%% Missing prefix or type\n");
854 return CMD_WARNING_CONFIG_FAILED
;
857 /* Sequential number. */
859 seqnum
= (int64_t)atol(seq
);
861 /* ge and le number */
867 /* Check filter type. */
868 if (strncmp("permit", typestr
, 1) == 0)
869 type
= PREFIX_PERMIT
;
870 else if (strncmp("deny", typestr
, 1) == 0)
873 vty_out(vty
, "%% prefix type must be permit or deny\n");
874 return CMD_WARNING_CONFIG_FAILED
;
877 /* "any" is special token for matching any IPv4 addresses. */
880 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
881 ret
= str2prefix_ipv4("0.0.0.0/0",
882 (struct prefix_ipv4
*)&p
);
884 lenum
= IPV4_MAX_BITLEN
;
887 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
890 vty_out(vty
, "%% Malformed IPv4 prefix\n");
891 return CMD_WARNING_CONFIG_FAILED
;
894 /* make a copy to verify prefix matches mask length */
895 prefix_copy(&p_tmp
, &p
);
896 apply_mask_ipv4((struct prefix_ipv4
*)&p_tmp
);
900 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
901 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
903 lenum
= IPV6_MAX_BITLEN
;
906 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
909 vty_out(vty
, "%% Malformed IPv6 prefix\n");
910 return CMD_WARNING_CONFIG_FAILED
;
913 /* make a copy to verify prefix matches mask length */
914 prefix_copy(&p_tmp
, &p
);
915 apply_mask_ipv6((struct prefix_ipv6
*)&p_tmp
);
920 vty_out(vty
, "%% Unrecognized AFI (%d)\n", afi
);
921 return CMD_WARNING_CONFIG_FAILED
;
925 /* If prefix has bits not under the mask, adjust it to fit */
926 if (!prefix_same(&p_tmp
, &p
)) {
927 char buf
[PREFIX2STR_BUFFER
];
928 char buf_tmp
[PREFIX2STR_BUFFER
];
929 prefix2str(&p
, buf
, sizeof(buf
));
930 prefix2str(&p_tmp
, buf_tmp
, sizeof(buf_tmp
));
932 "%% Prefix-list %s prefix changed from %s to %s to match length\n",
935 "Prefix-list %s prefix changed from %s to %s to match length",
940 /* ge and le check. */
941 if (genum
&& (genum
<= p
.prefixlen
))
942 return vty_invalid_prefix_range(vty
, prefix
);
944 if (lenum
&& (lenum
< p
.prefixlen
))
945 return vty_invalid_prefix_range(vty
, prefix
);
947 if (lenum
&& (genum
> lenum
))
948 return vty_invalid_prefix_range(vty
, prefix
);
950 if (genum
&& (lenum
== (afi
== AFI_IP
? 32 : 128)))
953 /* Get prefix_list with name. */
954 plist
= prefix_list_get(afi
, 0, name
);
956 /* Make prefix entry. */
957 pentry
= prefix_list_entry_make(&p
, type
, seqnum
, lenum
, genum
, any
);
959 /* Check same policy. */
960 dup
= prefix_entry_dup_check(plist
, pentry
);
963 prefix_list_entry_free(pentry
);
967 /* Install new filter to the access_list. */
968 prefix_list_entry_add(plist
, pentry
);
973 static int vty_prefix_list_uninstall(struct vty
*vty
, afi_t afi
,
974 const char *name
, const char *seq
,
975 const char *typestr
, const char *prefix
,
976 const char *ge
, const char *le
)
979 enum prefix_list_type type
;
980 struct prefix_list
*plist
;
981 struct prefix_list_entry
*pentry
;
987 /* Check prefix list name. */
988 plist
= prefix_list_lookup(afi
, name
);
990 vty_out(vty
, "%% Can't find specified prefix-list\n");
991 return CMD_WARNING_CONFIG_FAILED
;
994 /* Only prefix-list name specified, delete the entire prefix-list. */
995 if (seq
== NULL
&& typestr
== NULL
&& prefix
== NULL
&& ge
== NULL
997 prefix_list_delete(plist
);
1001 /* Check sequence number. */
1003 seqnum
= (int64_t)atol(seq
);
1005 /* Sequence number specified, but nothing else. */
1006 if (seq
&& typestr
== NULL
&& prefix
== NULL
&& ge
== NULL
1008 pentry
= prefix_seq_check(plist
, seqnum
);
1010 if (pentry
== NULL
) {
1012 "%% Can't find prefix-list %s with sequence number %" PRIu64
"\n",
1014 return CMD_WARNING_CONFIG_FAILED
;
1017 prefix_list_entry_delete(plist
, pentry
, 1);
1021 /* ge and le number */
1027 /* We must have, at a minimum, both the type and prefix here */
1028 if ((typestr
== NULL
) || (prefix
== NULL
))
1029 return CMD_WARNING_CONFIG_FAILED
;
1031 /* Check of filter type. */
1032 if (strncmp("permit", typestr
, 1) == 0)
1033 type
= PREFIX_PERMIT
;
1034 else if (strncmp("deny", typestr
, 1) == 0)
1037 vty_out(vty
, "%% prefix type must be permit or deny\n");
1038 return CMD_WARNING_CONFIG_FAILED
;
1041 /* "any" is special token for matching any IPv4 addresses. */
1042 if (afi
== AFI_IP
) {
1043 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
1044 ret
= str2prefix_ipv4("0.0.0.0/0",
1045 (struct prefix_ipv4
*)&p
);
1047 lenum
= IPV4_MAX_BITLEN
;
1049 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
1052 vty_out(vty
, "%% Malformed IPv4 prefix\n");
1053 return CMD_WARNING_CONFIG_FAILED
;
1055 } else if (afi
== AFI_IP6
) {
1056 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
1057 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
1059 lenum
= IPV6_MAX_BITLEN
;
1061 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
1064 vty_out(vty
, "%% Malformed IPv6 prefix\n");
1065 return CMD_WARNING_CONFIG_FAILED
;
1069 /* Lookup prefix entry. */
1071 prefix_list_entry_lookup(plist
, &p
, type
, seqnum
, lenum
, genum
);
1073 if (pentry
== NULL
) {
1074 vty_out(vty
, "%% Can't find specified prefix-list\n");
1075 return CMD_WARNING_CONFIG_FAILED
;
1078 /* Install new filter to the access_list. */
1079 prefix_list_entry_delete(plist
, pentry
, 1);
1084 static int vty_prefix_list_desc_unset(struct vty
*vty
, afi_t afi
,
1087 struct prefix_list
*plist
;
1089 plist
= prefix_list_lookup(afi
, name
);
1091 vty_out(vty
, "%% Can't find specified prefix-list\n");
1092 return CMD_WARNING_CONFIG_FAILED
;
1095 XFREE(MTYPE_TMP
, plist
->desc
);
1097 if (plist
->head
== NULL
&& plist
->tail
== NULL
&& plist
->desc
== NULL
)
1098 prefix_list_delete(plist
);
1112 static void vty_show_prefix_entry(struct vty
*vty
, afi_t afi
,
1113 struct prefix_list
*plist
,
1114 struct prefix_master
*master
,
1115 enum display_type dtype
, int seqnum
)
1117 struct prefix_list_entry
*pentry
;
1119 /* Print the name of the protocol */
1120 vty_out(vty
, "%s: ", frr_protoname
);
1122 if (dtype
== normal_display
) {
1123 vty_out(vty
, "ip%s prefix-list %s: %d entries\n",
1124 afi
== AFI_IP
? "" : "v6", plist
->name
, plist
->count
);
1126 vty_out(vty
, " Description: %s\n", plist
->desc
);
1127 } else if (dtype
== summary_display
|| dtype
== detail_display
) {
1128 vty_out(vty
, "ip%s prefix-list %s:\n",
1129 afi
== AFI_IP
? "" : "v6", plist
->name
);
1132 vty_out(vty
, " Description: %s\n", plist
->desc
);
1135 " count: %d, range entries: %d, sequences: %" PRId64
" - %" PRId64
"\n",
1136 plist
->count
, plist
->rangecount
,
1137 plist
->head
? plist
->head
->seq
: 0,
1138 plist
->tail
? plist
->tail
->seq
: 0);
1141 if (dtype
!= summary_display
) {
1142 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1143 if (dtype
== sequential_display
1144 && pentry
->seq
!= seqnum
)
1150 vty_out(vty
, "seq %" PRId64
" ", pentry
->seq
);
1152 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1155 vty_out(vty
, "any");
1157 struct prefix
*p
= &pentry
->prefix
;
1160 vty_out(vty
, "%s/%d",
1161 inet_ntop(p
->family
, p
->u
.val
, buf
,
1166 vty_out(vty
, " ge %d", pentry
->ge
);
1168 vty_out(vty
, " le %d", pentry
->le
);
1171 if (dtype
== detail_display
1172 || dtype
== sequential_display
)
1173 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1174 pentry
->hitcnt
, pentry
->refcnt
);
1181 static int vty_show_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1182 const char *seq
, enum display_type dtype
)
1184 struct prefix_list
*plist
;
1185 struct prefix_master
*master
;
1188 master
= prefix_master_get(afi
, 0);
1193 seqnum
= (int64_t)atol(seq
);
1196 plist
= prefix_list_lookup(afi
, name
);
1198 vty_out(vty
, "%% Can't find specified prefix-list\n");
1201 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
, seqnum
);
1203 if (dtype
== detail_display
|| dtype
== summary_display
) {
1206 "Prefix-list with the last deletion/insertion: %s\n",
1207 master
->recent
->name
);
1210 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
1211 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
1214 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1215 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
1222 static int vty_show_prefix_list_prefix(struct vty
*vty
, afi_t afi
,
1223 const char *name
, const char *prefix
,
1224 enum display_type type
)
1226 struct prefix_list
*plist
;
1227 struct prefix_list_entry
*pentry
;
1232 plist
= prefix_list_lookup(afi
, name
);
1234 vty_out(vty
, "%% Can't find specified prefix-list\n");
1238 ret
= str2prefix(prefix
, &p
);
1240 vty_out(vty
, "%% prefix is malformed\n");
1244 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1247 if (type
== normal_display
|| type
== first_match_display
)
1248 if (prefix_same(&p
, &pentry
->prefix
))
1251 if (type
== longer_display
) {
1252 if ((p
.family
== pentry
->prefix
.family
)
1253 && (prefix_match(&p
, &pentry
->prefix
)))
1258 vty_out(vty
, " seq %" PRId64
" %s ", pentry
->seq
,
1259 prefix_list_type_str(pentry
));
1262 vty_out(vty
, "any");
1264 struct prefix
*pf
= &pentry
->prefix
;
1267 vty_out(vty
, "%s/%d",
1268 inet_ntop(pf
->family
, pf
->u
.val
, buf
,
1273 vty_out(vty
, " ge %d", pentry
->ge
);
1275 vty_out(vty
, " le %d", pentry
->le
);
1278 if (type
== normal_display
1279 || type
== first_match_display
)
1280 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1281 pentry
->hitcnt
, pentry
->refcnt
);
1285 if (type
== first_match_display
)
1292 static int vty_clear_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1295 struct prefix_master
*master
;
1296 struct prefix_list
*plist
;
1297 struct prefix_list_entry
*pentry
;
1301 master
= prefix_master_get(afi
, 0);
1305 if (name
== NULL
&& prefix
== NULL
) {
1306 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
1307 for (pentry
= plist
->head
; pentry
;
1308 pentry
= pentry
->next
)
1311 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1312 for (pentry
= plist
->head
; pentry
;
1313 pentry
= pentry
->next
)
1316 plist
= prefix_list_lookup(afi
, name
);
1318 vty_out(vty
, "%% Can't find specified prefix-list\n");
1323 ret
= str2prefix(prefix
, &p
);
1325 vty_out(vty
, "%% prefix is malformed\n");
1330 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1332 if (pentry
->prefix
.family
== p
.family
1333 && prefix_match(&pentry
->prefix
, &p
))
1342 #ifndef VTYSH_EXTRACT_PL
1343 #include "lib/plist_clippy.c"
1346 DEFPY (ip_prefix_list
,
1348 "ip prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
1351 "Name of a prefix list\n"
1352 "sequence number of an entry\n"
1354 "Specify packets to reject\n"
1355 "Specify packets to forward\n"
1356 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1357 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1358 "Minimum prefix length to be matched\n"
1359 "Minimum prefix length\n"
1360 "Maximum prefix length to be matched\n"
1361 "Maximum prefix length\n")
1363 return vty_prefix_list_install(vty
, AFI_IP
, prefix_list
, seq_str
,
1364 action
, dest
, ge_str
, le_str
);
1367 DEFPY (no_ip_prefix_list
,
1368 no_ip_prefix_list_cmd
,
1369 "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)}]>",
1373 "Name of a prefix list\n"
1374 "sequence number of an entry\n"
1376 "Specify packets to reject\n"
1377 "Specify packets to forward\n"
1378 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1379 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1380 "Minimum prefix length to be matched\n"
1381 "Minimum prefix length\n"
1382 "Maximum prefix length to be matched\n"
1383 "Maximum prefix length\n")
1385 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, seq_str
,
1386 action
, dest
, ge_str
, le_str
);
1389 DEFPY(no_ip_prefix_list_seq
, no_ip_prefix_list_seq_cmd
,
1390 "no ip prefix-list WORD seq (1-4294967295)",
1391 NO_STR IP_STR PREFIX_LIST_STR
1392 "Name of a prefix list\n"
1393 "sequence number of an entry\n"
1394 "Sequence number\n")
1396 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, seq_str
,
1397 NULL
, NULL
, NULL
, NULL
);
1400 DEFPY (no_ip_prefix_list_all
,
1401 no_ip_prefix_list_all_cmd
,
1402 "no ip prefix-list WORD",
1406 "Name of a prefix list\n")
1408 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, NULL
, NULL
,
1412 DEFPY (ip_prefix_list_sequence_number
,
1413 ip_prefix_list_sequence_number_cmd
,
1414 "[no] ip prefix-list sequence-number",
1418 "Include/exclude sequence numbers in NVGEN\n")
1420 prefix_master_ipv4
.seqnum
= no
? false : true;
1424 DEFUN (ip_prefix_list_description
,
1425 ip_prefix_list_description_cmd
,
1426 "ip prefix-list WORD description LINE...",
1429 "Name of a prefix list\n"
1430 "Prefix-list specific description\n"
1431 "Up to 80 characters describing this prefix-list\n")
1435 struct prefix_list
*plist
;
1437 plist
= prefix_list_get(AFI_IP
, 0, argv
[idx_word
]->arg
);
1440 XFREE(MTYPE_TMP
, plist
->desc
);
1443 plist
->desc
= argv_concat(argv
, argc
, idx_line
);
1448 DEFUN (no_ip_prefix_list_description
,
1449 no_ip_prefix_list_description_cmd
,
1450 "no ip prefix-list WORD description",
1454 "Name of a prefix list\n"
1455 "Prefix-list specific description\n")
1458 return vty_prefix_list_desc_unset(vty
, AFI_IP
, argv
[idx_word
]->arg
);
1462 DEFUN (no_ip_prefix_list_description_comment
,
1463 no_ip_prefix_list_description_comment_cmd
,
1464 "no ip prefix-list WORD description LINE...",
1468 "Name of a prefix list\n"
1469 "Prefix-list specific description\n"
1470 "Up to 80 characters describing this prefix-list\n")
1472 return no_ip_prefix_list_description(self
, vty
, argc
, argv
);
1475 DEFPY (show_ip_prefix_list
,
1476 show_ip_prefix_list_cmd
,
1477 "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1481 "Name of a prefix list\n"
1482 "sequence number of an entry\n"
1483 "Sequence number\n")
1485 enum display_type dtype
= normal_display
;
1487 dtype
= sequential_display
;
1489 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, arg_str
, dtype
);
1492 DEFPY (show_ip_prefix_list_prefix
,
1493 show_ip_prefix_list_prefix_cmd
,
1494 "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
1498 "Name of a prefix list\n"
1499 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1500 "Lookup longer prefix\n"
1501 "First matched prefix\n")
1503 enum display_type dtype
= normal_display
;
1505 dtype
= longer_display
;
1507 dtype
= first_match_display
;
1509 return vty_show_prefix_list_prefix(vty
, AFI_IP
, prefix_list
, prefix_str
,
1513 DEFPY (show_ip_prefix_list_summary
,
1514 show_ip_prefix_list_summary_cmd
,
1515 "show ip prefix-list summary [WORD$prefix_list]",
1519 "Summary of prefix lists\n"
1520 "Name of a prefix list\n")
1522 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1526 DEFPY (show_ip_prefix_list_detail
,
1527 show_ip_prefix_list_detail_cmd
,
1528 "show ip prefix-list detail [WORD$prefix_list]",
1532 "Detail of prefix lists\n"
1533 "Name of a prefix list\n")
1535 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1539 DEFPY (clear_ip_prefix_list
,
1540 clear_ip_prefix_list_cmd
,
1541 "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
1545 "Name of a prefix list\n"
1546 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1548 return vty_clear_prefix_list(vty
, AFI_IP
, prefix_list
, prefix_str
);
1551 DEFPY (ipv6_prefix_list
,
1552 ipv6_prefix_list_cmd
,
1553 "ipv6 prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
1556 "Name of a prefix list\n"
1557 "sequence number of an entry\n"
1559 "Specify packets to reject\n"
1560 "Specify packets to forward\n"
1561 "Any prefix match. Same as \"::0/0 le 128\"\n"
1562 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1563 "Maximum prefix length to be matched\n"
1564 "Maximum prefix length\n"
1565 "Minimum prefix length to be matched\n"
1566 "Minimum prefix length\n")
1568 return vty_prefix_list_install(vty
, AFI_IP6
, prefix_list
, seq_str
,
1569 action
, dest
, ge_str
, le_str
);
1572 DEFPY (no_ipv6_prefix_list
,
1573 no_ipv6_prefix_list_cmd
,
1574 "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)}]>",
1578 "Name of a prefix list\n"
1579 "sequence number of an entry\n"
1581 "Specify packets to reject\n"
1582 "Specify packets to forward\n"
1583 "Any prefix match. Same as \"::0/0 le 128\"\n"
1584 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1585 "Maximum prefix length to be matched\n"
1586 "Maximum prefix length\n"
1587 "Minimum prefix length to be matched\n"
1588 "Minimum prefix length\n")
1590 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, seq_str
,
1591 action
, dest
, ge_str
, le_str
);
1594 DEFPY (no_ipv6_prefix_list_all
,
1595 no_ipv6_prefix_list_all_cmd
,
1596 "no ipv6 prefix-list WORD",
1600 "Name of a prefix list\n")
1602 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, NULL
, NULL
,
1606 DEFPY (ipv6_prefix_list_sequence_number
,
1607 ipv6_prefix_list_sequence_number_cmd
,
1608 "[no] ipv6 prefix-list sequence-number",
1612 "Include/exclude sequence numbers in NVGEN\n")
1614 prefix_master_ipv6
.seqnum
= no
? false : true;
1618 DEFUN (ipv6_prefix_list_description
,
1619 ipv6_prefix_list_description_cmd
,
1620 "ipv6 prefix-list WORD description LINE...",
1623 "Name of a prefix list\n"
1624 "Prefix-list specific description\n"
1625 "Up to 80 characters describing this prefix-list\n")
1629 struct prefix_list
*plist
;
1631 plist
= prefix_list_get(AFI_IP6
, 0, argv
[idx_word
]->arg
);
1634 XFREE(MTYPE_TMP
, plist
->desc
);
1637 plist
->desc
= argv_concat(argv
, argc
, iddx_line
);
1642 DEFUN (no_ipv6_prefix_list_description
,
1643 no_ipv6_prefix_list_description_cmd
,
1644 "no ipv6 prefix-list WORD description",
1648 "Name of a prefix list\n"
1649 "Prefix-list specific description\n")
1652 return vty_prefix_list_desc_unset(vty
, AFI_IP6
, argv
[idx_word
]->arg
);
1656 DEFUN (no_ipv6_prefix_list_description_comment
,
1657 no_ipv6_prefix_list_description_comment_cmd
,
1658 "no ipv6 prefix-list WORD description LINE...",
1662 "Name of a prefix list\n"
1663 "Prefix-list specific description\n"
1664 "Up to 80 characters describing this prefix-list\n")
1666 return no_ipv6_prefix_list_description(self
, vty
, argc
, argv
);
1670 DEFPY (show_ipv6_prefix_list
,
1671 show_ipv6_prefix_list_cmd
,
1672 "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1676 "Name of a prefix list\n"
1677 "sequence number of an entry\n"
1678 "Sequence number\n")
1680 enum display_type dtype
= normal_display
;
1682 dtype
= sequential_display
;
1684 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, arg_str
, dtype
);
1687 DEFPY (show_ipv6_prefix_list_prefix
,
1688 show_ipv6_prefix_list_prefix_cmd
,
1689 "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
1693 "Name of a prefix list\n"
1694 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1695 "Lookup longer prefix\n"
1696 "First matched prefix\n")
1698 enum display_type dtype
= normal_display
;
1700 dtype
= longer_display
;
1702 dtype
= first_match_display
;
1704 return vty_show_prefix_list_prefix(vty
, AFI_IP6
, prefix_list
,
1708 DEFPY (show_ipv6_prefix_list_summary
,
1709 show_ipv6_prefix_list_summary_cmd
,
1710 "show ipv6 prefix-list summary [WORD$prefix-list]",
1714 "Summary of prefix lists\n"
1715 "Name of a prefix list\n")
1717 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1721 DEFPY (show_ipv6_prefix_list_detail
,
1722 show_ipv6_prefix_list_detail_cmd
,
1723 "show ipv6 prefix-list detail [WORD$prefix-list]",
1727 "Detail of prefix lists\n"
1728 "Name of a prefix list\n")
1730 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1734 DEFPY (clear_ipv6_prefix_list
,
1735 clear_ipv6_prefix_list_cmd
,
1736 "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
1740 "Name of a prefix list\n"
1741 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
1743 return vty_clear_prefix_list(vty
, AFI_IP6
, prefix_list
, prefix_str
);
1746 /* Configuration write function. */
1747 static int config_write_prefix_afi(afi_t afi
, struct vty
*vty
)
1749 struct prefix_list
*plist
;
1750 struct prefix_list_entry
*pentry
;
1751 struct prefix_master
*master
;
1754 master
= prefix_master_get(afi
, 0);
1758 if (!master
->seqnum
) {
1759 vty_out(vty
, "no ip%s prefix-list sequence-number\n",
1760 afi
== AFI_IP
? "" : "v6");
1761 vty_out(vty
, "!\n");
1764 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
) {
1766 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1767 afi
== AFI_IP
? "" : "v6", plist
->name
,
1772 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1773 vty_out(vty
, "ip%s prefix-list %s ",
1774 afi
== AFI_IP
? "" : "v6", plist
->name
);
1777 vty_out(vty
, "seq %" PRId64
" ", pentry
->seq
);
1779 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1782 vty_out(vty
, "any");
1784 struct prefix
*p
= &pentry
->prefix
;
1787 vty_out(vty
, "%s/%d",
1788 inet_ntop(p
->family
, p
->u
.val
, buf
,
1793 vty_out(vty
, " ge %d", pentry
->ge
);
1795 vty_out(vty
, " le %d", pentry
->le
);
1800 /* vty_out (vty, "!\n"); */
1803 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
) {
1805 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1806 afi
== AFI_IP
? "" : "v6", plist
->name
,
1811 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1812 vty_out(vty
, "ip%s prefix-list %s ",
1813 afi
== AFI_IP
? "" : "v6", plist
->name
);
1816 vty_out(vty
, "seq %" PRId64
" ", pentry
->seq
);
1818 vty_out(vty
, "%s", prefix_list_type_str(pentry
));
1821 vty_out(vty
, " any");
1823 struct prefix
*p
= &pentry
->prefix
;
1826 vty_out(vty
, " %s/%d",
1827 inet_ntop(p
->family
, p
->u
.val
, buf
,
1832 vty_out(vty
, " ge %d", pentry
->ge
);
1834 vty_out(vty
, " le %d", pentry
->le
);
1844 struct stream
*prefix_bgp_orf_entry(struct stream
*s
, struct prefix_list
*plist
,
1845 uint8_t init_flag
, uint8_t permit_flag
,
1848 struct prefix_list_entry
*pentry
;
1853 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1854 uint8_t flag
= init_flag
;
1855 struct prefix
*p
= &pentry
->prefix
;
1857 flag
|= (pentry
->type
== PREFIX_PERMIT
? permit_flag
1859 stream_putc(s
, flag
);
1860 stream_putl(s
, (uint32_t)pentry
->seq
);
1861 stream_putc(s
, (uint8_t)pentry
->ge
);
1862 stream_putc(s
, (uint8_t)pentry
->le
);
1863 stream_put_prefix(s
, p
);
1869 int prefix_bgp_orf_set(char *name
, afi_t afi
, struct orf_prefix
*orfp
,
1870 int permit
, int set
)
1872 struct prefix_list
*plist
;
1873 struct prefix_list_entry
*pentry
;
1875 /* ge and le value check */
1876 if (orfp
->ge
&& orfp
->ge
<= orfp
->p
.prefixlen
)
1877 return CMD_WARNING_CONFIG_FAILED
;
1878 if (orfp
->le
&& orfp
->le
<= orfp
->p
.prefixlen
)
1879 return CMD_WARNING_CONFIG_FAILED
;
1880 if (orfp
->le
&& orfp
->ge
> orfp
->le
)
1881 return CMD_WARNING_CONFIG_FAILED
;
1883 if (orfp
->ge
&& orfp
->le
== (afi
== AFI_IP
? 32 : 128))
1886 plist
= prefix_list_get(afi
, 1, name
);
1888 return CMD_WARNING_CONFIG_FAILED
;
1890 apply_mask(&orfp
->p
);
1893 pentry
= prefix_list_entry_make(
1894 &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1895 orfp
->seq
, orfp
->le
, orfp
->ge
, 0);
1897 if (prefix_entry_dup_check(plist
, pentry
)) {
1898 prefix_list_entry_free(pentry
);
1899 return CMD_WARNING_CONFIG_FAILED
;
1902 prefix_list_entry_add(plist
, pentry
);
1904 pentry
= prefix_list_entry_lookup(
1905 plist
, &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1906 orfp
->seq
, orfp
->le
, orfp
->ge
);
1909 return CMD_WARNING_CONFIG_FAILED
;
1911 prefix_list_entry_delete(plist
, pentry
, 1);
1917 void prefix_bgp_orf_remove_all(afi_t afi
, char *name
)
1919 struct prefix_list
*plist
;
1921 plist
= prefix_bgp_orf_lookup(afi
, name
);
1923 prefix_list_delete(plist
);
1926 /* return prefix count */
1927 int prefix_bgp_show_prefix_list(struct vty
*vty
, afi_t afi
, char *name
,
1930 struct prefix_list
*plist
;
1931 struct prefix_list_entry
*pentry
;
1932 json_object
*json
= NULL
;
1933 json_object
*json_prefix
= NULL
;
1934 json_object
*json_list
= NULL
;
1936 plist
= prefix_bgp_orf_lookup(afi
, name
);
1941 return plist
->count
;
1944 json
= json_object_new_object();
1945 json_prefix
= json_object_new_object();
1946 json_list
= json_object_new_object();
1948 json_object_int_add(json_prefix
, "prefixListCounter",
1950 json_object_string_add(json_prefix
, "prefixListName",
1953 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1954 struct prefix
*p
= &pentry
->prefix
;
1958 sprintf(buf_a
, "%s/%d",
1959 inet_ntop(p
->family
, p
->u
.val
, buf_b
,
1963 json_object_int_add(json_list
, "seq", pentry
->seq
);
1964 json_object_string_add(json_list
, "seqPrefixListType",
1965 prefix_list_type_str(pentry
));
1968 json_object_int_add(json_list
, "ge",
1971 json_object_int_add(json_list
, "le",
1974 json_object_object_add(json_prefix
, buf_a
, json_list
);
1977 json_object_object_add(json
, "ipPrefixList",
1980 json_object_object_add(json
, "ipv6PrefixList",
1983 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1984 json
, JSON_C_TO_STRING_PRETTY
));
1985 json_object_free(json
);
1987 vty_out(vty
, "ip%s prefix-list %s: %d entries\n",
1988 afi
== AFI_IP
? "" : "v6", plist
->name
, plist
->count
);
1990 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1991 struct prefix
*p
= &pentry
->prefix
;
1994 vty_out(vty
, " seq %" PRId64
" %s %s/%d",
1996 prefix_list_type_str(pentry
),
1997 inet_ntop(p
->family
, p
->u
.val
, buf
, BUFSIZ
),
2001 vty_out(vty
, " ge %d", pentry
->ge
);
2003 vty_out(vty
, " le %d", pentry
->le
);
2008 return plist
->count
;
2011 static void prefix_list_reset_afi(afi_t afi
, int orf
)
2013 struct prefix_list
*plist
;
2014 struct prefix_list
*next
;
2015 struct prefix_master
*master
;
2017 master
= prefix_master_get(afi
, orf
);
2021 for (plist
= master
->num
.head
; plist
; plist
= next
) {
2023 prefix_list_delete(plist
);
2025 for (plist
= master
->str
.head
; plist
; plist
= next
) {
2027 prefix_list_delete(plist
);
2030 assert(master
->num
.head
== NULL
);
2031 assert(master
->num
.tail
== NULL
);
2033 assert(master
->str
.head
== NULL
);
2034 assert(master
->str
.tail
== NULL
);
2037 master
->recent
= NULL
;
2041 /* Prefix-list node. */
2042 static struct cmd_node prefix_node
= {PREFIX_NODE
,
2043 "", /* Prefix list has no interface. */
2046 static int config_write_prefix_ipv4(struct vty
*vty
)
2048 return config_write_prefix_afi(AFI_IP
, vty
);
2051 static void plist_autocomplete_afi(afi_t afi
, vector comps
,
2052 struct cmd_token
*token
)
2054 struct prefix_list
*plist
;
2055 struct prefix_master
*master
;
2057 master
= prefix_master_get(afi
, 0);
2061 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
2062 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, plist
->name
));
2063 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
2064 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, plist
->name
));
2067 static void plist_autocomplete(vector comps
, struct cmd_token
*token
)
2069 plist_autocomplete_afi(AFI_IP
, comps
, token
);
2070 plist_autocomplete_afi(AFI_IP6
, comps
, token
);
2073 static const struct cmd_variable_handler plist_var_handlers
[] = {
2074 {/* "prefix-list WORD" */
2075 .varname
= "prefix_list",
2076 .completions
= plist_autocomplete
},
2077 {.completions
= NULL
}};
2080 static void prefix_list_init_ipv4(void)
2082 install_node(&prefix_node
, config_write_prefix_ipv4
);
2084 install_element(CONFIG_NODE
, &ip_prefix_list_cmd
);
2085 install_element(CONFIG_NODE
, &no_ip_prefix_list_cmd
);
2086 install_element(CONFIG_NODE
, &no_ip_prefix_list_seq_cmd
);
2087 install_element(CONFIG_NODE
, &no_ip_prefix_list_all_cmd
);
2089 install_element(CONFIG_NODE
, &ip_prefix_list_description_cmd
);
2090 install_element(CONFIG_NODE
, &no_ip_prefix_list_description_cmd
);
2091 install_element(CONFIG_NODE
,
2092 &no_ip_prefix_list_description_comment_cmd
);
2094 install_element(CONFIG_NODE
, &ip_prefix_list_sequence_number_cmd
);
2096 install_element(VIEW_NODE
, &show_ip_prefix_list_cmd
);
2097 install_element(VIEW_NODE
, &show_ip_prefix_list_prefix_cmd
);
2098 install_element(VIEW_NODE
, &show_ip_prefix_list_summary_cmd
);
2099 install_element(VIEW_NODE
, &show_ip_prefix_list_detail_cmd
);
2101 install_element(ENABLE_NODE
, &clear_ip_prefix_list_cmd
);
2104 /* Prefix-list node. */
2105 static struct cmd_node prefix_ipv6_node
= {
2106 PREFIX_IPV6_NODE
, "", /* Prefix list has no interface. */
2109 static int config_write_prefix_ipv6(struct vty
*vty
)
2111 return config_write_prefix_afi(AFI_IP6
, vty
);
2114 static void prefix_list_init_ipv6(void)
2116 install_node(&prefix_ipv6_node
, config_write_prefix_ipv6
);
2118 install_element(CONFIG_NODE
, &ipv6_prefix_list_cmd
);
2119 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_cmd
);
2120 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_all_cmd
);
2122 install_element(CONFIG_NODE
, &ipv6_prefix_list_description_cmd
);
2123 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_description_cmd
);
2124 install_element(CONFIG_NODE
,
2125 &no_ipv6_prefix_list_description_comment_cmd
);
2127 install_element(CONFIG_NODE
, &ipv6_prefix_list_sequence_number_cmd
);
2129 install_element(VIEW_NODE
, &show_ipv6_prefix_list_cmd
);
2130 install_element(VIEW_NODE
, &show_ipv6_prefix_list_prefix_cmd
);
2131 install_element(VIEW_NODE
, &show_ipv6_prefix_list_summary_cmd
);
2132 install_element(VIEW_NODE
, &show_ipv6_prefix_list_detail_cmd
);
2134 install_element(ENABLE_NODE
, &clear_ipv6_prefix_list_cmd
);
2137 void prefix_list_init(void)
2139 cmd_variable_handler_register(plist_var_handlers
);
2141 prefix_list_init_ipv4();
2142 prefix_list_init_ipv6();
2145 void prefix_list_reset(void)
2147 prefix_list_reset_afi(AFI_IP
, 0);
2148 prefix_list_reset_afi(AFI_IP6
, 0);
2149 prefix_list_reset_afi(AFI_IP
, 1);
2150 prefix_list_reset_afi(AFI_IP6
, 1);