bgp_clist.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:20k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* BGP community-list and extcommunity-list.
  2.    Copyright (C) 1999 Kunihiro Ishiguro
  3. This file is part of GNU Zebra.
  4. GNU Zebra is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GNU Zebra is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Zebra; see the file COPYING.  If not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.  */
  16. #include <zebra.h>
  17. #include "command.h"
  18. #include "prefix.h"
  19. #include "memory.h"
  20. #include "bgpd/bgpd.h"
  21. #include "bgpd/bgp_community.h"
  22. #include "bgpd/bgp_ecommunity.h"
  23. #include "bgpd/bgp_aspath.h"
  24. #include "bgpd/bgp_regex.h"
  25. #include "bgpd/bgp_clist.h"
  26. /* Lookup master structure for community-list or
  27.    extcommunity-list.  */
  28. struct community_list_master *
  29. community_list_master_lookup (struct community_list_handler *ch, int master)
  30. {
  31.   if (ch)
  32.     switch (master)
  33.       {
  34.       case COMMUNITY_LIST_MASTER:
  35. return &ch->community_list;
  36. break;
  37.       case EXTCOMMUNITY_LIST_MASTER:
  38. return &ch->extcommunity_list;
  39.       }
  40.   return NULL;
  41. }
  42. /* Allocate a new community list entry.  */
  43. struct community_entry *
  44. community_entry_new ()
  45. {
  46.   struct community_entry *new;
  47.   new = XMALLOC (MTYPE_COMMUNITY_LIST_ENTRY, sizeof (struct community_entry));
  48.   memset (new, 0, sizeof (struct community_entry));
  49.   return new;
  50. }
  51. /* Free community list entry.  */
  52. void
  53. community_entry_free (struct community_entry *entry)
  54. {
  55.   switch (entry->style)
  56.     {
  57.     case COMMUNITY_LIST_STANDARD:
  58.       if (entry->u.com)
  59. community_free (entry->u.com);
  60.       break;
  61.     case EXTCOMMUNITY_LIST_STANDARD:
  62.       /* In case of standard extcommunity-list, configuration string
  63.  is made by ecommunity_ecom2str().  */
  64.       if (entry->config)
  65. XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
  66.       if (entry->u.ecom)
  67. ecommunity_free (entry->u.ecom);
  68.       break;
  69.     case COMMUNITY_LIST_EXPANDED:
  70.     case EXTCOMMUNITY_LIST_EXPANDED:
  71.       if (entry->config)
  72. XFREE (MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
  73.       if (entry->reg)
  74. bgp_regex_free (entry->reg);
  75.     default:
  76.       break;
  77.     }
  78.   XFREE (MTYPE_COMMUNITY_LIST_ENTRY, entry);
  79. }
  80. /* Allocate a new community-list.  */
  81. struct community_list *
  82. community_list_new ()
  83. {
  84.   struct community_list *new;
  85.   new = XMALLOC (MTYPE_COMMUNITY_LIST, sizeof (struct community_list));
  86.   memset (new, 0, sizeof (struct community_list));
  87.   return new;
  88. }
  89. /* Free community-list.  */
  90. void
  91. community_list_free (struct community_list *list)
  92. {
  93.   if (list->name)
  94.     XFREE (MTYPE_COMMUNITY_LIST_NAME, list->name);
  95.   XFREE (MTYPE_COMMUNITY_LIST, list);
  96. }
  97. struct community_list *
  98. community_list_insert (struct community_list_handler *ch,
  99.        char *name, int master)
  100. {
  101.   int i;
  102.   long number;
  103.   struct community_list *new;
  104.   struct community_list *point;
  105.   struct community_list_list *list;
  106.   struct community_list_master *cm;
  107.   /* Lookup community-list master.  */
  108.   cm = community_list_master_lookup (ch, master);
  109.   if (! cm)
  110.     return NULL;
  111.   /* Allocate new community_list and copy given name. */
  112.   new = community_list_new ();
  113.   new->name = XSTRDUP (MTYPE_COMMUNITY_LIST_NAME, name);
  114.   /* If name is made by all digit character.  We treat it as
  115.      number. */
  116.   for (number = 0, i = 0; i < strlen (name); i++)
  117.     {
  118.       if (isdigit ((int) name[i]))
  119. number = (number * 10) + (name[i] - '0');
  120.       else
  121. break;
  122.     }
  123.   /* In case of name is all digit character */
  124.   if (i == strlen (name))
  125.     {
  126.       new->sort = COMMUNITY_LIST_NUMBER;
  127.       /* Set access_list to number list. */
  128.       list = &cm->num;
  129.       for (point = list->head; point; point = point->next)
  130. if (atol (point->name) >= number)
  131.   break;
  132.     }
  133.   else
  134.     {
  135.       new->sort = COMMUNITY_LIST_STRING;
  136.       /* Set access_list to string list. */
  137.       list = &cm->str;
  138.   
  139.       /* Set point to insertion point. */
  140.       for (point = list->head; point; point = point->next)
  141. if (strcmp (point->name, name) >= 0)
  142.   break;
  143.     }
  144.   /* Link to upper list.  */
  145.   new->parent = list;
  146.   /* In case of this is the first element of master. */
  147.   if (list->head == NULL)
  148.     {
  149.       list->head = list->tail = new;
  150.       return new;
  151.     }
  152.   /* In case of insertion is made at the tail of access_list. */
  153.   if (point == NULL)
  154.     {
  155.       new->prev = list->tail;
  156.       list->tail->next = new;
  157.       list->tail = new;
  158.       return new;
  159.     }
  160.   /* In case of insertion is made at the head of access_list. */
  161.   if (point == list->head)
  162.     {
  163.       new->next = list->head;
  164.       list->head->prev = new;
  165.       list->head = new;
  166.       return new;
  167.     }
  168.   /* Insertion is made at middle of the access_list. */
  169.   new->next = point;
  170.   new->prev = point->prev;
  171.   if (point->prev)
  172.     point->prev->next = new;
  173.   point->prev = new;
  174.   return new;
  175. }
  176. struct community_list *
  177. community_list_lookup (struct community_list_handler *ch,
  178.        char *name, int master)
  179. {
  180.   struct community_list *list;
  181.   struct community_list_master *cm;
  182.   if (! name)
  183.     return NULL;
  184.   cm = community_list_master_lookup (ch, master);
  185.   if (! cm)
  186.     return NULL;
  187.   for (list = cm->num.head; list; list = list->next)
  188.     if (strcmp (list->name, name) == 0)
  189.       return list;
  190.   for (list = cm->str.head; list; list = list->next)
  191.     if (strcmp (list->name, name) == 0)
  192.       return list;
  193.   return NULL;
  194. }
  195. struct community_list *
  196. community_list_get (struct community_list_handler *ch, char *name, int master)
  197. {
  198.   struct community_list *list;
  199.   list = community_list_lookup (ch, name, master);
  200.   if (! list)
  201.     list = community_list_insert (ch, name, master);
  202.   return list;
  203. }
  204. void
  205. community_list_delete (struct community_list *list)
  206. {
  207.   struct community_list_list *clist;
  208.   struct community_entry *entry, *next;
  209.   for (entry = list->head; entry; entry = next)
  210.     {
  211.       next = entry->next;
  212.       community_entry_free (entry);
  213.     }
  214.   clist = list->parent;
  215.   if (list->next)
  216.     list->next->prev = list->prev;
  217.   else
  218.     clist->tail = list->prev;
  219.   if (list->prev)
  220.     list->prev->next = list->next;
  221.   else
  222.     clist->head = list->next;
  223.   community_list_free (list);
  224. }
  225. int
  226. community_list_empty_p (struct community_list *list)
  227. {
  228.   return (list->head == NULL && list->tail == NULL) ? 1 : 0;
  229. }
  230. /* Add community-list entry to the list.  */
  231. static void
  232. community_list_entry_add (struct community_list *list, 
  233.   struct community_entry *entry)
  234. {
  235.   entry->next = NULL;
  236.   entry->prev = list->tail;
  237.   if (list->tail)
  238.     list->tail->next = entry;
  239.   else
  240.     list->head = entry;
  241.   list->tail = entry;
  242. }
  243. /* Delete community-list entry from the list.  */
  244. static void
  245. community_list_entry_delete (struct community_list *list,
  246.      struct community_entry *entry, int style)
  247. {
  248.   if (entry->next)
  249.     entry->next->prev = entry->prev;
  250.   else
  251.     list->tail = entry->prev;
  252.   if (entry->prev)
  253.     entry->prev->next = entry->next;
  254.   else
  255.     list->head = entry->next;
  256.   community_entry_free (entry);
  257.   if (community_list_empty_p (list))
  258.     community_list_delete (list);
  259. }
  260. /* Lookup community-list entry from the list.  */
  261. static struct community_entry *
  262. community_list_entry_lookup (struct community_list *list, void *arg,
  263.      int direct)
  264. {
  265.   struct community_entry *entry;
  266.   for (entry = list->head; entry; entry = entry->next)
  267.     {
  268.       switch (entry->style)
  269. {
  270. case COMMUNITY_LIST_STANDARD:
  271.   if (community_cmp (entry->u.com, arg))
  272.     return entry;
  273.   break;
  274. case EXTCOMMUNITY_LIST_STANDARD:
  275.   if (ecommunity_cmp (entry->u.ecom, arg))
  276.     return entry;
  277.   break;
  278. case COMMUNITY_LIST_EXPANDED:
  279. case EXTCOMMUNITY_LIST_EXPANDED:
  280.   if (strcmp (entry->config, arg) == 0)
  281.     return entry;
  282.   break;
  283. default:
  284.   break;
  285. }
  286.     }
  287.   return NULL;
  288. }
  289. /* Internal function to perform regular expression match for community
  290.    attribute.  */
  291. static int
  292. community_regexp_match (struct community *com, regex_t *reg)
  293. {
  294.   char *str;
  295.   /* When there is no communities attribute it is treated as empty
  296.      string.  */
  297.   if (com == NULL || com->size == 0)
  298.     str = "";
  299.   else
  300.     str = community_str (com);
  301.   /* Regular expression match.  */
  302.   if (regexec (reg, str, 0, NULL, 0) == 0)
  303.     return 1;
  304.   /* No match.  */
  305.   return 0;
  306. }
  307. static int
  308. ecommunity_regexp_match (struct ecommunity *ecom, regex_t *reg)
  309. {
  310.   char *str;
  311.   /* When there is no communities attribute it is treated as empty
  312.      string.  */
  313.   if (ecom == NULL || ecom->size == 0)
  314.     str = "";
  315.   else
  316.     str = ecommunity_str (ecom);
  317.   /* Regular expression match.  */
  318.   if (regexec (reg, str, 0, NULL, 0) == 0)
  319.     return 1;
  320.   /* No match.  */
  321.   return 0;
  322. }
  323. /* When given community attribute matches to the community-list return
  324.    1 else return 0.  */
  325. int
  326. community_list_match (struct community *com, struct community_list *list)
  327. {
  328.   struct community_entry *entry;
  329.   for (entry = list->head; entry; entry = entry->next)
  330.     {
  331.       if (entry->any)
  332. return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  333.       if (entry->style == COMMUNITY_LIST_STANDARD)
  334. {
  335.   if (community_include (entry->u.com, COMMUNITY_INTERNET))
  336.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  337.   if (community_match (com, entry->u.com))
  338.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  339. }
  340.       else if (entry->style == COMMUNITY_LIST_EXPANDED)
  341. {
  342.   if (community_regexp_match (com, entry->reg))
  343.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  344. }
  345.     }
  346.   return 0;
  347. }
  348. int
  349. ecommunity_list_match (struct ecommunity *ecom, struct community_list *list)
  350. {
  351.   struct community_entry *entry;
  352.   for (entry = list->head; entry; entry = entry->next)
  353.     {
  354.       if (entry->any)
  355. return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  356.       if (entry->style == EXTCOMMUNITY_LIST_STANDARD)
  357. {
  358.   if (ecommunity_match (ecom, entry->u.ecom))
  359.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  360. }
  361.       else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED)
  362. {
  363.   if (ecommunity_regexp_match (ecom, entry->reg))
  364.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  365. }
  366.     }
  367.   return 0;
  368. }
  369. /* Perform exact matching.  In case of expanded community-list, do
  370.    same thing as community_list_match().  */
  371. int
  372. community_list_exact_match (struct community *com, struct community_list *list)
  373. {
  374.   struct community_entry *entry;
  375.   for (entry = list->head; entry; entry = entry->next)
  376.     {
  377.       if (entry->any)
  378. return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  379.       if (entry->style == COMMUNITY_LIST_STANDARD)
  380. {
  381.   if (community_include (entry->u.com, COMMUNITY_INTERNET))
  382.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  383.   if (community_cmp (com, entry->u.com))
  384.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  385. }
  386.       else if (entry->style == COMMUNITY_LIST_EXPANDED)
  387. {
  388.   if (community_regexp_match (com, entry->reg))
  389.     return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
  390. }
  391.     }
  392.   return 0;
  393. }
  394. /* Do regular expression matching with single community val.  */
  395. static int
  396. comval_regexp_match (u_int32_t comval, regex_t *reg)
  397. {
  398.   /* Maximum is "65535:65535" + ''. */
  399.   char c[12];
  400.   char *str;
  401.   switch (comval)
  402.     {
  403.     case COMMUNITY_INTERNET:
  404.       str = "internet";
  405.       break;
  406.     case COMMUNITY_NO_EXPORT:
  407.       str = "no-export";
  408.       break;
  409.     case COMMUNITY_NO_ADVERTISE:
  410.       str = "no-advertise";
  411.       break;
  412.     case COMMUNITY_LOCAL_AS:
  413.       str = "local-AS";
  414.       break;
  415.     default:
  416.       snprintf (c, sizeof c,
  417. "%d:%d", (comval >> 16) & 0xFFFF, comval & 0xFFFF);
  418.       str = c;
  419.       break;
  420.     }
  421.   if (regexec (reg, str, 0, NULL, 0) == 0)
  422.     return 1;
  423.   
  424.   return 0;
  425. }
  426. /* Delete all permitted communities in the list from com.  */
  427. struct community *
  428. community_list_match_delete (struct community *com,
  429.                              struct community_list *clist)
  430. {
  431.   int i;
  432.   u_int32_t comval;
  433.   struct community *merge;
  434.   struct community_entry *entry;
  435.   /* Empty community value check.  */
  436.   if (! com)
  437.     return NULL;
  438.   /* Duplicate communities value.  */
  439.   merge = community_dup (com);
  440.   /* For each communities value, we have to check each
  441.      community-list.  */
  442.   for (i = 0; i < com->size; i ++)
  443.     {
  444.       /* Get one communities value.  */
  445.       memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
  446.       comval = ntohl (comval);
  447.       /* Loop community-list.  */
  448.       for (entry = clist->head; entry; entry = entry->next)
  449. {
  450.   /* Various match condition check.  */
  451.   if (entry->any
  452.       || (entry->style == COMMUNITY_LIST_STANDARD
  453.   && entry->u.com
  454.   && community_include (entry->u.com, comval))
  455.       || (entry->style == COMMUNITY_LIST_EXPANDED
  456.   && entry->reg
  457.   && comval_regexp_match (comval, entry->reg)))
  458.     {
  459.       /* If the rule is "permit", delete this community value. */
  460.       if (entry->direct == COMMUNITY_PERMIT)
  461. community_del_val (merge, com_nthval (com, i));
  462.       /* Exit community-list loop, goto next communities
  463.  value.  */
  464.       break;
  465.     }
  466.         }   
  467.     }
  468.   return merge;
  469. }
  470. /* To avoid duplicated entry in the community-list, this function
  471.    compares specified entry to existing entry.  */
  472. int
  473. community_list_dup_check (struct community_list *list, 
  474.   struct community_entry *new)
  475. {
  476.   struct community_entry *entry;
  477.   
  478.   for (entry = list->head; entry; entry = entry->next)
  479.     {
  480.       if (entry->style != new->style)
  481. continue;
  482.       if (entry->direct != new->direct)
  483. continue;
  484.       if (entry->any != new->any)
  485. continue;
  486.       if (entry->any)
  487. return 1;
  488.       switch (entry->style)
  489. {
  490. case COMMUNITY_LIST_STANDARD:
  491.   if (community_cmp (entry->u.com, new->u.com))
  492.     return 1;
  493.   break;
  494. case EXTCOMMUNITY_LIST_STANDARD:
  495.   if (ecommunity_cmp (entry->u.ecom, new->u.ecom))
  496.     return 1;
  497.   break;
  498. case COMMUNITY_LIST_EXPANDED:
  499. case EXTCOMMUNITY_LIST_EXPANDED:
  500.   if (strcmp (entry->config, new->config) == 0)
  501.     return 1;
  502.   break;
  503. default:
  504.   break;
  505. }
  506.     }
  507.   return 0;
  508. }
  509. /* Set community-list.  */
  510. int
  511. community_list_set (struct community_list_handler *ch,
  512.     char *name, char *str, int direct, int style)
  513. {
  514.   struct community_entry *entry = NULL;
  515.   struct community_list *list;
  516.   struct community *com = NULL;
  517.   regex_t *regex = NULL;
  518.   /* Get community list. */
  519.   list = community_list_get (ch, name, COMMUNITY_LIST_MASTER);
  520.   /* When community-list already has entry, new entry should have same
  521.      style.  If you want to have mixed style community-list, you can
  522.      comment out this check.  */
  523.   if (! community_list_empty_p (list))
  524.     {
  525.       struct community_entry *first;
  526.       first = list->head;
  527.       if (style != first->style)
  528. {
  529.   return (first->style == COMMUNITY_LIST_STANDARD
  530.   ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
  531.   : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
  532. }
  533.     }
  534.   if (str)
  535.     {
  536.       if (style == COMMUNITY_LIST_STANDARD)
  537. com = community_str2com (str);
  538.       else
  539. regex = bgp_regcomp (str);
  540.       if (! com && ! regex)
  541. return COMMUNITY_LIST_ERR_MALFORMED_VAL;
  542.     }
  543.   entry = community_entry_new ();
  544.   entry->direct = direct;
  545.   entry->style = style;
  546.   entry->any = (str ? 0 : 1);
  547.   entry->u.com = com;
  548.   entry->reg = regex;
  549.   entry->config = (regex ? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL);
  550.   /* Do not put duplicated community entry.  */
  551.   if (community_list_dup_check (list, entry))
  552.     community_entry_free (entry);
  553.   else
  554.     community_list_entry_add (list, entry);
  555.   return 0;
  556. }
  557. /* Unset community-list.  When str is NULL, delete all of
  558.    community-list entry belongs to the specified name.  */
  559. int
  560. community_list_unset (struct community_list_handler *ch,
  561.       char *name, char *str, int direct, int style)
  562. {
  563.   struct community_entry *entry = NULL;
  564.   struct community_list *list;
  565.   struct community *com = NULL;
  566.   regex_t *regex = NULL;
  567.   /* Lookup community list.  */
  568.   list = community_list_lookup (ch, name, COMMUNITY_LIST_MASTER);
  569.   if (list == NULL)
  570.     return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
  571.   /* Delete all of entry belongs to this community-list.  */
  572.   if (! str)
  573.     {
  574.       community_list_delete (list);
  575.       return 0;
  576.     }
  577.   if (style == COMMUNITY_LIST_STANDARD)
  578.     com = community_str2com (str);
  579.   else
  580.     regex = bgp_regcomp (str);
  581.   if (! com && ! regex)
  582.     return COMMUNITY_LIST_ERR_MALFORMED_VAL;
  583.   if (com)
  584.     entry = community_list_entry_lookup (list, com, direct);
  585.   else
  586.     entry = community_list_entry_lookup (list, str, direct);
  587.   if (com)
  588.     community_free (com);
  589.   if (regex)
  590.     bgp_regex_free (regex);
  591.   if (! entry)
  592.     return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
  593.   community_list_entry_delete (list, entry, style);
  594.   return 0;
  595. }
  596. /* Set extcommunity-list.  */
  597. int
  598. extcommunity_list_set (struct community_list_handler *ch,
  599.        char *name, char *str, int direct, int style)
  600. {
  601.   struct community_entry *entry = NULL;
  602.   struct community_list *list;
  603.   struct ecommunity *ecom = NULL;
  604.   regex_t *regex = NULL;
  605.   entry = NULL;
  606.   /* Get community list. */
  607.   list = community_list_get (ch, name, EXTCOMMUNITY_LIST_MASTER);
  608.   /* When community-list already has entry, new entry should have same
  609.      style.  If you want to have mixed style community-list, you can
  610.      comment out this check.  */
  611.   if (! community_list_empty_p (list))
  612.     {
  613.       struct community_entry *first;
  614.       first = list->head;
  615.       if (style != first->style)
  616. {
  617.   return (first->style == EXTCOMMUNITY_LIST_STANDARD
  618.   ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
  619.   : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
  620. }
  621.     }
  622.   if (str)
  623.     {
  624.       if (style == EXTCOMMUNITY_LIST_STANDARD)
  625. ecom = ecommunity_str2com (str, 0, 1);
  626.       else
  627. regex = bgp_regcomp (str);
  628.       if (! ecom && ! regex)
  629. return COMMUNITY_LIST_ERR_MALFORMED_VAL;
  630.     }
  631.   if (ecom)
  632.     ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
  633.   entry = community_entry_new ();
  634.   entry->direct = direct;
  635.   entry->style = style;
  636.   entry->any = (str ? 0 : 1);
  637.   if (ecom)
  638.     entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_CONFIG);
  639.   else if (regex)
  640.     entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str);
  641.   else
  642.     entry->config = NULL;
  643.   entry->u.ecom = ecom;
  644.   entry->reg = regex;
  645.   /* Do not put duplicated community entry.  */
  646.   if (community_list_dup_check (list, entry))
  647.     community_entry_free (entry);
  648.   else
  649.     community_list_entry_add (list, entry);
  650.   return 0;
  651. }
  652. /* Unset extcommunity-list.  When str is NULL, delete all of
  653.    extcommunity-list entry belongs to the specified name.  */
  654. int
  655. extcommunity_list_unset (struct community_list_handler *ch,
  656.  char *name, char *str, int direct, int style)
  657. {
  658.   struct community_entry *entry = NULL;
  659.   struct community_list *list;
  660.   struct ecommunity *ecom = NULL;
  661.   regex_t *regex = NULL;
  662.   /* Lookup extcommunity list.  */
  663.   list = community_list_lookup (ch, name, EXTCOMMUNITY_LIST_MASTER);
  664.   if (list == NULL)
  665.     return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
  666.   /* Delete all of entry belongs to this extcommunity-list.  */
  667.   if (! str)
  668.     {
  669.       community_list_delete (list);
  670.       return 0;
  671.     }
  672.   if (style == EXTCOMMUNITY_LIST_STANDARD)
  673.     ecom = ecommunity_str2com (str, 0, 1);
  674.   else
  675.     regex = bgp_regcomp (str);
  676.   if (! ecom && ! regex)
  677.     return COMMUNITY_LIST_ERR_MALFORMED_VAL;
  678.   if (ecom)
  679.     entry = community_list_entry_lookup (list, ecom, direct);
  680.   else
  681.     entry = community_list_entry_lookup (list, str, direct);
  682.   if (ecom)
  683.     ecommunity_free (ecom);
  684.   if (regex)
  685.     bgp_regex_free (regex);
  686.   if (! entry)
  687.     return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
  688.   community_list_entry_delete (list, entry, style);
  689.   return 0;
  690. }
  691. /* Initializa community-list.  Return community-list handler.  */
  692. struct community_list_handler *
  693. community_list_init ()
  694. {
  695.   struct community_list_handler *ch;
  696.   ch = XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER,
  697. sizeof (struct community_list_handler));
  698.   return ch;
  699. }
  700. /* Terminate community-list.  */
  701. void
  702. community_list_terminate (struct community_list_handler *ch)
  703. {
  704.   struct community_list_master *cm;
  705.   struct community_list *list;
  706.   cm = &ch->community_list;
  707.   while ((list = cm->num.head) != NULL)
  708.     community_list_delete (list);
  709.   while ((list = cm->str.head) != NULL)
  710.     community_list_delete (list);
  711.   cm = &ch->extcommunity_list;
  712.   while ((list = cm->num.head) != NULL)
  713.     community_list_delete (list);
  714.   while ((list = cm->str.head) != NULL)
  715.     community_list_delete (list);
  716.   XFREE (MTYPE_COMMUNITY_LIST_HANDLER, ch);
  717. }