1 /* BGP community-list and extcommunity-list.
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 it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_community.h"
31 #include "bgpd/bgp_ecommunity.h"
32 #include "bgpd/bgp_lcommunity.h"
33 #include "bgpd/bgp_aspath.h"
34 #include "bgpd/bgp_regex.h"
35 #include "bgpd/bgp_clist.h"
37 /* Lookup master structure for community-list or
39 struct community_list_master
*
40 community_list_master_lookup (struct community_list_handler
*ch
, int master
)
45 case COMMUNITY_LIST_MASTER
:
46 return &ch
->community_list
;
47 case EXTCOMMUNITY_LIST_MASTER
:
48 return &ch
->extcommunity_list
;
49 case LARGE_COMMUNITY_LIST_MASTER
:
50 return &ch
->lcommunity_list
;
55 /* Allocate a new community list entry. */
56 static struct community_entry
*
57 community_entry_new (void)
59 return XCALLOC (MTYPE_COMMUNITY_LIST_ENTRY
, sizeof (struct community_entry
));
62 /* Free community list entry. */
64 community_entry_free (struct community_entry
*entry
)
68 case COMMUNITY_LIST_STANDARD
:
70 community_free (entry
->u
.com
);
72 case LARGE_COMMUNITY_LIST_STANDARD
:
74 lcommunity_free (&entry
->u
.lcom
);
76 case EXTCOMMUNITY_LIST_STANDARD
:
77 /* In case of standard extcommunity-list, configuration string
78 is made by ecommunity_ecom2str(). */
80 XFREE (MTYPE_ECOMMUNITY_STR
, entry
->config
);
82 ecommunity_free (&entry
->u
.ecom
);
84 case COMMUNITY_LIST_EXPANDED
:
85 case EXTCOMMUNITY_LIST_EXPANDED
:
86 case LARGE_COMMUNITY_LIST_EXPANDED
:
88 XFREE (MTYPE_COMMUNITY_LIST_CONFIG
, entry
->config
);
90 bgp_regex_free (entry
->reg
);
94 XFREE (MTYPE_COMMUNITY_LIST_ENTRY
, entry
);
97 /* Allocate a new community-list. */
98 static struct community_list
*
99 community_list_new (void)
101 return XCALLOC (MTYPE_COMMUNITY_LIST
, sizeof (struct community_list
));
104 /* Free community-list. */
106 community_list_free (struct community_list
*list
)
109 XFREE (MTYPE_COMMUNITY_LIST_NAME
, list
->name
);
110 XFREE (MTYPE_COMMUNITY_LIST
, list
);
113 static struct community_list
*
114 community_list_insert (struct community_list_handler
*ch
,
115 const char *name
, int master
)
119 struct community_list
*new;
120 struct community_list
*point
;
121 struct community_list_list
*list
;
122 struct community_list_master
*cm
;
124 /* Lookup community-list master. */
125 cm
= community_list_master_lookup (ch
, master
);
129 /* Allocate new community_list and copy given name. */
130 new = community_list_new ();
131 new->name
= XSTRDUP (MTYPE_COMMUNITY_LIST_NAME
, name
);
133 /* If name is made by all digit character. We treat it as
135 for (number
= 0, i
= 0; i
< strlen (name
); i
++)
137 if (isdigit ((int) name
[i
]))
138 number
= (number
* 10) + (name
[i
] - '0');
143 /* In case of name is all digit character */
144 if (i
== strlen (name
))
146 new->sort
= COMMUNITY_LIST_NUMBER
;
148 /* Set access_list to number list. */
151 for (point
= list
->head
; point
; point
= point
->next
)
152 if (atol (point
->name
) >= number
)
157 new->sort
= COMMUNITY_LIST_STRING
;
159 /* Set access_list to string list. */
162 /* Set point to insertion point. */
163 for (point
= list
->head
; point
; point
= point
->next
)
164 if (strcmp (point
->name
, name
) >= 0)
168 /* Link to upper list. */
171 /* In case of this is the first element of master. */
172 if (list
->head
== NULL
)
174 list
->head
= list
->tail
= new;
178 /* In case of insertion is made at the tail of access_list. */
181 new->prev
= list
->tail
;
182 list
->tail
->next
= new;
187 /* In case of insertion is made at the head of access_list. */
188 if (point
== list
->head
)
190 new->next
= list
->head
;
191 list
->head
->prev
= new;
196 /* Insertion is made at middle of the access_list. */
198 new->prev
= point
->prev
;
201 point
->prev
->next
= new;
207 struct community_list
*
208 community_list_lookup (struct community_list_handler
*ch
,
209 const char *name
, int master
)
211 struct community_list
*list
;
212 struct community_list_master
*cm
;
217 cm
= community_list_master_lookup (ch
, master
);
221 for (list
= cm
->num
.head
; list
; list
= list
->next
)
222 if (strcmp (list
->name
, name
) == 0)
224 for (list
= cm
->str
.head
; list
; list
= list
->next
)
225 if (strcmp (list
->name
, name
) == 0)
231 static struct community_list
*
232 community_list_get (struct community_list_handler
*ch
,
233 const char *name
, int master
)
235 struct community_list
*list
;
237 list
= community_list_lookup (ch
, name
, master
);
239 list
= community_list_insert (ch
, name
, master
);
244 community_list_delete (struct community_list
*list
)
246 struct community_list_list
*clist
;
247 struct community_entry
*entry
, *next
;
249 for (entry
= list
->head
; entry
; entry
= next
)
252 community_entry_free (entry
);
255 clist
= list
->parent
;
258 list
->next
->prev
= list
->prev
;
260 clist
->tail
= list
->prev
;
263 list
->prev
->next
= list
->next
;
265 clist
->head
= list
->next
;
267 community_list_free (list
);
271 community_list_empty_p (struct community_list
*list
)
273 return (list
->head
== NULL
&& list
->tail
== NULL
) ? 1 : 0;
276 /* Add community-list entry to the list. */
278 community_list_entry_add (struct community_list
*list
,
279 struct community_entry
*entry
)
282 entry
->prev
= list
->tail
;
285 list
->tail
->next
= entry
;
291 /* Delete community-list entry from the list. */
293 community_list_entry_delete (struct community_list
*list
,
294 struct community_entry
*entry
, int style
)
297 entry
->next
->prev
= entry
->prev
;
299 list
->tail
= entry
->prev
;
302 entry
->prev
->next
= entry
->next
;
304 list
->head
= entry
->next
;
306 community_entry_free (entry
);
308 if (community_list_empty_p (list
))
309 community_list_delete (list
);
312 /* Lookup community-list entry from the list. */
313 static struct community_entry
*
314 community_list_entry_lookup (struct community_list
*list
, const void *arg
,
317 struct community_entry
*entry
;
319 for (entry
= list
->head
; entry
; entry
= entry
->next
)
321 switch (entry
->style
)
323 case COMMUNITY_LIST_STANDARD
:
324 if (entry
->direct
== direct
&& community_cmp (entry
->u
.com
, arg
))
327 case EXTCOMMUNITY_LIST_STANDARD
:
328 if (entry
->direct
== direct
&& ecommunity_cmp (entry
->u
.ecom
, arg
))
331 case LARGE_COMMUNITY_LIST_STANDARD
:
332 if (entry
->direct
== direct
&& lcommunity_cmp (entry
->u
.lcom
, arg
))
335 case COMMUNITY_LIST_EXPANDED
:
336 case EXTCOMMUNITY_LIST_EXPANDED
:
337 case LARGE_COMMUNITY_LIST_EXPANDED
:
338 if (entry
->direct
== direct
&& strcmp (entry
->config
, arg
) == 0)
349 community_str_get (struct community
*com
, int i
)
358 memcpy (&comval
, com_nthval (com
, i
), sizeof (u_int32_t
));
359 comval
= ntohl (comval
);
363 case COMMUNITY_INTERNET
:
364 len
= strlen (" internet");
366 case COMMUNITY_NO_EXPORT
:
367 len
= strlen (" no-export");
369 case COMMUNITY_NO_ADVERTISE
:
370 len
= strlen (" no-advertise");
372 case COMMUNITY_LOCAL_AS
:
373 len
= strlen (" local-AS");
376 len
= strlen (" 65536:65535");
380 /* Allocate memory. */
381 str
= pnt
= XMALLOC (MTYPE_COMMUNITY_STR
, len
);
385 case COMMUNITY_INTERNET
:
386 strcpy (pnt
, "internet");
387 pnt
+= strlen ("internet");
389 case COMMUNITY_NO_EXPORT
:
390 strcpy (pnt
, "no-export");
391 pnt
+= strlen ("no-export");
393 case COMMUNITY_NO_ADVERTISE
:
394 strcpy (pnt
, "no-advertise");
395 pnt
+= strlen ("no-advertise");
397 case COMMUNITY_LOCAL_AS
:
398 strcpy (pnt
, "local-AS");
399 pnt
+= strlen ("local-AS");
402 as
= (comval
>> 16) & 0xFFFF;
403 val
= comval
& 0xFFFF;
404 sprintf (pnt
, "%u:%d", as
, val
);
414 /* Internal function to perform regular expression match for
415 * a single community. */
417 community_regexp_include (regex_t
* reg
, struct community
*com
, int i
)
422 /* When there is no communities attribute it is treated as empty string. */
423 if (com
== NULL
|| com
->size
== 0)
424 str
= XSTRDUP(MTYPE_COMMUNITY_STR
, "");
426 str
= community_str_get (com
, i
);
428 /* Regular expression match. */
429 rv
= regexec (reg
, str
, 0, NULL
, 0);
431 XFREE(MTYPE_COMMUNITY_STR
, str
);
440 /* Internal function to perform regular expression match for community
443 community_regexp_match (struct community
*com
, regex_t
* reg
)
447 /* When there is no communities attribute it is treated as empty
449 if (com
== NULL
|| com
->size
== 0)
452 str
= community_str (com
);
454 /* Regular expression match. */
455 if (regexec (reg
, str
, 0, NULL
, 0) == 0)
463 lcommunity_str_get (struct lcommunity
*lcom
, int i
)
465 struct lcommunity_val lcomval
;
466 u_int32_t globaladmin
;
467 u_int32_t localdata1
;
468 u_int32_t localdata2
;
474 ptr
+= (i
* LCOMMUNITY_SIZE
);
476 memcpy (&lcomval
, ptr
, LCOMMUNITY_SIZE
);
478 /* Allocate memory. 48 bytes taken off bgp_lcommunity.c */
479 str
= pnt
= XMALLOC (MTYPE_LCOMMUNITY_STR
, 48);
481 ptr
= (u_char
*)lcomval
.val
;
482 globaladmin
= (*ptr
++ << 24);
483 globaladmin
|= (*ptr
++ << 16);
484 globaladmin
|= (*ptr
++ << 8);
485 globaladmin
|= (*ptr
++);
487 localdata1
= (*ptr
++ << 24);
488 localdata1
|= (*ptr
++ << 16);
489 localdata1
|= (*ptr
++ << 8);
490 localdata1
|= (*ptr
++);
492 localdata2
= (*ptr
++ << 24);
493 localdata2
|= (*ptr
++ << 16);
494 localdata2
|= (*ptr
++ << 8);
495 localdata2
|= (*ptr
++);
497 sprintf (pnt
, "%u:%u:%u", globaladmin
, localdata1
, localdata2
);
504 /* Internal function to perform regular expression match for
505 * a single community. */
507 lcommunity_regexp_include (regex_t
* reg
, struct lcommunity
*lcom
, int i
)
511 /* When there is no communities attribute it is treated as empty string. */
512 if (lcom
== NULL
|| lcom
->size
== 0)
513 str
= XSTRDUP (MTYPE_LCOMMUNITY_STR
, "");
515 str
= lcommunity_str_get (lcom
, i
);
517 /* Regular expression match. */
518 if (regexec (reg
, str
, 0, NULL
, 0) == 0)
520 XFREE (MTYPE_LCOMMUNITY_STR
, str
);
524 XFREE (MTYPE_LCOMMUNITY_STR
, str
);
530 lcommunity_regexp_match (struct lcommunity
*com
, regex_t
* reg
)
534 /* When there is no communities attribute it is treated as empty
536 if (com
== NULL
|| com
->size
== 0)
539 str
= lcommunity_str (com
);
541 /* Regular expression match. */
542 if (regexec (reg
, str
, 0, NULL
, 0) == 0)
551 ecommunity_regexp_match (struct ecommunity
*ecom
, regex_t
* reg
)
555 /* When there is no communities attribute it is treated as empty
557 if (ecom
== NULL
|| ecom
->size
== 0)
560 str
= ecommunity_str (ecom
);
562 /* Regular expression match. */
563 if (regexec (reg
, str
, 0, NULL
, 0) == 0)
571 /* Delete community attribute using regular expression match. Return
572 modified communites attribute. */
573 static struct community
*
574 community_regexp_delete (struct community
*com
, regex_t
* reg
)
578 /* Maximum is "65535:65535" + '\0'. */
586 while (i
< com
->size
)
588 memcpy (&comval
, com_nthval (com
, i
), sizeof (u_int32_t
));
589 comval
= ntohl (comval
);
593 case COMMUNITY_INTERNET
:
596 case COMMUNITY_NO_EXPORT
:
599 case COMMUNITY_NO_ADVERTISE
:
600 str
= "no-advertise";
602 case COMMUNITY_LOCAL_AS
:
606 sprintf (c
, "%d:%d", (comval
>> 16) & 0xFFFF, comval
& 0xFFFF);
611 if (regexec (reg
, str
, 0, NULL
, 0) == 0)
612 community_del_val (com
, com_nthval (com
, i
));
620 /* When given community attribute matches to the community-list return
623 community_list_match (struct community
*com
, struct community_list
*list
)
625 struct community_entry
*entry
;
627 for (entry
= list
->head
; entry
; entry
= entry
->next
)
630 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
632 if (entry
->style
== COMMUNITY_LIST_STANDARD
)
634 if (community_include (entry
->u
.com
, COMMUNITY_INTERNET
))
635 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
637 if (community_match (com
, entry
->u
.com
))
638 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
640 else if (entry
->style
== COMMUNITY_LIST_EXPANDED
)
642 if (community_regexp_match (com
, entry
->reg
))
643 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
650 lcommunity_list_match (struct lcommunity
*lcom
, struct community_list
*list
)
652 struct community_entry
*entry
;
654 for (entry
= list
->head
; entry
; entry
= entry
->next
)
657 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
659 if (entry
->style
== LARGE_COMMUNITY_LIST_STANDARD
)
661 if (lcommunity_match (lcom
, entry
->u
.lcom
))
662 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
664 else if (entry
->style
== LARGE_COMMUNITY_LIST_EXPANDED
)
666 if (lcommunity_regexp_match (lcom
, entry
->reg
))
667 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
674 ecommunity_list_match (struct ecommunity
*ecom
, struct community_list
*list
)
676 struct community_entry
*entry
;
678 for (entry
= list
->head
; entry
; entry
= entry
->next
)
681 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
683 if (entry
->style
== EXTCOMMUNITY_LIST_STANDARD
)
685 if (ecommunity_match (ecom
, entry
->u
.ecom
))
686 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
688 else if (entry
->style
== EXTCOMMUNITY_LIST_EXPANDED
)
690 if (ecommunity_regexp_match (ecom
, entry
->reg
))
691 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
697 /* Perform exact matching. In case of expanded community-list, do
698 same thing as community_list_match(). */
700 community_list_exact_match (struct community
*com
,
701 struct community_list
*list
)
703 struct community_entry
*entry
;
705 for (entry
= list
->head
; entry
; entry
= entry
->next
)
708 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
710 if (entry
->style
== COMMUNITY_LIST_STANDARD
)
712 if (community_include (entry
->u
.com
, COMMUNITY_INTERNET
))
713 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
715 if (community_cmp (com
, entry
->u
.com
))
716 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
718 else if (entry
->style
== COMMUNITY_LIST_EXPANDED
)
720 if (community_regexp_match (com
, entry
->reg
))
721 return entry
->direct
== COMMUNITY_PERMIT
? 1 : 0;
727 /* Delete all permitted communities in the list from com. */
729 community_list_match_delete (struct community
*com
,
730 struct community_list
*list
)
732 struct community_entry
*entry
;
734 u_int32_t com_index_to_delete
[com
->size
];
735 int delete_index
= 0;
738 /* Loop over each community value and evaluate each against the
739 * community-list. If we need to delete a community value add its index to
740 * com_index_to_delete.
742 for (i
= 0; i
< com
->size
; i
++)
744 val
= community_val_get (com
, i
);
746 for (entry
= list
->head
; entry
; entry
= entry
->next
)
750 if (entry
->direct
== COMMUNITY_PERMIT
)
752 com_index_to_delete
[delete_index
] = i
;
758 else if ((entry
->style
== COMMUNITY_LIST_STANDARD
)
759 && (community_include (entry
->u
.com
, COMMUNITY_INTERNET
)
760 || community_include (entry
->u
.com
, val
) ))
762 if (entry
->direct
== COMMUNITY_PERMIT
)
764 com_index_to_delete
[delete_index
] = i
;
770 else if ((entry
->style
== COMMUNITY_LIST_EXPANDED
)
771 && community_regexp_include (entry
->reg
, com
, i
))
773 if (entry
->direct
== COMMUNITY_PERMIT
)
775 com_index_to_delete
[delete_index
] = i
;
783 /* Delete all of the communities we flagged for deletion */
784 for (i
= delete_index
-1; i
>= 0; i
--)
786 val
= community_val_get (com
, com_index_to_delete
[i
]);
787 community_del_val (com
, &val
);
793 /* To avoid duplicated entry in the community-list, this function
794 compares specified entry to existing entry. */
796 community_list_dup_check (struct community_list
*list
,
797 struct community_entry
*new)
799 struct community_entry
*entry
;
801 for (entry
= list
->head
; entry
; entry
= entry
->next
)
803 if (entry
->style
!= new->style
)
806 if (entry
->direct
!= new->direct
)
809 if (entry
->any
!= new->any
)
815 switch (entry
->style
)
817 case COMMUNITY_LIST_STANDARD
:
818 if (community_cmp (entry
->u
.com
, new->u
.com
))
821 case LARGE_COMMUNITY_LIST_STANDARD
:
822 if (lcommunity_cmp (entry
->u
.lcom
, new->u
.lcom
))
825 case EXTCOMMUNITY_LIST_STANDARD
:
826 if (ecommunity_cmp (entry
->u
.ecom
, new->u
.ecom
))
829 case COMMUNITY_LIST_EXPANDED
:
830 case EXTCOMMUNITY_LIST_EXPANDED
:
831 case LARGE_COMMUNITY_LIST_EXPANDED
:
832 if (strcmp (entry
->config
, new->config
) == 0)
842 /* Set community-list. */
844 community_list_set (struct community_list_handler
*ch
,
845 const char *name
, const char *str
, int direct
, int style
)
847 struct community_entry
*entry
= NULL
;
848 struct community_list
*list
;
849 struct community
*com
= NULL
;
850 regex_t
*regex
= NULL
;
852 /* Get community list. */
853 list
= community_list_get (ch
, name
, COMMUNITY_LIST_MASTER
);
855 /* When community-list already has entry, new entry should have same
856 style. If you want to have mixed style community-list, you can
857 comment out this check. */
858 if (!community_list_empty_p (list
))
860 struct community_entry
*first
;
864 if (style
!= first
->style
)
866 return (first
->style
== COMMUNITY_LIST_STANDARD
867 ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
868 : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT
);
874 if (style
== COMMUNITY_LIST_STANDARD
)
875 com
= community_str2com (str
);
877 regex
= bgp_regcomp (str
);
879 if (! com
&& ! regex
)
880 return COMMUNITY_LIST_ERR_MALFORMED_VAL
;
883 entry
= community_entry_new ();
884 entry
->direct
= direct
;
885 entry
->style
= style
;
886 entry
->any
= (str
? 0 : 1);
889 entry
->config
= (regex
? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG
, str
) : NULL
);
891 /* Do not put duplicated community entry. */
892 if (community_list_dup_check (list
, entry
))
893 community_entry_free (entry
);
896 community_list_entry_add (list
, entry
);
897 route_map_notify_dependencies(name
, RMAP_EVENT_CLIST_ADDED
);
903 /* Unset community-list */
905 community_list_unset (struct community_list_handler
*ch
,
906 const char *name
, const char *str
,
907 int direct
, int style
, int delete_all
)
909 struct community_entry
*entry
= NULL
;
910 struct community_list
*list
;
911 struct community
*com
= NULL
;
913 /* Lookup community list. */
914 list
= community_list_lookup (ch
, name
, COMMUNITY_LIST_MASTER
);
916 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
918 /* Delete all of entry belongs to this community-list. */
921 community_list_delete (list
);
922 route_map_notify_dependencies(name
, RMAP_EVENT_CLIST_DELETED
);
926 if (style
== COMMUNITY_LIST_STANDARD
)
929 com
= community_str2com (str
);
934 entry
= community_list_entry_lookup (list
, com
, direct
);
935 community_free (com
);
938 entry
= community_list_entry_lookup (list
, str
, direct
);
941 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
943 community_list_entry_delete (list
, entry
, style
);
944 route_map_notify_dependencies(name
, RMAP_EVENT_CLIST_DELETED
);
949 /* Delete all permitted large communities in the list from com. */
951 lcommunity_list_match_delete (struct lcommunity
*lcom
,
952 struct community_list
*list
)
954 struct community_entry
*entry
;
955 u_int32_t com_index_to_delete
[lcom
->size
];
957 int delete_index
= 0;
960 /* Loop over each lcommunity value and evaluate each against the
961 * community-list. If we need to delete a community value add its index to
962 * com_index_to_delete.
965 for (i
= 0; i
< lcom
->size
; i
++)
967 ptr
+= (i
* LCOMMUNITY_SIZE
);
968 for (entry
= list
->head
; entry
; entry
= entry
->next
)
972 if (entry
->direct
== COMMUNITY_PERMIT
)
974 com_index_to_delete
[delete_index
] = i
;
980 else if ((entry
->style
== LARGE_COMMUNITY_LIST_STANDARD
)
981 && lcommunity_include (entry
->u
.lcom
, ptr
) )
983 if (entry
->direct
== COMMUNITY_PERMIT
)
985 com_index_to_delete
[delete_index
] = i
;
991 else if ((entry
->style
== LARGE_COMMUNITY_LIST_STANDARD
)
992 && lcommunity_regexp_include (entry
->reg
, lcom
, i
))
994 if (entry
->direct
== COMMUNITY_PERMIT
)
996 com_index_to_delete
[delete_index
] = i
;
1004 /* Delete all of the communities we flagged for deletion */
1006 for (i
= delete_index
-1; i
>= 0; i
--)
1008 ptr
+= (com_index_to_delete
[i
] * LCOMMUNITY_SIZE
);
1009 lcommunity_del_val (lcom
, ptr
);
1015 /* Set lcommunity-list. */
1017 lcommunity_list_set (struct community_list_handler
*ch
,
1018 const char *name
, const char *str
, int direct
, int style
)
1020 struct community_entry
*entry
= NULL
;
1021 struct community_list
*list
;
1022 struct lcommunity
*lcom
= NULL
;
1023 regex_t
*regex
= NULL
;
1025 /* Get community list. */
1026 list
= community_list_get (ch
, name
, LARGE_COMMUNITY_LIST_MASTER
);
1028 /* When community-list already has entry, new entry should have same
1029 style. If you want to have mixed style community-list, you can
1030 comment out this check. */
1031 if (!community_list_empty_p (list
))
1033 struct community_entry
*first
;
1037 if (style
!= first
->style
)
1039 return (first
->style
== COMMUNITY_LIST_STANDARD
1040 ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
1041 : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT
);
1047 if (style
== LARGE_COMMUNITY_LIST_STANDARD
)
1048 lcom
= lcommunity_str2com (str
);
1050 regex
= bgp_regcomp (str
);
1052 if (! lcom
&& ! regex
)
1053 return COMMUNITY_LIST_ERR_MALFORMED_VAL
;
1056 entry
= community_entry_new ();
1057 entry
->direct
= direct
;
1058 entry
->style
= style
;
1059 entry
->any
= (str
? 0 : 1);
1060 entry
->u
.lcom
= lcom
;
1063 entry
->config
= lcommunity_lcom2str (lcom
, LCOMMUNITY_FORMAT_COMMUNITY_LIST
);
1065 entry
->config
= XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG
, str
);
1067 entry
->config
= NULL
;
1069 /* Do not put duplicated community entry. */
1070 if (community_list_dup_check (list
, entry
))
1071 community_entry_free (entry
);
1073 community_list_entry_add (list
, entry
);
1078 /* Unset community-list. When str is NULL, delete all of
1079 community-list entry belongs to the specified name. */
1081 lcommunity_list_unset (struct community_list_handler
*ch
,
1082 const char *name
, const char *str
,
1083 int direct
, int style
)
1085 struct community_entry
*entry
= NULL
;
1086 struct community_list
*list
;
1087 struct lcommunity
*lcom
= NULL
;
1088 regex_t
*regex
= NULL
;
1090 /* Lookup community list. */
1091 list
= community_list_lookup (ch
, name
, LARGE_COMMUNITY_LIST_MASTER
);
1093 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
1095 /* Delete all of entry belongs to this community-list. */
1098 community_list_delete (list
);
1102 if (style
== LARGE_COMMUNITY_LIST_STANDARD
)
1103 lcom
= lcommunity_str2com (str
);
1105 regex
= bgp_regcomp (str
);
1107 if (! lcom
&& ! regex
)
1108 return COMMUNITY_LIST_ERR_MALFORMED_VAL
;
1111 entry
= community_list_entry_lookup (list
, lcom
, direct
);
1113 entry
= community_list_entry_lookup (list
, str
, direct
);
1116 lcommunity_free (&lcom
);
1118 bgp_regex_free (regex
);
1121 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
1123 community_list_entry_delete (list
, entry
, style
);
1128 /* Set extcommunity-list. */
1130 extcommunity_list_set (struct community_list_handler
*ch
,
1131 const char *name
, const char *str
,
1132 int direct
, int style
)
1134 struct community_entry
*entry
= NULL
;
1135 struct community_list
*list
;
1136 struct ecommunity
*ecom
= NULL
;
1137 regex_t
*regex
= NULL
;
1141 /* Get community list. */
1142 list
= community_list_get (ch
, name
, EXTCOMMUNITY_LIST_MASTER
);
1144 /* When community-list already has entry, new entry should have same
1145 style. If you want to have mixed style community-list, you can
1146 comment out this check. */
1147 if (!community_list_empty_p (list
))
1149 struct community_entry
*first
;
1153 if (style
!= first
->style
)
1155 return (first
->style
== EXTCOMMUNITY_LIST_STANDARD
1156 ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
1157 : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT
);
1163 if (style
== EXTCOMMUNITY_LIST_STANDARD
)
1164 ecom
= ecommunity_str2com (str
, 0, 1);
1166 regex
= bgp_regcomp (str
);
1168 if (! ecom
&& ! regex
)
1169 return COMMUNITY_LIST_ERR_MALFORMED_VAL
;
1173 ecom
->str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_DISPLAY
, 0);
1175 entry
= community_entry_new ();
1176 entry
->direct
= direct
;
1177 entry
->style
= style
;
1178 entry
->any
= (str
? 0 : 1);
1180 entry
->config
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_COMMUNITY_LIST
, 0);
1182 entry
->config
= XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG
, str
);
1184 entry
->config
= NULL
;
1185 entry
->u
.ecom
= ecom
;
1188 /* Do not put duplicated community entry. */
1189 if (community_list_dup_check (list
, entry
))
1190 community_entry_free (entry
);
1193 community_list_entry_add (list
, entry
);
1194 route_map_notify_dependencies(name
, RMAP_EVENT_ECLIST_ADDED
);
1200 /* Unset extcommunity-list. When str is NULL, delete all of
1201 extcommunity-list entry belongs to the specified name. */
1203 extcommunity_list_unset (struct community_list_handler
*ch
,
1204 const char *name
, const char *str
,
1205 int direct
, int style
, int delete_all
)
1207 struct community_entry
*entry
= NULL
;
1208 struct community_list
*list
;
1209 struct ecommunity
*ecom
= NULL
;
1211 /* Lookup extcommunity list. */
1212 list
= community_list_lookup (ch
, name
, EXTCOMMUNITY_LIST_MASTER
);
1214 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
1216 /* Delete all of entry belongs to this extcommunity-list. */
1219 community_list_delete (list
);
1220 route_map_notify_dependencies(name
, RMAP_EVENT_ECLIST_DELETED
);
1224 if (style
== EXTCOMMUNITY_LIST_STANDARD
)
1227 ecom
= ecommunity_str2com (str
, 0, 1);
1232 entry
= community_list_entry_lookup (list
, ecom
, direct
);
1233 ecommunity_free (&ecom
);
1236 entry
= community_list_entry_lookup (list
, str
, direct
);
1239 return COMMUNITY_LIST_ERR_CANT_FIND_LIST
;
1241 community_list_entry_delete (list
, entry
, style
);
1242 route_map_notify_dependencies(name
, RMAP_EVENT_ECLIST_DELETED
);
1247 /* Initializa community-list. Return community-list handler. */
1248 struct community_list_handler
*
1249 community_list_init (void)
1251 struct community_list_handler
*ch
;
1252 ch
= XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER
,
1253 sizeof (struct community_list_handler
));
1257 /* Terminate community-list. */
1259 community_list_terminate (struct community_list_handler
*ch
)
1261 struct community_list_master
*cm
;
1262 struct community_list
*list
;
1264 cm
= &ch
->community_list
;
1265 while ((list
= cm
->num
.head
) != NULL
)
1266 community_list_delete (list
);
1267 while ((list
= cm
->str
.head
) != NULL
)
1268 community_list_delete (list
);
1270 cm
= &ch
->lcommunity_list
;
1271 while ((list
= cm
->num
.head
) != NULL
)
1272 community_list_delete (list
);
1273 while ((list
= cm
->str
.head
) != NULL
)
1274 community_list_delete (list
);
1276 cm
= &ch
->extcommunity_list
;
1277 while ((list
= cm
->num
.head
) != NULL
)
1278 community_list_delete (list
);
1279 while ((list
= cm
->str
.head
) != NULL
)
1280 community_list_delete (list
);
1282 XFREE (MTYPE_COMMUNITY_LIST_HANDLER
, ch
);