Annotation of embedaddon/quagga/bgpd/bgp_clist.c, revision 1.1.1.2
1.1 misho 1: /* BGP community-list and extcommunity-list.
2: Copyright (C) 1999 Kunihiro Ishiguro
3:
4: This file is part of GNU Zebra.
5:
6: GNU Zebra is free software; you can redistribute it and/or modify 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
9: later version.
10:
11: GNU Zebra is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
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
19: 02111-1307, USA. */
20:
21: #include <zebra.h>
22:
23: #include "command.h"
24: #include "prefix.h"
25: #include "memory.h"
1.1.1.2 ! misho 26: #include "filter.h"
1.1 misho 27:
28: #include "bgpd/bgpd.h"
29: #include "bgpd/bgp_community.h"
30: #include "bgpd/bgp_ecommunity.h"
31: #include "bgpd/bgp_aspath.h"
32: #include "bgpd/bgp_regex.h"
33: #include "bgpd/bgp_clist.h"
1.1.1.2 ! misho 34:
1.1 misho 35: /* Lookup master structure for community-list or
36: extcommunity-list. */
37: struct community_list_master *
38: community_list_master_lookup (struct community_list_handler *ch, int master)
39: {
40: if (ch)
41: switch (master)
42: {
43: case COMMUNITY_LIST_MASTER:
44: return &ch->community_list;
45: case EXTCOMMUNITY_LIST_MASTER:
46: return &ch->extcommunity_list;
47: }
48: return NULL;
49: }
50:
51: /* Allocate a new community list entry. */
52: static struct community_entry *
53: community_entry_new (void)
54: {
55: return XCALLOC (MTYPE_COMMUNITY_LIST_ENTRY, sizeof (struct community_entry));
56: }
57:
58: /* Free community list entry. */
59: static void
60: community_entry_free (struct community_entry *entry)
61: {
62: switch (entry->style)
63: {
64: case COMMUNITY_LIST_STANDARD:
65: if (entry->u.com)
66: community_free (entry->u.com);
67: break;
68: case EXTCOMMUNITY_LIST_STANDARD:
69: /* In case of standard extcommunity-list, configuration string
70: is made by ecommunity_ecom2str(). */
71: if (entry->config)
72: XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
73: if (entry->u.ecom)
74: ecommunity_free (&entry->u.ecom);
75: break;
76: case COMMUNITY_LIST_EXPANDED:
77: case EXTCOMMUNITY_LIST_EXPANDED:
78: if (entry->config)
79: XFREE (MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
80: if (entry->reg)
81: bgp_regex_free (entry->reg);
82: default:
83: break;
84: }
85: XFREE (MTYPE_COMMUNITY_LIST_ENTRY, entry);
86: }
87:
88: /* Allocate a new community-list. */
89: static struct community_list *
90: community_list_new (void)
91: {
92: return XCALLOC (MTYPE_COMMUNITY_LIST, sizeof (struct community_list));
93: }
94:
95: /* Free community-list. */
96: static void
97: community_list_free (struct community_list *list)
98: {
99: if (list->name)
100: XFREE (MTYPE_COMMUNITY_LIST_NAME, list->name);
101: XFREE (MTYPE_COMMUNITY_LIST, list);
102: }
103:
104: static struct community_list *
105: community_list_insert (struct community_list_handler *ch,
106: const char *name, int master)
107: {
108: size_t i;
109: long number;
110: struct community_list *new;
111: struct community_list *point;
112: struct community_list_list *list;
113: struct community_list_master *cm;
114:
115: /* Lookup community-list master. */
116: cm = community_list_master_lookup (ch, master);
117: if (!cm)
118: return NULL;
119:
120: /* Allocate new community_list and copy given name. */
121: new = community_list_new ();
122: new->name = XSTRDUP (MTYPE_COMMUNITY_LIST_NAME, name);
123:
124: /* If name is made by all digit character. We treat it as
125: number. */
126: for (number = 0, i = 0; i < strlen (name); i++)
127: {
128: if (isdigit ((int) name[i]))
129: number = (number * 10) + (name[i] - '0');
130: else
131: break;
132: }
133:
134: /* In case of name is all digit character */
135: if (i == strlen (name))
136: {
137: new->sort = COMMUNITY_LIST_NUMBER;
138:
139: /* Set access_list to number list. */
140: list = &cm->num;
141:
142: for (point = list->head; point; point = point->next)
143: if (atol (point->name) >= number)
144: break;
145: }
146: else
147: {
148: new->sort = COMMUNITY_LIST_STRING;
149:
150: /* Set access_list to string list. */
151: list = &cm->str;
152:
153: /* Set point to insertion point. */
154: for (point = list->head; point; point = point->next)
155: if (strcmp (point->name, name) >= 0)
156: break;
157: }
158:
159: /* Link to upper list. */
160: new->parent = list;
161:
162: /* In case of this is the first element of master. */
163: if (list->head == NULL)
164: {
165: list->head = list->tail = new;
166: return new;
167: }
168:
169: /* In case of insertion is made at the tail of access_list. */
170: if (point == NULL)
171: {
172: new->prev = list->tail;
173: list->tail->next = new;
174: list->tail = new;
175: return new;
176: }
177:
178: /* In case of insertion is made at the head of access_list. */
179: if (point == list->head)
180: {
181: new->next = list->head;
182: list->head->prev = new;
183: list->head = new;
184: return new;
185: }
186:
187: /* Insertion is made at middle of the access_list. */
188: new->next = point;
189: new->prev = point->prev;
190:
191: if (point->prev)
192: point->prev->next = new;
193: point->prev = new;
194:
195: return new;
196: }
197:
198: struct community_list *
199: community_list_lookup (struct community_list_handler *ch,
200: const char *name, int master)
201: {
202: struct community_list *list;
203: struct community_list_master *cm;
204:
205: if (!name)
206: return NULL;
207:
208: cm = community_list_master_lookup (ch, master);
209: if (!cm)
210: return NULL;
211:
212: for (list = cm->num.head; list; list = list->next)
213: if (strcmp (list->name, name) == 0)
214: return list;
215: for (list = cm->str.head; list; list = list->next)
216: if (strcmp (list->name, name) == 0)
217: return list;
218:
219: return NULL;
220: }
221:
222: static struct community_list *
223: community_list_get (struct community_list_handler *ch,
224: const char *name, int master)
225: {
226: struct community_list *list;
227:
228: list = community_list_lookup (ch, name, master);
229: if (!list)
230: list = community_list_insert (ch, name, master);
231: return list;
232: }
233:
234: static void
235: community_list_delete (struct community_list *list)
236: {
237: struct community_list_list *clist;
238: struct community_entry *entry, *next;
239:
240: for (entry = list->head; entry; entry = next)
241: {
242: next = entry->next;
243: community_entry_free (entry);
244: }
245:
246: clist = list->parent;
247:
248: if (list->next)
249: list->next->prev = list->prev;
250: else
251: clist->tail = list->prev;
252:
253: if (list->prev)
254: list->prev->next = list->next;
255: else
256: clist->head = list->next;
257:
258: community_list_free (list);
259: }
260:
261: static int
262: community_list_empty_p (struct community_list *list)
263: {
264: return (list->head == NULL && list->tail == NULL) ? 1 : 0;
265: }
1.1.1.2 ! misho 266:
1.1 misho 267: /* Add community-list entry to the list. */
268: static void
269: community_list_entry_add (struct community_list *list,
270: struct community_entry *entry)
271: {
272: entry->next = NULL;
273: entry->prev = list->tail;
274:
275: if (list->tail)
276: list->tail->next = entry;
277: else
278: list->head = entry;
279: list->tail = entry;
280: }
281:
282: /* Delete community-list entry from the list. */
283: static void
284: community_list_entry_delete (struct community_list *list,
285: struct community_entry *entry, int style)
286: {
287: if (entry->next)
288: entry->next->prev = entry->prev;
289: else
290: list->tail = entry->prev;
291:
292: if (entry->prev)
293: entry->prev->next = entry->next;
294: else
295: list->head = entry->next;
296:
297: community_entry_free (entry);
298:
299: if (community_list_empty_p (list))
300: community_list_delete (list);
301: }
302:
303: /* Lookup community-list entry from the list. */
304: static struct community_entry *
305: community_list_entry_lookup (struct community_list *list, const void *arg,
306: int direct)
307: {
308: struct community_entry *entry;
309:
310: for (entry = list->head; entry; entry = entry->next)
311: {
312: switch (entry->style)
313: {
314: case COMMUNITY_LIST_STANDARD:
315: if (community_cmp (entry->u.com, arg))
316: return entry;
317: break;
318: case EXTCOMMUNITY_LIST_STANDARD:
319: if (ecommunity_cmp (entry->u.ecom, arg))
320: return entry;
321: break;
322: case COMMUNITY_LIST_EXPANDED:
323: case EXTCOMMUNITY_LIST_EXPANDED:
324: if (strcmp (entry->config, arg) == 0)
325: return entry;
326: break;
327: default:
328: break;
329: }
330: }
331: return NULL;
332: }
1.1.1.2 ! misho 333:
! 334: static char *
! 335: community_str_get (struct community *com, int i)
! 336: {
! 337: int len;
! 338: u_int32_t comval;
! 339: u_int16_t as;
! 340: u_int16_t val;
! 341: char *str;
! 342: char *pnt;
! 343:
! 344: memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
! 345: comval = ntohl (comval);
! 346:
! 347: switch (comval)
! 348: {
! 349: case COMMUNITY_INTERNET:
! 350: len = strlen (" internet");
! 351: break;
! 352: case COMMUNITY_NO_EXPORT:
! 353: len = strlen (" no-export");
! 354: break;
! 355: case COMMUNITY_NO_ADVERTISE:
! 356: len = strlen (" no-advertise");
! 357: break;
! 358: case COMMUNITY_LOCAL_AS:
! 359: len = strlen (" local-AS");
! 360: break;
! 361: default:
! 362: len = strlen (" 65536:65535");
! 363: break;
! 364: }
! 365:
! 366: /* Allocate memory. */
! 367: str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len);
! 368:
! 369: switch (comval)
! 370: {
! 371: case COMMUNITY_INTERNET:
! 372: strcpy (pnt, "internet");
! 373: pnt += strlen ("internet");
! 374: break;
! 375: case COMMUNITY_NO_EXPORT:
! 376: strcpy (pnt, "no-export");
! 377: pnt += strlen ("no-export");
! 378: break;
! 379: case COMMUNITY_NO_ADVERTISE:
! 380: strcpy (pnt, "no-advertise");
! 381: pnt += strlen ("no-advertise");
! 382: break;
! 383: case COMMUNITY_LOCAL_AS:
! 384: strcpy (pnt, "local-AS");
! 385: pnt += strlen ("local-AS");
! 386: break;
! 387: default:
! 388: as = (comval >> 16) & 0xFFFF;
! 389: val = comval & 0xFFFF;
! 390: sprintf (pnt, "%u:%d", as, val);
! 391: pnt += strlen (pnt);
! 392: break;
! 393: }
! 394:
! 395: *pnt = '\0';
! 396:
! 397: return str;
! 398: }
! 399:
! 400: /* Internal function to perform regular expression match for
! 401: * * a single community. */
! 402: static int
! 403: community_regexp_include (regex_t * reg, struct community *com, int i)
! 404: {
! 405: const char *str;
! 406:
! 407: /* When there is no communities attribute it is treated as empty
! 408: * string. */
! 409: if (com == NULL || com->size == 0)
! 410: str = "";
! 411: else
! 412: str = community_str_get (com, i);
! 413:
! 414: /* Regular expression match. */
! 415: if (regexec (reg, str, 0, NULL, 0) == 0)
! 416: return 1;
! 417:
! 418: /* No match. */
! 419: return 0;
! 420: }
! 421:
1.1 misho 422: /* Internal function to perform regular expression match for community
423: attribute. */
424: static int
425: community_regexp_match (struct community *com, regex_t * reg)
426: {
427: const char *str;
428:
429: /* When there is no communities attribute it is treated as empty
430: string. */
431: if (com == NULL || com->size == 0)
432: str = "";
433: else
434: str = community_str (com);
435:
436: /* Regular expression match. */
437: if (regexec (reg, str, 0, NULL, 0) == 0)
438: return 1;
439:
440: /* No match. */
441: return 0;
442: }
443:
444: static int
445: ecommunity_regexp_match (struct ecommunity *ecom, regex_t * reg)
446: {
447: const char *str;
448:
449: /* When there is no communities attribute it is treated as empty
450: string. */
451: if (ecom == NULL || ecom->size == 0)
452: str = "";
453: else
454: str = ecommunity_str (ecom);
455:
456: /* Regular expression match. */
457: if (regexec (reg, str, 0, NULL, 0) == 0)
458: return 1;
459:
460: /* No match. */
461: return 0;
462: }
463:
464: /* When given community attribute matches to the community-list return
465: 1 else return 0. */
466: int
467: community_list_match (struct community *com, struct community_list *list)
468: {
469: struct community_entry *entry;
470:
471: for (entry = list->head; entry; entry = entry->next)
472: {
473: if (entry->any)
474: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
475:
476: if (entry->style == COMMUNITY_LIST_STANDARD)
477: {
478: if (community_include (entry->u.com, COMMUNITY_INTERNET))
479: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
480:
481: if (community_match (com, entry->u.com))
482: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
483: }
484: else if (entry->style == COMMUNITY_LIST_EXPANDED)
485: {
486: if (community_regexp_match (com, entry->reg))
487: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
488: }
489: }
490: return 0;
491: }
492:
493: int
494: ecommunity_list_match (struct ecommunity *ecom, struct community_list *list)
495: {
496: struct community_entry *entry;
497:
498: for (entry = list->head; entry; entry = entry->next)
499: {
500: if (entry->any)
501: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
502:
503: if (entry->style == EXTCOMMUNITY_LIST_STANDARD)
504: {
505: if (ecommunity_match (ecom, entry->u.ecom))
506: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
507: }
508: else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED)
509: {
510: if (ecommunity_regexp_match (ecom, entry->reg))
511: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
512: }
513: }
514: return 0;
515: }
516:
517: /* Perform exact matching. In case of expanded community-list, do
518: same thing as community_list_match(). */
519: int
520: community_list_exact_match (struct community *com,
521: struct community_list *list)
522: {
523: struct community_entry *entry;
524:
525: for (entry = list->head; entry; entry = entry->next)
526: {
527: if (entry->any)
528: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
529:
530: if (entry->style == COMMUNITY_LIST_STANDARD)
531: {
532: if (community_include (entry->u.com, COMMUNITY_INTERNET))
533: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
534:
535: if (community_cmp (com, entry->u.com))
536: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
537: }
538: else if (entry->style == COMMUNITY_LIST_EXPANDED)
539: {
540: if (community_regexp_match (com, entry->reg))
541: return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
542: }
543: }
544: return 0;
545: }
546:
547: /* Delete all permitted communities in the list from com. */
548: struct community *
549: community_list_match_delete (struct community *com,
550: struct community_list *list)
551: {
552: struct community_entry *entry;
1.1.1.2 ! misho 553: u_int32_t val;
! 554: u_int32_t com_index_to_delete[com->size];
! 555: int delete_index = 0;
! 556: int i;
1.1 misho 557:
1.1.1.2 ! misho 558: /* Loop over each community value and evaluate each against the
! 559: * community-list. If we need to delete a community value add its index to
! 560: * com_index_to_delete.
! 561: */
! 562: for (i = 0; i < com->size; i++)
1.1 misho 563: {
1.1.1.2 ! misho 564: val = community_val_get (com, i);
! 565:
! 566: for (entry = list->head; entry; entry = entry->next)
1.1 misho 567: {
1.1.1.2 ! misho 568: if (entry->any)
1.1 misho 569: {
1.1.1.2 ! misho 570: if (entry->direct == COMMUNITY_PERMIT)
! 571: {
! 572: com_index_to_delete[delete_index] = i;
! 573: delete_index++;
! 574: }
! 575: break;
1.1 misho 576: }
577:
1.1.1.2 ! misho 578: else if ((entry->style == COMMUNITY_LIST_STANDARD)
! 579: && (community_include (entry->u.com, COMMUNITY_INTERNET)
! 580: || community_include (entry->u.com, val) ))
! 581: {
1.1 misho 582: if (entry->direct == COMMUNITY_PERMIT)
1.1.1.2 ! misho 583: {
! 584: com_index_to_delete[delete_index] = i;
! 585: delete_index++;
! 586: }
! 587: break;
! 588: }
! 589:
! 590: else if ((entry->style == COMMUNITY_LIST_EXPANDED)
! 591: && community_regexp_include (entry->reg, com, i))
! 592: {
! 593: if (entry->direct == COMMUNITY_PERMIT)
! 594: {
! 595: com_index_to_delete[delete_index] = i;
! 596: delete_index++;
! 597: }
! 598: break;
! 599: }
! 600: }
! 601: }
! 602:
! 603: /* Delete all of the communities we flagged for deletion */
! 604: for (i = delete_index-1; i >= 0; i--)
! 605: {
! 606: val = community_val_get (com, com_index_to_delete[i]);
! 607: community_del_val (com, &val);
1.1 misho 608: }
1.1.1.2 ! misho 609:
1.1 misho 610: return com;
611: }
612:
613: /* To avoid duplicated entry in the community-list, this function
614: compares specified entry to existing entry. */
615: static int
616: community_list_dup_check (struct community_list *list,
617: struct community_entry *new)
618: {
619: struct community_entry *entry;
620:
621: for (entry = list->head; entry; entry = entry->next)
622: {
623: if (entry->style != new->style)
624: continue;
625:
626: if (entry->direct != new->direct)
627: continue;
628:
629: if (entry->any != new->any)
630: continue;
631:
632: if (entry->any)
633: return 1;
634:
635: switch (entry->style)
636: {
637: case COMMUNITY_LIST_STANDARD:
638: if (community_cmp (entry->u.com, new->u.com))
639: return 1;
640: break;
641: case EXTCOMMUNITY_LIST_STANDARD:
642: if (ecommunity_cmp (entry->u.ecom, new->u.ecom))
643: return 1;
644: break;
645: case COMMUNITY_LIST_EXPANDED:
646: case EXTCOMMUNITY_LIST_EXPANDED:
647: if (strcmp (entry->config, new->config) == 0)
648: return 1;
649: break;
650: default:
651: break;
652: }
653: }
654: return 0;
655: }
1.1.1.2 ! misho 656:
1.1 misho 657: /* Set community-list. */
658: int
659: community_list_set (struct community_list_handler *ch,
660: const char *name, const char *str, int direct, int style)
661: {
662: struct community_entry *entry = NULL;
663: struct community_list *list;
664: struct community *com = NULL;
665: regex_t *regex = NULL;
666:
667: /* Get community list. */
668: list = community_list_get (ch, name, COMMUNITY_LIST_MASTER);
669:
670: /* When community-list already has entry, new entry should have same
671: style. If you want to have mixed style community-list, you can
672: comment out this check. */
673: if (!community_list_empty_p (list))
674: {
675: struct community_entry *first;
676:
677: first = list->head;
678:
679: if (style != first->style)
680: {
681: return (first->style == COMMUNITY_LIST_STANDARD
682: ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
683: : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
684: }
685: }
686:
687: if (str)
688: {
689: if (style == COMMUNITY_LIST_STANDARD)
690: com = community_str2com (str);
691: else
692: regex = bgp_regcomp (str);
693:
694: if (! com && ! regex)
695: return COMMUNITY_LIST_ERR_MALFORMED_VAL;
696: }
697:
698: entry = community_entry_new ();
699: entry->direct = direct;
700: entry->style = style;
701: entry->any = (str ? 0 : 1);
702: entry->u.com = com;
703: entry->reg = regex;
704: entry->config = (regex ? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL);
705:
706: /* Do not put duplicated community entry. */
707: if (community_list_dup_check (list, entry))
708: community_entry_free (entry);
709: else
710: community_list_entry_add (list, entry);
711:
712: return 0;
713: }
714:
715: /* Unset community-list. When str is NULL, delete all of
716: community-list entry belongs to the specified name. */
717: int
718: community_list_unset (struct community_list_handler *ch,
719: const char *name, const char *str,
720: int direct, int style)
721: {
722: struct community_entry *entry = NULL;
723: struct community_list *list;
724: struct community *com = NULL;
725: regex_t *regex = NULL;
726:
727: /* Lookup community list. */
728: list = community_list_lookup (ch, name, COMMUNITY_LIST_MASTER);
729: if (list == NULL)
730: return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
731:
732: /* Delete all of entry belongs to this community-list. */
733: if (!str)
734: {
735: community_list_delete (list);
736: return 0;
737: }
738:
739: if (style == COMMUNITY_LIST_STANDARD)
740: com = community_str2com (str);
741: else
742: regex = bgp_regcomp (str);
743:
744: if (! com && ! regex)
745: return COMMUNITY_LIST_ERR_MALFORMED_VAL;
746:
747: if (com)
748: entry = community_list_entry_lookup (list, com, direct);
749: else
750: entry = community_list_entry_lookup (list, str, direct);
751:
752: if (com)
753: community_free (com);
754: if (regex)
755: bgp_regex_free (regex);
756:
757: if (!entry)
758: return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
759:
760: community_list_entry_delete (list, entry, style);
761:
762: return 0;
763: }
764:
765: /* Set extcommunity-list. */
766: int
767: extcommunity_list_set (struct community_list_handler *ch,
768: const char *name, const char *str,
769: int direct, int style)
770: {
771: struct community_entry *entry = NULL;
772: struct community_list *list;
773: struct ecommunity *ecom = NULL;
774: regex_t *regex = NULL;
775:
776: entry = NULL;
777:
778: /* Get community list. */
779: list = community_list_get (ch, name, EXTCOMMUNITY_LIST_MASTER);
780:
781: /* When community-list already has entry, new entry should have same
782: style. If you want to have mixed style community-list, you can
783: comment out this check. */
784: if (!community_list_empty_p (list))
785: {
786: struct community_entry *first;
787:
788: first = list->head;
789:
790: if (style != first->style)
791: {
792: return (first->style == EXTCOMMUNITY_LIST_STANDARD
793: ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
794: : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
795: }
796: }
797:
798: if (str)
799: {
800: if (style == EXTCOMMUNITY_LIST_STANDARD)
801: ecom = ecommunity_str2com (str, 0, 1);
802: else
803: regex = bgp_regcomp (str);
804:
805: if (! ecom && ! regex)
806: return COMMUNITY_LIST_ERR_MALFORMED_VAL;
807: }
808:
809: if (ecom)
810: ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
811:
812: entry = community_entry_new ();
813: entry->direct = direct;
814: entry->style = style;
815: entry->any = (str ? 0 : 1);
816: if (ecom)
817: entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST);
818: else if (regex)
819: entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str);
820: else
821: entry->config = NULL;
822: entry->u.ecom = ecom;
823: entry->reg = regex;
824:
825: /* Do not put duplicated community entry. */
826: if (community_list_dup_check (list, entry))
827: community_entry_free (entry);
828: else
829: community_list_entry_add (list, entry);
830:
831: return 0;
832: }
833:
834: /* Unset extcommunity-list. When str is NULL, delete all of
835: extcommunity-list entry belongs to the specified name. */
836: int
837: extcommunity_list_unset (struct community_list_handler *ch,
838: const char *name, const char *str,
839: int direct, int style)
840: {
841: struct community_entry *entry = NULL;
842: struct community_list *list;
843: struct ecommunity *ecom = NULL;
844: regex_t *regex = NULL;
845:
846: /* Lookup extcommunity list. */
847: list = community_list_lookup (ch, name, EXTCOMMUNITY_LIST_MASTER);
848: if (list == NULL)
849: return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
850:
851: /* Delete all of entry belongs to this extcommunity-list. */
852: if (!str)
853: {
854: community_list_delete (list);
855: return 0;
856: }
857:
858: if (style == EXTCOMMUNITY_LIST_STANDARD)
859: ecom = ecommunity_str2com (str, 0, 1);
860: else
861: regex = bgp_regcomp (str);
862:
863: if (! ecom && ! regex)
864: return COMMUNITY_LIST_ERR_MALFORMED_VAL;
865:
866: if (ecom)
867: entry = community_list_entry_lookup (list, ecom, direct);
868: else
869: entry = community_list_entry_lookup (list, str, direct);
870:
871: if (ecom)
872: ecommunity_free (&ecom);
873: if (regex)
874: bgp_regex_free (regex);
875:
876: if (!entry)
877: return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
878:
879: community_list_entry_delete (list, entry, style);
880:
881: return 0;
882: }
883:
884: /* Initializa community-list. Return community-list handler. */
885: struct community_list_handler *
886: community_list_init (void)
887: {
888: struct community_list_handler *ch;
889: ch = XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER,
890: sizeof (struct community_list_handler));
891: return ch;
892: }
893:
894: /* Terminate community-list. */
895: void
896: community_list_terminate (struct community_list_handler *ch)
897: {
898: struct community_list_master *cm;
899: struct community_list *list;
900:
901: cm = &ch->community_list;
902: while ((list = cm->num.head) != NULL)
903: community_list_delete (list);
904: while ((list = cm->str.head) != NULL)
905: community_list_delete (list);
906:
907: cm = &ch->extcommunity_list;
908: while ((list = cm->num.head) != NULL)
909: community_list_delete (list);
910: while ((list = cm->str.head) != NULL)
911: community_list_delete (list);
912:
913: XFREE (MTYPE_COMMUNITY_LIST_HANDLER, ch);
914: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>