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
)->prefix
.prefixlen
== object
->prefix
.prefixlen
542 && (*updptr
)->seq
> object
->seq
)
544 updptr
= &(*updptr
)->next_best
;
547 if (!object
->next_best
)
548 object
->next_best
= *updptr
;
550 assert(object
->next_best
== *updptr
|| !*updptr
);
555 static void prefix_list_trie_add(struct prefix_list
*plist
,
556 struct prefix_list_entry
*pentry
)
558 size_t depth
= plist
->master
->trie_depth
;
559 uint8_t *bytes
= &pentry
->prefix
.u
.prefix
;
560 size_t validbits
= pentry
->prefix
.prefixlen
;
561 struct pltrie_table
*table
;
564 while (validbits
> PLC_BITS
&& depth
> 1) {
565 if (!table
->entries
[*bytes
].next_table
)
566 table
->entries
[*bytes
].next_table
=
567 XCALLOC(MTYPE_PREFIX_LIST_TRIE
,
568 sizeof(struct pltrie_table
));
569 table
= table
->entries
[*bytes
].next_table
;
572 validbits
-= PLC_BITS
;
575 trie_walk_affected(validbits
, table
, *bytes
, pentry
, trie_install_fn
);
578 static void prefix_list_entry_add(struct prefix_list
*plist
,
579 struct prefix_list_entry
*pentry
)
581 struct prefix_list_entry
*replace
;
582 struct prefix_list_entry
*point
;
584 /* Automatic asignment of seq no. */
585 if (pentry
->seq
== -1)
586 pentry
->seq
= prefix_new_seq_get(plist
);
588 if (plist
->tail
&& pentry
->seq
> plist
->tail
->seq
)
591 /* Is there any same seq prefix list entry? */
592 replace
= prefix_seq_check(plist
, pentry
->seq
);
594 prefix_list_entry_delete(plist
, replace
, 0);
596 /* Check insert point. */
597 for (point
= plist
->head
; point
; point
= point
->next
)
598 if (point
->seq
>= pentry
->seq
)
602 /* In case of this is the first element of the list. */
603 pentry
->next
= point
;
607 point
->prev
->next
= pentry
;
609 plist
->head
= pentry
;
611 pentry
->prev
= point
->prev
;
612 point
->prev
= pentry
;
615 plist
->tail
->next
= pentry
;
617 plist
->head
= pentry
;
619 pentry
->prev
= plist
->tail
;
620 plist
->tail
= pentry
;
623 prefix_list_trie_add(plist
, pentry
);
625 /* Increment count. */
628 /* Run hook function. */
629 if (plist
->master
->add_hook
)
630 (*plist
->master
->add_hook
)(plist
);
632 route_map_notify_dependencies(plist
->name
, RMAP_EVENT_PLIST_ADDED
);
633 plist
->master
->recent
= plist
;
636 /* Return string of prefix_list_type. */
637 static const char *prefix_list_type_str(struct prefix_list_entry
*pentry
)
639 switch (pentry
->type
) {
649 static int prefix_list_entry_match(struct prefix_list_entry
*pentry
,
654 ret
= prefix_match(&pentry
->prefix
, p
);
658 /* In case of le nor ge is specified, exact match is performed. */
659 if (!pentry
->le
&& !pentry
->ge
) {
660 if (pentry
->prefix
.prefixlen
!= p
->prefixlen
)
664 if (p
->prefixlen
> pentry
->le
)
668 if (p
->prefixlen
< pentry
->ge
)
674 enum prefix_list_type
prefix_list_apply(struct prefix_list
*plist
, void *object
)
676 struct prefix_list_entry
*pentry
, *pbest
= NULL
;
678 struct prefix
*p
= (struct prefix
*)object
;
679 uint8_t *byte
= &p
->u
.prefix
;
681 size_t validbits
= p
->prefixlen
;
682 struct pltrie_table
*table
;
687 if (plist
->count
== 0)
688 return PREFIX_PERMIT
;
690 depth
= plist
->master
->trie_depth
;
693 for (pentry
= table
->entries
[*byte
].up_chain
; pentry
;
694 pentry
= pentry
->next_best
) {
695 if (pbest
&& pbest
->seq
< pentry
->seq
)
697 if (prefix_list_entry_match(pentry
, p
))
701 if (validbits
<= PLC_BITS
)
703 validbits
-= PLC_BITS
;
706 if (!table
->entries
[*byte
].next_table
)
709 table
= table
->entries
[*byte
].next_table
;
714 for (pentry
= table
->entries
[*byte
].final_chain
; pentry
;
715 pentry
= pentry
->next_best
) {
716 if (pbest
&& pbest
->seq
< pentry
->seq
)
718 if (prefix_list_entry_match(pentry
, p
))
730 static void __attribute__((unused
)) prefix_list_print(struct prefix_list
*plist
)
732 struct prefix_list_entry
*pentry
;
737 printf("ip prefix-list %s: %d entries\n", plist
->name
, plist
->count
);
739 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
741 printf("any %s\n", prefix_list_type_str(pentry
));
748 printf(" seq %u %s %s/%d", pentry
->seq
,
749 prefix_list_type_str(pentry
),
750 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
753 printf(" ge %d", pentry
->ge
);
755 printf(" le %d", pentry
->le
);
761 /* Retrun 1 when plist already include pentry policy. */
762 static struct prefix_list_entry
*
763 prefix_entry_dup_check(struct prefix_list
*plist
, struct prefix_list_entry
*new)
765 size_t depth
, maxdepth
= plist
->master
->trie_depth
;
766 uint8_t byte
, *bytes
= &new->prefix
.u
.prefix
;
767 size_t validbits
= new->prefix
.prefixlen
;
768 struct pltrie_table
*table
;
769 struct prefix_list_entry
*pentry
;
773 seq
= prefix_new_seq_get(plist
);
778 for (depth
= 0; validbits
> PLC_BITS
&& depth
< maxdepth
- 1; depth
++) {
780 if (!table
->entries
[byte
].next_table
)
783 table
= table
->entries
[byte
].next_table
;
784 validbits
-= PLC_BITS
;
788 if (validbits
> PLC_BITS
)
789 pentry
= table
->entries
[byte
].final_chain
;
791 pentry
= table
->entries
[byte
].up_chain
;
793 for (; pentry
; pentry
= pentry
->next_best
) {
794 if (prefix_same(&pentry
->prefix
, &new->prefix
)
795 && pentry
->type
== new->type
&& pentry
->le
== new->le
796 && pentry
->ge
== new->ge
&& pentry
->seq
!= seq
)
802 static int vty_invalid_prefix_range(struct vty
*vty
, const char *prefix
)
805 "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n",
807 return CMD_WARNING_CONFIG_FAILED
;
810 static int vty_prefix_list_install(struct vty
*vty
, afi_t afi
, const char *name
,
811 const char *seq
, const char *typestr
,
812 const char *prefix
, const char *ge
,
816 enum prefix_list_type type
;
817 struct prefix_list
*plist
;
818 struct prefix_list_entry
*pentry
;
819 struct prefix_list_entry
*dup
;
820 struct prefix p
, p_tmp
;
826 /* Sequential number. */
830 /* ge and le number */
836 /* Check filter type. */
837 if (strncmp("permit", typestr
, 1) == 0)
838 type
= PREFIX_PERMIT
;
839 else if (strncmp("deny", typestr
, 1) == 0)
842 vty_out(vty
, "%% prefix type must be permit or deny\n");
843 return CMD_WARNING_CONFIG_FAILED
;
846 /* "any" is special token for matching any IPv4 addresses. */
849 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
850 ret
= str2prefix_ipv4("0.0.0.0/0",
851 (struct prefix_ipv4
*)&p
);
853 lenum
= IPV4_MAX_BITLEN
;
856 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
859 vty_out(vty
, "%% Malformed IPv4 prefix\n");
860 return CMD_WARNING_CONFIG_FAILED
;
863 /* make a copy to verify prefix matches mask length */
864 prefix_copy(&p_tmp
, &p
);
865 apply_mask_ipv4((struct prefix_ipv4
*)&p_tmp
);
869 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
870 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
872 lenum
= IPV6_MAX_BITLEN
;
875 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
878 vty_out(vty
, "%% Malformed IPv6 prefix\n");
879 return CMD_WARNING_CONFIG_FAILED
;
882 /* make a copy to verify prefix matches mask length */
883 prefix_copy(&p_tmp
, &p
);
884 apply_mask_ipv6((struct prefix_ipv6
*)&p_tmp
);
889 vty_out(vty
, "%% Unrecognized AFI (%d)\n", afi
);
890 return CMD_WARNING_CONFIG_FAILED
;
894 /* If prefix has bits not under the mask, adjust it to fit */
895 if (!prefix_same(&p_tmp
, &p
)) {
896 char buf
[PREFIX2STR_BUFFER
];
897 char buf_tmp
[PREFIX2STR_BUFFER
];
898 prefix2str(&p
, buf
, sizeof(buf
));
899 prefix2str(&p_tmp
, buf_tmp
, sizeof(buf_tmp
));
901 "Prefix-list %s prefix changed from %s to %s to match length",
906 /* ge and le check. */
907 if (genum
&& (genum
<= p
.prefixlen
))
908 return vty_invalid_prefix_range(vty
, prefix
);
910 if (lenum
&& (lenum
<= p
.prefixlen
))
911 return vty_invalid_prefix_range(vty
, prefix
);
913 if (lenum
&& (genum
> lenum
))
914 return vty_invalid_prefix_range(vty
, prefix
);
916 if (genum
&& (lenum
== (afi
== AFI_IP
? 32 : 128)))
919 /* Get prefix_list with name. */
920 plist
= prefix_list_get(afi
, 0, name
);
922 /* Make prefix entry. */
923 pentry
= prefix_list_entry_make(&p
, type
, seqnum
, lenum
, genum
, any
);
925 /* Check same policy. */
926 dup
= prefix_entry_dup_check(plist
, pentry
);
929 prefix_list_entry_free(pentry
);
933 /* Install new filter to the access_list. */
934 prefix_list_entry_add(plist
, pentry
);
939 static int vty_prefix_list_uninstall(struct vty
*vty
, afi_t afi
,
940 const char *name
, const char *seq
,
941 const char *typestr
, const char *prefix
,
942 const char *ge
, const char *le
)
945 enum prefix_list_type type
;
946 struct prefix_list
*plist
;
947 struct prefix_list_entry
*pentry
;
953 /* Check prefix list name. */
954 plist
= prefix_list_lookup(afi
, name
);
956 vty_out(vty
, "%% Can't find specified prefix-list\n");
957 return CMD_WARNING_CONFIG_FAILED
;
960 /* Only prefix-list name specified, delete the entire prefix-list. */
961 if (seq
== NULL
&& typestr
== NULL
&& prefix
== NULL
&& ge
== NULL
963 prefix_list_delete(plist
);
967 /* We must have, at a minimum, both the type and prefix here */
968 if ((typestr
== NULL
) || (prefix
== NULL
)) {
969 vty_out(vty
, "%% Both prefix and type required\n");
970 return CMD_WARNING_CONFIG_FAILED
;
973 /* Check sequence number. */
977 /* ge and le number */
983 /* Check of filter type. */
984 if (strncmp("permit", typestr
, 1) == 0)
985 type
= PREFIX_PERMIT
;
986 else if (strncmp("deny", typestr
, 1) == 0)
989 vty_out(vty
, "%% prefix type must be permit or deny\n");
990 return CMD_WARNING_CONFIG_FAILED
;
993 /* "any" is special token for matching any IPv4 addresses. */
995 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
996 ret
= str2prefix_ipv4("0.0.0.0/0",
997 (struct prefix_ipv4
*)&p
);
999 lenum
= IPV4_MAX_BITLEN
;
1001 ret
= str2prefix_ipv4(prefix
, (struct prefix_ipv4
*)&p
);
1004 vty_out(vty
, "%% Malformed IPv4 prefix\n");
1005 return CMD_WARNING_CONFIG_FAILED
;
1007 } else if (afi
== AFI_IP6
) {
1008 if (strncmp("any", prefix
, strlen(prefix
)) == 0) {
1009 ret
= str2prefix_ipv6("::/0", (struct prefix_ipv6
*)&p
);
1011 lenum
= IPV6_MAX_BITLEN
;
1013 ret
= str2prefix_ipv6(prefix
, (struct prefix_ipv6
*)&p
);
1016 vty_out(vty
, "%% Malformed IPv6 prefix\n");
1017 return CMD_WARNING_CONFIG_FAILED
;
1021 /* Lookup prefix entry. */
1023 prefix_list_entry_lookup(plist
, &p
, type
, seqnum
, lenum
, genum
);
1025 if (pentry
== NULL
) {
1026 vty_out(vty
, "%% Can't find specified prefix-list\n");
1027 return CMD_WARNING_CONFIG_FAILED
;
1030 /* Install new filter to the access_list. */
1031 prefix_list_entry_delete(plist
, pentry
, 1);
1036 static int vty_prefix_list_desc_unset(struct vty
*vty
, afi_t afi
,
1039 struct prefix_list
*plist
;
1041 plist
= prefix_list_lookup(afi
, name
);
1043 vty_out(vty
, "%% Can't find specified prefix-list\n");
1044 return CMD_WARNING_CONFIG_FAILED
;
1048 XFREE(MTYPE_TMP
, plist
->desc
);
1052 if (plist
->head
== NULL
&& plist
->tail
== NULL
&& plist
->desc
== NULL
)
1053 prefix_list_delete(plist
);
1067 static void vty_show_prefix_entry(struct vty
*vty
, afi_t afi
,
1068 struct prefix_list
*plist
,
1069 struct prefix_master
*master
,
1070 enum display_type dtype
, int seqnum
)
1072 struct prefix_list_entry
*pentry
;
1074 /* Print the name of the protocol */
1075 vty_out(vty
, "%s: ", frr_protoname
);
1077 if (dtype
== normal_display
) {
1078 vty_out(vty
, "ip%s prefix-list %s: %d entries\n",
1079 afi
== AFI_IP
? "" : "v6", plist
->name
, plist
->count
);
1081 vty_out(vty
, " Description: %s\n", plist
->desc
);
1082 } else if (dtype
== summary_display
|| dtype
== detail_display
) {
1083 vty_out(vty
, "ip%s prefix-list %s:\n",
1084 afi
== AFI_IP
? "" : "v6", plist
->name
);
1087 vty_out(vty
, " Description: %s\n", plist
->desc
);
1090 " count: %d, range entries: %d, sequences: %u - %u\n",
1091 plist
->count
, plist
->rangecount
,
1092 plist
->head
? plist
->head
->seq
: 0,
1093 plist
->tail
? plist
->tail
->seq
: 0);
1096 if (dtype
!= summary_display
) {
1097 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1098 if (dtype
== sequential_display
1099 && pentry
->seq
!= seqnum
)
1105 vty_out(vty
, "seq %u ", pentry
->seq
);
1107 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1110 vty_out(vty
, "any");
1112 struct prefix
*p
= &pentry
->prefix
;
1115 vty_out(vty
, "%s/%d",
1116 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1121 vty_out(vty
, " ge %d", pentry
->ge
);
1123 vty_out(vty
, " le %d", pentry
->le
);
1126 if (dtype
== detail_display
1127 || dtype
== sequential_display
)
1128 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1129 pentry
->hitcnt
, pentry
->refcnt
);
1136 static int vty_show_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1137 const char *seq
, enum display_type dtype
)
1139 struct prefix_list
*plist
;
1140 struct prefix_master
*master
;
1143 master
= prefix_master_get(afi
, 0);
1151 plist
= prefix_list_lookup(afi
, name
);
1153 vty_out(vty
, "%% Can't find specified prefix-list\n");
1156 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
, seqnum
);
1158 if (dtype
== detail_display
|| dtype
== summary_display
) {
1161 "Prefix-list with the last deletion/insertion: %s\n",
1162 master
->recent
->name
);
1165 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
1166 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
1169 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1170 vty_show_prefix_entry(vty
, afi
, plist
, master
, dtype
,
1177 static int vty_show_prefix_list_prefix(struct vty
*vty
, afi_t afi
,
1178 const char *name
, const char *prefix
,
1179 enum display_type type
)
1181 struct prefix_list
*plist
;
1182 struct prefix_list_entry
*pentry
;
1187 plist
= prefix_list_lookup(afi
, name
);
1189 vty_out(vty
, "%% Can't find specified prefix-list\n");
1193 ret
= str2prefix(prefix
, &p
);
1195 vty_out(vty
, "%% prefix is malformed\n");
1199 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1202 if (type
== normal_display
|| type
== first_match_display
)
1203 if (prefix_same(&p
, &pentry
->prefix
))
1206 if (type
== longer_display
)
1207 if (prefix_match(&p
, &pentry
->prefix
))
1211 vty_out(vty
, " seq %u %s ", pentry
->seq
,
1212 prefix_list_type_str(pentry
));
1215 vty_out(vty
, "any");
1217 struct prefix
*p
= &pentry
->prefix
;
1220 vty_out(vty
, "%s/%d",
1221 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1226 vty_out(vty
, " ge %d", pentry
->ge
);
1228 vty_out(vty
, " le %d", pentry
->le
);
1231 if (type
== normal_display
1232 || type
== first_match_display
)
1233 vty_out(vty
, " (hit count: %ld, refcount: %ld)",
1234 pentry
->hitcnt
, pentry
->refcnt
);
1238 if (type
== first_match_display
)
1245 static int vty_clear_prefix_list(struct vty
*vty
, afi_t afi
, const char *name
,
1248 struct prefix_master
*master
;
1249 struct prefix_list
*plist
;
1250 struct prefix_list_entry
*pentry
;
1254 master
= prefix_master_get(afi
, 0);
1258 if (name
== NULL
&& prefix
== NULL
) {
1259 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
1260 for (pentry
= plist
->head
; pentry
;
1261 pentry
= pentry
->next
)
1264 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
1265 for (pentry
= plist
->head
; pentry
;
1266 pentry
= pentry
->next
)
1269 plist
= prefix_list_lookup(afi
, name
);
1271 vty_out(vty
, "%% Can't find specified prefix-list\n");
1276 ret
= str2prefix(prefix
, &p
);
1278 vty_out(vty
, "%% prefix is malformed\n");
1283 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1285 if (prefix_match(&pentry
->prefix
, &p
))
1294 #ifndef VTYSH_EXTRACT_PL
1295 #include "plist_clippy.c"
1298 DEFPY (ip_prefix_list
,
1300 "ip prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
1303 "Name of a prefix list\n"
1304 "sequence number of an entry\n"
1306 "Specify packets to reject\n"
1307 "Specify packets to forward\n"
1308 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1309 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1310 "Minimum prefix length to be matched\n"
1311 "Minimum prefix length\n"
1312 "Maximum prefix length to be matched\n"
1313 "Maximum prefix length\n")
1315 return vty_prefix_list_install(vty
, AFI_IP
, prefix_list
, seq_str
,
1316 action
, dest
, ge_str
, le_str
);
1319 DEFPY (no_ip_prefix_list
,
1320 no_ip_prefix_list_cmd
,
1321 "no ip prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|A.B.C.D/M$dest [{ge (0-32)|le (0-32)}]>",
1325 "Name of a prefix list\n"
1326 "sequence number of an entry\n"
1328 "Specify packets to reject\n"
1329 "Specify packets to forward\n"
1330 "Any prefix match. Same as \"0.0.0.0/0 le 32\"\n"
1331 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1332 "Minimum prefix length to be matched\n"
1333 "Minimum prefix length\n"
1334 "Maximum prefix length to be matched\n"
1335 "Maximum prefix length\n")
1337 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, seq_str
,
1338 action
, dest
, ge_str
, le_str
);
1341 DEFPY (no_ip_prefix_list_all
,
1342 no_ip_prefix_list_all_cmd
,
1343 "no ip prefix-list WORD",
1347 "Name of a prefix list\n")
1349 return vty_prefix_list_uninstall(vty
, AFI_IP
, prefix_list
, NULL
, NULL
,
1353 DEFPY (ip_prefix_list_sequence_number
,
1354 ip_prefix_list_sequence_number_cmd
,
1355 "[no] ip prefix-list sequence-number",
1359 "Include/exclude sequence numbers in NVGEN\n")
1361 prefix_master_ipv4
.seqnum
= no
? 0 : 1;
1365 DEFUN (ip_prefix_list_description
,
1366 ip_prefix_list_description_cmd
,
1367 "ip prefix-list WORD description LINE...",
1370 "Name of a prefix list\n"
1371 "Prefix-list specific description\n"
1372 "Up to 80 characters describing this prefix-list\n")
1376 struct prefix_list
*plist
;
1378 plist
= prefix_list_get(AFI_IP
, 0, argv
[idx_word
]->arg
);
1381 XFREE(MTYPE_TMP
, plist
->desc
);
1384 plist
->desc
= argv_concat(argv
, argc
, idx_line
);
1389 DEFUN (no_ip_prefix_list_description
,
1390 no_ip_prefix_list_description_cmd
,
1391 "no ip prefix-list WORD description",
1395 "Name of a prefix list\n"
1396 "Prefix-list specific description\n")
1399 return vty_prefix_list_desc_unset(vty
, AFI_IP
, argv
[idx_word
]->arg
);
1403 DEFUN (no_ip_prefix_list_description_comment
,
1404 no_ip_prefix_list_description_comment_cmd
,
1405 "no ip prefix-list WORD description LINE...",
1409 "Name of a prefix list\n"
1410 "Prefix-list specific description\n"
1411 "Up to 80 characters describing this prefix-list\n")
1413 return no_ip_prefix_list_description(self
, vty
, argc
, argv
);
1416 DEFPY (show_ip_prefix_list
,
1417 show_ip_prefix_list_cmd
,
1418 "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1422 "Name of a prefix list\n"
1423 "sequence number of an entry\n"
1424 "Sequence number\n")
1426 enum display_type dtype
= normal_display
;
1428 dtype
= sequential_display
;
1430 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, arg_str
, dtype
);
1433 DEFPY (show_ip_prefix_list_prefix
,
1434 show_ip_prefix_list_prefix_cmd
,
1435 "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
1439 "Name of a prefix list\n"
1440 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1441 "Lookup longer prefix\n"
1442 "First matched prefix\n")
1444 enum display_type dtype
= normal_display
;
1446 dtype
= longer_display
;
1448 dtype
= first_match_display
;
1450 return vty_show_prefix_list_prefix(vty
, AFI_IP
, prefix_list
, prefix_str
,
1454 DEFPY (show_ip_prefix_list_summary
,
1455 show_ip_prefix_list_summary_cmd
,
1456 "show ip prefix-list summary [WORD$prefix_list]",
1460 "Summary of prefix lists\n"
1461 "Name of a prefix list\n")
1463 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1467 DEFPY (show_ip_prefix_list_detail
,
1468 show_ip_prefix_list_detail_cmd
,
1469 "show ip prefix-list detail [WORD$prefix_list]",
1473 "Detail of prefix lists\n"
1474 "Name of a prefix list\n")
1476 return vty_show_prefix_list(vty
, AFI_IP
, prefix_list
, NULL
,
1480 DEFPY (clear_ip_prefix_list
,
1481 clear_ip_prefix_list_cmd
,
1482 "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
1486 "Name of a prefix list\n"
1487 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1489 return vty_clear_prefix_list(vty
, AFI_IP
, prefix_list
, prefix_str
);
1492 DEFPY (ipv6_prefix_list
,
1493 ipv6_prefix_list_cmd
,
1494 "ipv6 prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
1497 "Name of a prefix list\n"
1498 "sequence number of an entry\n"
1500 "Specify packets to reject\n"
1501 "Specify packets to forward\n"
1502 "Any prefix match. Same as \"::0/0 le 128\"\n"
1503 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1504 "Maximum prefix length to be matched\n"
1505 "Maximum prefix length\n"
1506 "Minimum prefix length to be matched\n"
1507 "Minimum prefix length\n")
1509 return vty_prefix_list_install(vty
, AFI_IP6
, prefix_list
, seq_str
,
1510 action
, dest
, ge_str
, le_str
);
1513 DEFPY (no_ipv6_prefix_list
,
1514 no_ipv6_prefix_list_cmd
,
1515 "no ipv6 prefix-list WORD [seq (1-4294967295)] <deny|permit>$action <any$dest|X:X::X:X/M$dest [{ge (0-128)|le (0-128)}]>",
1519 "Name of a prefix list\n"
1520 "sequence number of an entry\n"
1522 "Specify packets to reject\n"
1523 "Specify packets to forward\n"
1524 "Any prefix match. Same as \"::0/0 le 128\"\n"
1525 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1526 "Maximum prefix length to be matched\n"
1527 "Maximum prefix length\n"
1528 "Minimum prefix length to be matched\n"
1529 "Minimum prefix length\n")
1531 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, seq_str
,
1532 action
, dest
, ge_str
, le_str
);
1535 DEFPY (no_ipv6_prefix_list_all
,
1536 no_ipv6_prefix_list_all_cmd
,
1537 "no ipv6 prefix-list WORD",
1541 "Name of a prefix list\n")
1543 return vty_prefix_list_uninstall(vty
, AFI_IP6
, prefix_list
, NULL
, NULL
,
1547 DEFPY (ipv6_prefix_list_sequence_number
,
1548 ipv6_prefix_list_sequence_number_cmd
,
1549 "[no] ipv6 prefix-list sequence-number",
1553 "Include/exclude sequence numbers in NVGEN\n")
1555 prefix_master_ipv6
.seqnum
= no
? 0 : 1;
1559 DEFUN (ipv6_prefix_list_description
,
1560 ipv6_prefix_list_description_cmd
,
1561 "ipv6 prefix-list WORD description LINE...",
1564 "Name of a prefix list\n"
1565 "Prefix-list specific description\n"
1566 "Up to 80 characters describing this prefix-list\n")
1570 struct prefix_list
*plist
;
1572 plist
= prefix_list_get(AFI_IP6
, 0, argv
[idx_word
]->arg
);
1575 XFREE(MTYPE_TMP
, plist
->desc
);
1578 plist
->desc
= argv_concat(argv
, argc
, iddx_line
);
1583 DEFUN (no_ipv6_prefix_list_description
,
1584 no_ipv6_prefix_list_description_cmd
,
1585 "no ipv6 prefix-list WORD description",
1589 "Name of a prefix list\n"
1590 "Prefix-list specific description\n")
1593 return vty_prefix_list_desc_unset(vty
, AFI_IP6
, argv
[idx_word
]->arg
);
1597 DEFUN (no_ipv6_prefix_list_description_comment
,
1598 no_ipv6_prefix_list_description_comment_cmd
,
1599 "no ipv6 prefix-list WORD description LINE...",
1603 "Name of a prefix list\n"
1604 "Prefix-list specific description\n"
1605 "Up to 80 characters describing this prefix-list\n")
1607 return no_ipv6_prefix_list_description(self
, vty
, argc
, argv
);
1611 DEFPY (show_ipv6_prefix_list
,
1612 show_ipv6_prefix_list_cmd
,
1613 "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1617 "Name of a prefix list\n"
1618 "sequence number of an entry\n"
1619 "Sequence number\n")
1621 enum display_type dtype
= normal_display
;
1623 dtype
= sequential_display
;
1625 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, arg_str
, dtype
);
1628 DEFPY (show_ipv6_prefix_list_prefix
,
1629 show_ipv6_prefix_list_prefix_cmd
,
1630 "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
1634 "Name of a prefix list\n"
1635 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
1636 "Lookup longer prefix\n"
1637 "First matched prefix\n")
1639 enum display_type dtype
= normal_display
;
1641 dtype
= longer_display
;
1643 dtype
= first_match_display
;
1645 return vty_show_prefix_list_prefix(vty
, AFI_IP6
, prefix_list
,
1649 DEFPY (show_ipv6_prefix_list_summary
,
1650 show_ipv6_prefix_list_summary_cmd
,
1651 "show ipv6 prefix-list summary [WORD$prefix-list]",
1655 "Summary of prefix lists\n"
1656 "Name of a prefix list\n")
1658 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1662 DEFPY (show_ipv6_prefix_list_detail
,
1663 show_ipv6_prefix_list_detail_cmd
,
1664 "show ipv6 prefix-list detail [WORD$prefix-list]",
1668 "Detail of prefix lists\n"
1669 "Name of a prefix list\n")
1671 return vty_show_prefix_list(vty
, AFI_IP6
, prefix_list
, NULL
,
1675 DEFPY (clear_ipv6_prefix_list
,
1676 clear_ipv6_prefix_list_cmd
,
1677 "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
1681 "Name of a prefix list\n"
1682 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
1684 return vty_clear_prefix_list(vty
, AFI_IP6
, prefix_list
, prefix_str
);
1687 /* Configuration write function. */
1688 static int config_write_prefix_afi(afi_t afi
, struct vty
*vty
)
1690 struct prefix_list
*plist
;
1691 struct prefix_list_entry
*pentry
;
1692 struct prefix_master
*master
;
1695 master
= prefix_master_get(afi
, 0);
1699 if (!master
->seqnum
) {
1700 vty_out(vty
, "no ip%s prefix-list sequence-number\n",
1701 afi
== AFI_IP
? "" : "v6");
1702 vty_out(vty
, "!\n");
1705 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
) {
1707 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1708 afi
== AFI_IP
? "" : "v6", plist
->name
,
1713 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1714 vty_out(vty
, "ip%s prefix-list %s ",
1715 afi
== AFI_IP
? "" : "v6", plist
->name
);
1718 vty_out(vty
, "seq %u ", pentry
->seq
);
1720 vty_out(vty
, "%s ", prefix_list_type_str(pentry
));
1723 vty_out(vty
, "any");
1725 struct prefix
*p
= &pentry
->prefix
;
1728 vty_out(vty
, "%s/%d",
1729 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1734 vty_out(vty
, " ge %d", pentry
->ge
);
1736 vty_out(vty
, " le %d", pentry
->le
);
1741 /* vty_out (vty, "!\n"); */
1744 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
) {
1746 vty_out(vty
, "ip%s prefix-list %s description %s\n",
1747 afi
== AFI_IP
? "" : "v6", plist
->name
,
1752 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1753 vty_out(vty
, "ip%s prefix-list %s ",
1754 afi
== AFI_IP
? "" : "v6", plist
->name
);
1757 vty_out(vty
, "seq %u ", pentry
->seq
);
1759 vty_out(vty
, "%s", prefix_list_type_str(pentry
));
1762 vty_out(vty
, " any");
1764 struct prefix
*p
= &pentry
->prefix
;
1767 vty_out(vty
, " %s/%d",
1768 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
1773 vty_out(vty
, " ge %d", pentry
->ge
);
1775 vty_out(vty
, " le %d", pentry
->le
);
1785 struct stream
*prefix_bgp_orf_entry(struct stream
*s
, struct prefix_list
*plist
,
1786 u_char init_flag
, u_char permit_flag
,
1789 struct prefix_list_entry
*pentry
;
1794 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1795 u_char flag
= init_flag
;
1796 struct prefix
*p
= &pentry
->prefix
;
1798 flag
|= (pentry
->type
== PREFIX_PERMIT
? permit_flag
1800 stream_putc(s
, flag
);
1801 stream_putl(s
, (u_int32_t
)pentry
->seq
);
1802 stream_putc(s
, (u_char
)pentry
->ge
);
1803 stream_putc(s
, (u_char
)pentry
->le
);
1804 stream_put_prefix(s
, p
);
1810 int prefix_bgp_orf_set(char *name
, afi_t afi
, struct orf_prefix
*orfp
,
1811 int permit
, int set
)
1813 struct prefix_list
*plist
;
1814 struct prefix_list_entry
*pentry
;
1816 /* ge and le value check */
1817 if (orfp
->ge
&& orfp
->ge
<= orfp
->p
.prefixlen
)
1818 return CMD_WARNING_CONFIG_FAILED
;
1819 if (orfp
->le
&& orfp
->le
<= orfp
->p
.prefixlen
)
1820 return CMD_WARNING_CONFIG_FAILED
;
1821 if (orfp
->le
&& orfp
->ge
> orfp
->le
)
1822 return CMD_WARNING_CONFIG_FAILED
;
1824 if (orfp
->ge
&& orfp
->le
== (afi
== AFI_IP
? 32 : 128))
1827 plist
= prefix_list_get(afi
, 1, name
);
1829 return CMD_WARNING_CONFIG_FAILED
;
1832 pentry
= prefix_list_entry_make(
1833 &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1834 orfp
->seq
, orfp
->le
, orfp
->ge
, 0);
1836 if (prefix_entry_dup_check(plist
, pentry
)) {
1837 prefix_list_entry_free(pentry
);
1838 return CMD_WARNING_CONFIG_FAILED
;
1841 prefix_list_entry_add(plist
, pentry
);
1843 pentry
= prefix_list_entry_lookup(
1844 plist
, &orfp
->p
, (permit
? PREFIX_PERMIT
: PREFIX_DENY
),
1845 orfp
->seq
, orfp
->le
, orfp
->ge
);
1848 return CMD_WARNING_CONFIG_FAILED
;
1850 prefix_list_entry_delete(plist
, pentry
, 1);
1856 void prefix_bgp_orf_remove_all(afi_t afi
, char *name
)
1858 struct prefix_list
*plist
;
1860 plist
= prefix_bgp_orf_lookup(afi
, name
);
1862 prefix_list_delete(plist
);
1865 /* return prefix count */
1866 int prefix_bgp_show_prefix_list(struct vty
*vty
, afi_t afi
, char *name
,
1869 struct prefix_list
*plist
;
1870 struct prefix_list_entry
*pentry
;
1871 json_object
*json
= NULL
;
1872 json_object
*json_prefix
= NULL
;
1873 json_object
*json_list
= NULL
;
1875 plist
= prefix_bgp_orf_lookup(afi
, name
);
1880 return plist
->count
;
1883 json
= json_object_new_object();
1884 json_prefix
= json_object_new_object();
1885 json_list
= json_object_new_object();
1887 json_object_int_add(json_prefix
, "prefixListCounter",
1889 json_object_string_add(json_prefix
, "prefixListName",
1892 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1893 struct prefix
*p
= &pentry
->prefix
;
1897 sprintf(buf_a
, "%s/%d",
1898 inet_ntop(p
->family
, &p
->u
.prefix
, buf_b
,
1902 json_object_int_add(json_list
, "seq", pentry
->seq
);
1903 json_object_string_add(json_list
, "seqPrefixListType",
1904 prefix_list_type_str(pentry
));
1907 json_object_int_add(json_list
, "ge",
1910 json_object_int_add(json_list
, "le",
1913 json_object_object_add(json_prefix
, buf_a
, json_list
);
1916 json_object_object_add(json
, "ipPrefixList",
1919 json_object_object_add(json
, "ipv6PrefixList",
1922 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1923 json
, JSON_C_TO_STRING_PRETTY
));
1924 json_object_free(json
);
1926 vty_out(vty
, "ip%s prefix-list %s: %d entries\n",
1927 afi
== AFI_IP
? "" : "v6", plist
->name
, plist
->count
);
1929 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
1930 struct prefix
*p
= &pentry
->prefix
;
1933 vty_out(vty
, " seq %u %s %s/%d", pentry
->seq
,
1934 prefix_list_type_str(pentry
),
1935 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
1939 vty_out(vty
, " ge %d", pentry
->ge
);
1941 vty_out(vty
, " le %d", pentry
->le
);
1946 return plist
->count
;
1949 static void prefix_list_reset_afi(afi_t afi
, int orf
)
1951 struct prefix_list
*plist
;
1952 struct prefix_list
*next
;
1953 struct prefix_master
*master
;
1955 master
= prefix_master_get(afi
, orf
);
1959 for (plist
= master
->num
.head
; plist
; plist
= next
) {
1961 prefix_list_delete(plist
);
1963 for (plist
= master
->str
.head
; plist
; plist
= next
) {
1965 prefix_list_delete(plist
);
1968 assert(master
->num
.head
== NULL
);
1969 assert(master
->num
.tail
== NULL
);
1971 assert(master
->str
.head
== NULL
);
1972 assert(master
->str
.tail
== NULL
);
1975 master
->recent
= NULL
;
1979 /* Prefix-list node. */
1980 static struct cmd_node prefix_node
= {PREFIX_NODE
,
1981 "", /* Prefix list has no interface. */
1984 static int config_write_prefix_ipv4(struct vty
*vty
)
1986 return config_write_prefix_afi(AFI_IP
, vty
);
1989 static void plist_autocomplete_afi(afi_t afi
, vector comps
,
1990 struct cmd_token
*token
)
1992 struct prefix_list
*plist
;
1993 struct prefix_master
*master
;
1995 master
= prefix_master_get(afi
, 0);
1999 for (plist
= master
->str
.head
; plist
; plist
= plist
->next
)
2000 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, plist
->name
));
2001 for (plist
= master
->num
.head
; plist
; plist
= plist
->next
)
2002 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, plist
->name
));
2005 static void plist_autocomplete(vector comps
, struct cmd_token
*token
)
2007 plist_autocomplete_afi(AFI_IP
, comps
, token
);
2008 plist_autocomplete_afi(AFI_IP6
, comps
, token
);
2011 static const struct cmd_variable_handler plist_var_handlers
[] = {
2012 {/* "prefix-list WORD" */
2013 .varname
= "prefix_list",
2014 .completions
= plist_autocomplete
},
2015 {.completions
= NULL
}};
2018 static void prefix_list_init_ipv4(void)
2020 install_node(&prefix_node
, config_write_prefix_ipv4
);
2022 install_element(CONFIG_NODE
, &ip_prefix_list_cmd
);
2023 install_element(CONFIG_NODE
, &no_ip_prefix_list_cmd
);
2024 install_element(CONFIG_NODE
, &no_ip_prefix_list_all_cmd
);
2026 install_element(CONFIG_NODE
, &ip_prefix_list_description_cmd
);
2027 install_element(CONFIG_NODE
, &no_ip_prefix_list_description_cmd
);
2028 install_element(CONFIG_NODE
,
2029 &no_ip_prefix_list_description_comment_cmd
);
2031 install_element(CONFIG_NODE
, &ip_prefix_list_sequence_number_cmd
);
2033 install_element(VIEW_NODE
, &show_ip_prefix_list_cmd
);
2034 install_element(VIEW_NODE
, &show_ip_prefix_list_prefix_cmd
);
2035 install_element(VIEW_NODE
, &show_ip_prefix_list_summary_cmd
);
2036 install_element(VIEW_NODE
, &show_ip_prefix_list_detail_cmd
);
2038 install_element(ENABLE_NODE
, &clear_ip_prefix_list_cmd
);
2041 /* Prefix-list node. */
2042 static struct cmd_node prefix_ipv6_node
= {
2043 PREFIX_IPV6_NODE
, "", /* Prefix list has no interface. */
2046 static int config_write_prefix_ipv6(struct vty
*vty
)
2048 return config_write_prefix_afi(AFI_IP6
, vty
);
2051 static void prefix_list_init_ipv6(void)
2053 install_node(&prefix_ipv6_node
, config_write_prefix_ipv6
);
2055 install_element(CONFIG_NODE
, &ipv6_prefix_list_cmd
);
2056 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_cmd
);
2057 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_all_cmd
);
2059 install_element(CONFIG_NODE
, &ipv6_prefix_list_description_cmd
);
2060 install_element(CONFIG_NODE
, &no_ipv6_prefix_list_description_cmd
);
2061 install_element(CONFIG_NODE
,
2062 &no_ipv6_prefix_list_description_comment_cmd
);
2064 install_element(CONFIG_NODE
, &ipv6_prefix_list_sequence_number_cmd
);
2066 install_element(VIEW_NODE
, &show_ipv6_prefix_list_cmd
);
2067 install_element(VIEW_NODE
, &show_ipv6_prefix_list_prefix_cmd
);
2068 install_element(VIEW_NODE
, &show_ipv6_prefix_list_summary_cmd
);
2069 install_element(VIEW_NODE
, &show_ipv6_prefix_list_detail_cmd
);
2071 install_element(ENABLE_NODE
, &clear_ipv6_prefix_list_cmd
);
2074 void prefix_list_init()
2076 cmd_variable_handler_register(plist_var_handlers
);
2078 prefix_list_init_ipv4();
2079 prefix_list_init_ipv6();
2082 void prefix_list_reset()
2084 prefix_list_reset_afi(AFI_IP
, 0);
2085 prefix_list_reset_afi(AFI_IP6
, 0);
2086 prefix_list_reset_afi(AFI_IP
, 1);
2087 prefix_list_reset_afi(AFI_IP6
, 1);